LED点阵屏通过LED(发光二极管)组成,以灯珠亮灭来显示文字、图片、动画、视频等,LED点阵显示屏制作简单,安装方便,被广泛应用于各种公共场合,如汽车报站器、广告屏、银行窗口屏叫号屏以及停车系统等等。
LED点阵屏在生活中的应用:
我们今天实验的是8*8点阵屏,其原理图如下所示:
直接看右边的原理图,它有8行8列的LED灯构成,其共有16个引脚,对于的左边的实物16个引脚位置如图所示。
假设我们现在要点亮右边原理图的第一个引脚,根据二极管的特性是不是需要把引脚9姐高电平,引脚13接低电平,才能使第一个LED灯亮起来。那么如何像生活中那样多个位置的LED灯同时亮起来呢?比如现在要让第一个LED灯和二行二列的那个LED灯同时亮起来,是不是引脚9和14都接高电平,而引脚13和3都接低电平就行了呢?
其实不然,如果同时让引脚引脚9和14都接高电平,而引脚13和3都接低电平,那么你分析以下第二个引脚也就是一行二列的那个引脚,它也是要亮起来的,从而达不到我们的要求。其实这个数码管的动态显示的原理是一样的,也是借助人的视觉效果看起来像是同时亮的,其实它是分两次传输,第一次只有引脚9接高电平,引脚13接低电平从而让第一个灯亮起,而第二次传输只有引脚24接高电平,而引脚3接低电平从而让其对应的灯亮起来。也就是说实际上它是分两次亮起来的,而人眼却无法区分代码运行时这二者的效果,从而实际看起来是同时亮起来的。
74HC595
芯片
74HC595
芯片是一种串入并出的芯片,在电子显示屏制作当中有广泛的应用。74HC595
是8位串行输入/输出或者并行输出移位寄存器。
为什么要在这里说这个芯片呢,原因是我们刚刚知道一个88的点阵屏有16的引脚,而我们的51单片机总共才32个引脚,如果需要同时满足两个或三个点阵屏工作其单片机引脚远远是不够的,但是不可能为此再购买另一个单片机,成本高昂。所以就有了74HC595
芯片,它的作用就是可以节省点阵屏占用的引脚数,只需要3个引脚就可以控制一个88的点阵屏,大大节省了引脚资源。
74HC595
芯片原理图如下:
符号 | 引脚 | 描述 |
---|---|---|
Q0~Q7 | 第15脚、第1-7脚 | 8位并行数据输出 |
GND | 第8脚 | 接地 |
Q7’ | 第9脚 | 串行数据输出 |
MR | 第10脚 | 主复位(低电平) |
SHCP | 第11脚 | 数据输入时钟线 |
STCP | 第12脚 | 输出存储器锁存时钟线 |
OE | 第13脚 | 输出有效(低电平) |
DS | 第14脚 | 串行数据输入 |
VCC | 第16脚 | 电源 |
DS
(14脚):串行数据输入端,级联的话接上一级的Q7
。Q7'
(9脚): 级联输出端。将它接下一个595的DS
端SHCP
(11脚):上升沿时数据从DS
(14脚)串行输入。Q0->Q1->...->Q7
:移位寄存器的数据移位。STCP
(12脚):上升沿时数据从Q0---Q7
并行输出MR
(10脚):低电平时将移位寄存器的数据清零,通常将它接VCC
。OE
(13脚):高电平时禁止输出(高阻态),通常将它接GND
串行输入并行输出的过程,首先我们要明白595芯片内部有
Q0->Q7
八个并行输出端口,每个输出端口与一个移位寄存器相连,总共8个移位寄存器,他们是以类似于“栈”的方式存储的,比如现在我们要输入1001 1011
的8位数据,首先它是在SHCP
(11脚)和Q7'
(9脚)的共同作用下串行输入的,我们在芯片SHCP
接收到的第一个上升沿时从Q7'
传输最低位的1,然后在下一次的上升沿传输其次的1,在8个上升沿后完成串行输入。
其中第一次传入的1本来是存在Q7端口对应的寄存器,但是在下一位1传入后,第一次的1被挤入Q6对应的寄存器,类似于进栈操作理解,最后的结果是最低位的1存在Q0端口对应的寄存器,最高位的1存在Q7端口对应的寄存器。
那么如何并行输出呢,当输入完成后,如果STCP
(12脚)再检测到一个上升沿,那么寄存器对应的内容就会通过对应的输出端口再这个上升沿时全部输出完毕。
74HC595
芯片与我们8*8点阵连接的电路图如图所示:
练习从点亮一颗灯开始:
#include <reg52.h>
#define uchar unsigned char
sbit DIO=P3^4; //串行输入端口
sbit S_CLK=P3^5; //移位寄存器时钟,即输入时钟
sbit R_CLK=P3^6; //输出锁存器时钟,即输出时钟
void main(){
//ROW 0x80 ,COL 0xfe
uchar i,date;
//先发列数据,再发行数据,这是由电路决定的
date=0xfe;
for(i=0;i<8;i++)
{
S_CLK=0;
R_CLK=0;
if(date & 0x01) //求最低位,为1就发1,为0就发0
DIO=1;
else
DIO=0;
S_CLK=1; //产生上升沿,发送数据
date=date>>1; //这里有人可能会记得上回的_cror_()函数,注意它是循环右移函数,而不是算术右移函数
}
date=0x80;
for(i=0;i<8;i++)
{
S_CLK=0;
R_CLK=0;
if(date & 0x01) //求最低位,为1就发1,为0就发0
DIO=1;
else
DIO=0;
S_CLK=1; //产生上升沿,发送数据
date=date>>1;
}
R_CLK=1; //并行输出数据
while(1);
}
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
sbit DIO=P3^4; //串行输入端口
sbit S_CLK=P3^5; //移位寄存器时钟,即输入时钟
sbit R_CLK=P3^6; //输出锁存器时钟,即输出时钟
uchar code table[8]={0xEF,0x01,0x6D,0x01,0x6D,0x01,0xEE,0xE0};
//把发送一次8位数据封装为一个函数
void send_byte(uchar date){
uchar i;
S_CLK=0;
R_CLK=0;
for(i=0;i<8;i++)
{
if(date & 0x01) //求最低位,为1就发1,为0就发0
DIO=1;
else
DIO=0;
S_CLK=1; //产生上升沿,发送数据
date=date>>1; //这里有人可能会记得上回的_cror_()函数,注意它是循环右移函数,而不是算术右移函数
S_CLK=0;
}
}
void main(){
//0xEF,0x01,0x6D,0x01,0x6D,0x01,0xEE,0xE0 电
//ROW 0x80 ,COL 0xfe
uchar j,ROW;
while(1){
ROW=0x80;
for(j=0;j<8;j++)
{
send_byte(table[j]);
send_byte(ROW);
R_CLK=1;
R_CLK=0;
ROW=_cror_(ROW,1);
}
}
}
循环显示几个汉字。