文章借鉴https://blog.csdn.net/qq_41639829/article/details/82222753,并在基础上加以总结改进.
一、位移缓存器
74HC595是一个8位串行输入、并行输出的位移缓存器,也就是1个I/O口输入,8个I/O口输出.
一、管脚说明
管脚编号:缺口左边为1号角,然后按照逆时针编号。
1~7脚 ,15脚(Q n):并行输出脚
8脚(GND):接地
9脚(SOUT也称Q7’):用于级联,移位寄存器中数据多于八位时,就会这八位数据送到下一个595
10脚(MR):低电平时触发,清空移位寄存器中已有数据,接高电平即可。
11脚(SH_CP):移位寄存器时钟,每一次上升沿(低电平到高电平)寄存器做一次移位,接受一位数据
12脚(ST_CP):存储寄存器时钟。上升沿时,数据从移位寄存器转存带存储寄存器
13脚(OE):595使能管脚,接低电平即可以让595输出数据
14脚(DS):输入串行数据
16脚(VCC):电源脚
注意:最先输入的数据由Q7输出
DS串行输入的数据为0111 1111
此过程为:串行数据输入时钟(11脚 SH_CP)寄存器时钟(12脚 ST_CP)为低电平,DS输入数据0;然后SH_CP变为高电平(上升沿触发),DS数据进入Q0中,紧接着SH_CP变成0,来为下一次数据输入准备。然后DS得到数据1,SH_CP再次变为高电平,Q0中的0进入Q1,1进入Q0。等八位数据进入寄存器后,SH_CP变为高电平,则可以输出数据。然后变为低电平,为下一次数据输出做准备。
1.SH_CP=0,Ds=0,SH_CP=1,Q0=Ds=0
2.SH_CP=0,Ds=1,SH_CP=1,Q1=Q0=0,Q0=Ds=1.
2.SH_CP=0,Ds=1,SH_CP=1,Q2=Q1=0,Q1=Q0=1,Q0=Ds=1.
…
以此类推
掌握了74HC595位移缓存器的工作方式后,我们可以通过它写一个流水灯的样例.
如图下,代码就不贴出了.
二、Matrix点阵
在Proteus中我选择的是绿色的8x8的点阵,其类型是行共阴!
电路图
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190415204731408.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMzE4NDk4,size_16,color_FFFFFF,t_70
比如点亮第一个灯,那么第一行给出低电平,第一列给出高电平即可,按照这样的思路完成点阵实验。
前面我们已经熟悉了数码管的静态显示和动态显示,实在不懂可以看我之前发的博客,这里我就不赘述了。
要画出一个好的图形,需要用到取模软件.
我们要在实验中得到这样的一个图形.
Proteus仿真图如下
元器件,AT89C52,MATRIX,74HC595
完整代码如下.
#include<reg52.h>
#include<intrins.h>
//intrins.h函数,一般出现在C51单片机编程中,一般程序中需要使用到空指令_nop_();字符循环移位指令_crol_等时使用
//OE 第13脚 输出有效(低电平)
//MR 第10脚 主复位(低电平)
typedef unsigned char uchar;
typedef unsigned int uint;
/*
上面引脚控制行,行共阴,即低电平选中
下面引脚控制列,列共阳,即高电平选中
*/
sbit SER = P3^4; //p3.4串行数据输入 DS
sbit SCK = P3^6; //串行输入时钟,上升沿有效 SHCP 第11脚 数据输入时钟线
sbit RCK = P3^5; //串行寄存器时钟,上升沿有效 STCP 第12脚 输出存储器锁存时钟线
void SendTo595(uchar Data);
char shu=0xFE;
char a[8]={0x00,0x66,0x99,0x81,0x42,0x24,0x18,0x00};//列
void delay(unsigned int n)//延时函数
{
unsigned int i=0,j=0;
for(i=0;i<n;i++)
for(j=0;j<123;j++);
}
void Hang()//行扫描
{
P1=shu;
shu=_crol_(shu,1);
}
void main(){
int i=0;
RCK=0;
while(1){
for(i=0;i<8;i++){
Hang();
SendTo595(a[i]); //串行,控制列.
delay(3);
}
}
}
void SendTo595(uchar Data){
int i;
for(i=0;i<8;i++){
SCK=0;
SER = 0x80&Data;
Data = _crol_(Data,1);
SCK=1;
_nop_(); //等待一个机器指令时间.
}
/*位移寄存器完毕,转移到存储寄存器*/
RCK = 1; //上升沿,存储寄存器变为高电平 延迟两个时钟周期
_nop_();
_nop_();
RCK = 0; //不加出错,因为电平不变化,存储寄存器的内容不变,为第一次输入的移位寄存器内容0x00.
}
在此基础上,实现滚动的I LOVE YOU字符.
//把原先a数组改变,把原先主函数改变替换.
char a[32]={0x3e,0x08,0x08,0x08,0x08,0x08,0x08,0x3e,
0x00,0x66,0x99,0x81,0x42,0x24,0x18,0x00,
0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x7e,
0x00,0x3e,0x08,0x08,0x08,0x08,0x08,0x08} ;
void main(){
int i=0,changeRow=0;
RCK=0;
while(1){
int speed=12; //控制速度
while(speed--){
for(i=0;i<8;i++){
Hang();
SendTo595(b[i+changeRow]); //串行,控制列.
delay(4);
}
}
changeRow++; //原来的第二行,变成第一行了.
if (changeRow>=24) changeRow=0; //循环开始.
}
}
总的效果应该这样,由于不会截取动图,先这样了,下次学习改进.
由于刚学单片机,难免存在一些知识漏斗,请批评指正.