首先分享一个贴吧神贴(滑稽)
74HC595概述
74HC595是一个8位串入并出的移位寄存器,其在proteus中的器件图片如下:
其中各个端口的定义如下表:
| 引脚 | 描述 |
| :----: | :----: |
| SH_CP | 数据输入时钟线 |
| ST_CP | 输出存储器锁存时钟线 |
| /OE | 输出有效(低电平有效) |
| /MR | 主复位(低电平有效) |
| Q0~Q7 | 8位并行输出口 |
| Q7' | 串行数据输出口 |
| DS | 串行数据输入口 |
在SH_CP的上升沿,串行数据由DS输入并由Q7'输出;在ST_CP的上升沿,8位数据存入并行输出缓存器,并在当/OE为低电平时输出。
此为proteus中595的基本功能的概述。
# 将要实现的功能概述
C51单片机与两个595移存器连接,一个595的串行输出口Q7'与另一个595的串行输入口DS相连;C51的IO口发送两个字节的数据,一共有6种组合,所有组合中第一个字节都为0x01,第二个分别为0x00,0x01,0x02,0x03,0x04,0x05,然后让两个595进行接收并通过并行输出口输出这两个字节;数据组合的切换由按键进行。
| | 1 | 2 | 3 | 4 | 5 | 6 |
| :---: | :-: | :-: | :-: | :-: | :-: | :-: |
|第一个字节| 0x01| 0x01| 0x01| 0x01| 0x01| 0x01|
|第二个字节| 0x00| 0x01| 0x02| 0x03| 0x04| 0x05|
proteus器件连接图
- /MR为主复位端口,本次不使用,全置高。
- /OE为控制输出有效端口,将其置为低电平,即所有时候均有效。
- 下方的595的串行输入口DS连接单片机的P1^0端口,上方的595的DS连接下方595的串行输出口Q7’。即意味着上方595最终输出的是第二个字节,下方595最终输出的是第一个字节。
- 按钮一端连接P1\^7口,一端接地,意味着按钮按下,P1^7为低电平。
- 两个595的输出存储器锁存时钟线ST_CP与单片机IO口P3^5相连,且/OE为始终为低,说明单片机控制着两个595的并行输出同时进行。
- 两个595的数据输入时钟线SH_CP与单片机IO口P1^2相连,说明单片机控制着两个595的串行输入同时进行,即使此时上方的串行出入来自于下方的串行输出。
keil C51 程序代码:
头文件以及定义
#include <REG2051.H>
sbit out=P1^0; //串行输出口
sbit rclk=P1^2; //时钟脉冲信号-上升沿有效
sbit sclk=P3^5; //打入信号-上升沿有效
sbit key=P1^7; //按键
unsigned char code table[]={0,0x00,0x01,0x02,0x03,0x04,0x05}; //数组
unsigned char i,aa,bb,flag;
延时函数
void delayms(unsigned char z) //延时函数,delayms(1)延时1ms
{
unsigned char x,y;
for(x=z;x>0;x--);
for(y=110;y>0;y--);
}
输出第一个字节(0x01)函数
void output_0x01() //输出0x01
{
aa=0x01;
for(i=8;i>0;i--)
{
out=aa&0x80; //将最低位取出
aa<<=1; //左移一位
delayms(5); //延时5ms
rclk=0; //clock
rclk=1; //rising edge effective
rclk=0; //重新置低
}
sclk=0; //74HC592 output relase clock
sclk=1; //rising edge effective
sclk=0; //74HC592 output relase clock
}
输出第二个字节(table[])函数
void output_table() //输出数组内的值
{
aa=table[bb];
for(i=8;i>0;i--)
{
out=aa&0x80; //将最低位取出
aa<<=1; //左移一位
delayms(5);
rclk=0; //clock
rclk=1; //rising edge effective
rclk=0;
}
sclk=0; //74HC592 output relase clock
sclk=1; //rising edge effective
sclk=0; //74HC592 output relase clock
}
键盘扫描函数
void keyscan() //键盘扫描函数
{
if(key==0) //按键按下,P1^7口为低电平
{
delayms(10); //按键消抖
if(key==0)
{
while(!key); //松手消抖
if(bb==6) bb=1; //四种情况(0x01,0x02,0x03,0x04)循环
bb++;
flag=1; //标志位置1,作用是有按键按下才能运行两个output函数且运行一次
}
}
}
主函数
void main()
{
while(1) //大循环
{
keyscan(); //键盘扫描函数
if(flag==1) //当标志位置1时,开始输出(有按键按下标志位才置1)
{
flag=0; //作用是只输出一次
output_0x10(); //先输出table,再输出0x01,这样0x01会在下面的595并行输出
delayms(200); //延时500ms(不是必须的)
output_table();
}
}
}
注:程序里面的延时函数都不是必须的,只是为了保证运行的稳定,去掉可能也没问题(延时是门玄学),或者也可以换上_nop_()短暂延时,此时应加上头文件:
#include<intrins.h>