如图3所示,点阵屏分为单色和颜色。点阵屏由许多点组成。在一个点上,只有一个颜色的灯珠。这是单色点阵屏。一个点上有三个灯珠,分别是RGB三原色。
你可能看不到图4,所以大黄色是点阵屏,下面的粉色长条也是。
大点阵屏幕实际上是由许多小点阵屏幕拼接在一起,最终形成一个大,在移动舞台上,拆卸方便,如音乐会,液晶不方便,运输不方便,也容易损坏,点阵屏幕可以快速一起运输,然后拼在一起。
单色点阵屏成本低,不能像图4那样显示视频,只能显示文本。
这是我们用的,一个点里有一个灯珠的单色点阵屏。
8*8是8行8列的64个点阵屏幕,左下角是背引脚图。在设计点阵屏幕时,您需要知道引脚是如何排序的,否则如何驱动它。
这里有一个凹塑料,以这一点为参考点,右边是1脚,左边是8脚,右到左1~8、上左右9~16.学完之后,如果想做点阵屏,就要知道引脚的排序。
接下来看点阵屏内部原理图。
内部结构相对简单,由多个组成LED灯珠连接在一起组成
左边和上边的数字分别对应的是引脚
LED就是让指定的灯亮起来,显示我们需要的字形
比如“上”
那我们怎么点亮呢?
例如,在左上角,它的正极接收到9英尺,负极接收到13英尺,然后9英尺高,13英尺低电平明亮,那么我们如何赋予其他英尺呢?
我们的LED点阵是共阳极,和前面的数字管一样,也分为共阳极共阴极。
是的,都是接正极的,就是共阳极。相反,如果是,LED正极接在列上,那就是共阴极。
回到刚才的问题,如下:
那点亮许多灯怎么办?
比如我们再点亮这个。
使用动态扫描技术。(像数字管一样,利用人眼的视觉暂留效果)
我们先让第一个亮,然后马上让第二个亮,然后让第一个亮,一直循环。这样,两者似乎都亮了,但事实上,两盏灯不能同时静态显示。
让我们看看原因:
如果我们要想让这两个亮,那么9,14是高电平,13,3是低电平。那么第一行第二列的灯也会亮,第二行第一列也是。所以我们就需要用动态扫描的方式。
以上是点阵屏静态显示和动态显示的工作原理。在实际应用中,我们使用动态显示来显示我们需要的内容。
有人会问,为什么不把这16个引脚接到单片机的引脚上?因为接下来我们介绍74HC595芯片。
我们的点阵焊接在一起PCB板上的点阵模块由两个595级联驱动*8点阵的。
只需要需要三个单片机IO嘴,可以控制16个脚的点阵。非常经济IO嘴。这也是实际应用中的一个方案。在点阵屏行业,几乎所有74HC595级联驱动。
当其他学生再次做实验时,一些学生会看到16个引脚被单片机驱动。作为初学者,它看起来很简单,实际上与我们的实际应用脱节。在实际应用中,我们不能用这种方式来驱动它。这种方法消耗了太多的硬件资源。你看,一个点阵有16只脚。假设我们想丰富点阵显示的内容,我们将添加3个8*8点阵,即64个引脚,如果我们直接单片机,需要多少个单片机?以我们stc89c例如,一台单片机有32台IO口,然后需要两个单片机。(这种4块8*我们称之为16*16点阵模块)上面的方案显然是不可行的。一台单片机要几块钱,需要两台单片机才能驱动四个屏幕,所以硬件成本太高。
595方法,两个595级可以一起驱动一个8*8点阵,驱动4点阵,我们只需要8片595,1595只需要几毛钱(5毛)。有些学生可能会看到其他硬件驱动18*8个点阵需要8个或10个以上IO嘴,这种硬件纯粹是为你设计的,他和实际应用程序严重脱轨,即使你学习单片机只是为了玩,那么你也想玩符合实际的东西,否则你不能玩任何高端。
74HC595
在学习了595之后,你会发现他非常适合驱动这种电子屏幕。
串行输入,并行输出。
例如,有一个数据,一个字节的8位数据,从A传输到B点,如果是串行,串行只有一个数据通道,这8位想要从A到BB只能通过这个通道,所以一次只能通过一个,比如第一次通过1,1,2,以此类推,8次。如果是8个平行,他有8个通道,8个数据可以一次传输
可见并行传输速度快,但占用的硬件资源多,共占用8条传输数据线。串行占用的硬件资源少,但传输速度慢很多。
让我们来看看595的使用方法
更重要的是,如果你理解了这一块,595芯片就会完全理解,如果你理解了使用方法,编程就不会有问题。
(比较难,前面是并行输入输出,现在已经串行输入了)
中间是我们的引脚图,下面是我们模块的原理图。他只需要三个IO口可以驱动16个引脚阵屏。
DS(14):串行数据输入端,串行输入只需要一条数据线,级联连接到一级Q7',意思是如果要多加595芯片,那么DS接到最后一个Q7'
看看这个电路图。当然,这里的目标是不同的。这里的目标是SER,我们看引脚,
为什么要级联?595串入并出,8个IO口作并行输出,我们点阵有16个脚,1个只能控制8个脚,8个脚我们需要另一个。
Q7'(9)(注意两个Q7.是不同的,要区分,9脚上的点是非的意思):级联输出端,接收下一个595DS端
看上面的595Q7'有个×,悬空,如果不级联悬空,如果级联接到下一片14脚。
如果有三个级联,我们用三个IO嘴可以做8*3=并行输出24位数据。该方法用于扩展单片机IO口很实用,如果是单片机IO口不够用,我们就可以用这种方案,并且价格也便宜,而且成熟好用。
SH_CP(11):数据输入时钟线,因为它是串行输入,基本上所有串行输入都需要一个时钟线,这个时钟线是给他们一个节拍,当你的数据应该去,什么时候不应该给一个节拍,否则数据不知道轮到我传输过去了。上升时,数据从DS串行输入。移位寄存器(8位)输入595内部是什么过程?下面演示一下。
DS应用脚时,应接收单片机IO如果在嘴上收到DS的IO发送一个数据1,然后DS脚是1(高电平),那么1是如何进入内部移位寄存器的呢?需要在11脚上产生一个上升边缘,然后数据可以进入移位寄存器。什么是上升边缘?低电平,然后变成高电平。对于5V就单片机而言,低电平时0V,高电平时5V。从0V变到5V这个过程叫上升沿。单片机产生上升边很简单,给它IO单片机输出一个低电平0V,再给单片机一个1,单片机输出5V,从0V到5V这样的变化产生了上升沿,这是单片机产生上升沿的过程。
再详细说一下:
假设我们发1101 0011这样的数据,1字节8位。右边低,左边高。先发低位。给先给DS一、用单片机IO口输出1,然后给11英尺一个低电平和一个高电平产生上升边缘。此时,1将被送到移位寄存器的第八位,然后发送第二位,然后发送给DS一个1,然后产生一个上升边缘,将第一个1挤压到第七位移位寄存器,这一次1发送到第八位,然后发送0,然后第八位移位寄存器是0,第七位是1,第六位就是1,依次类推。然后我们需要输出,输出到Q0~Q7.并行输出怎么办?然后我们需要输出,输出到Q0~Q7.并行输出,怎么办?这时是12英尺。
ST_CP(12):输出存储器锁定时钟线,12也连接单片机IO,给他一个上升沿,然后刚才的8位数据突然从Q0到Q7输出,即串行输入并行输出。只从输入DS一个口,通过时钟控制,依次放在8位内部移位寄存器上,然后给12脚输出锁存器一个上升边缘,锁存器中的8位数据突然输出到Q0~Q7。我们还需要注意12英尺。这是一个锁定器。当我们学习数字管时,我们也说573是一个锁定器。这里的锁定器是什么意思?假设8次后,将数据放入移位寄存器并给出上升沿,则将数据输出到Q0~Q7上只要595没有断电,Q0~Q除非我们再次通过,否则7的数据保持不变DS过去串行输入端输入8位数据,覆盖数据,否则不断电就保持不变。这有什么好处?这对我们驱动电子屏幕非常实用,他可以实现不闪光屏幕,我现在想要这8盏灯,它总是保持明亮,不会因为其他情况而改变数据,假设以下几个IO用嘴做其他用途(11、12),Q0~Q保持不变,这就是他的锁定功能。体现在数字管的课上。
/MR(10):我们不需要清除低电平清0移位寄存器,所以直接在电路图上连接VCC。电路图上的标的不同,标的/SRCLR。
/OE(13):高电平为进制输出状态(高阻态),我们需要使用他的串入和出口,所以这只脚必须收到GND上。标的电路图E。假如这只脚是高电平,那么Q0~Q7和点阵屏的IO嘴断了,断了之后没有电压电流,就息屏了,不工作了。如果在IO如果我们有很多嘴,我们可以连接这个脚IO,给一个高电平就会息屏,点阵的16脚相当于悬空,过去没有任何能量,LED灯将完全熄灭,然后给出一个低电平,两个芯片Q0~Q7.它们都连接起来了。数据保持不变。上次的内容是什么?这一次,仍然是同一个内容,实现了闪屏效果。
VCC(16):连接电源,2~6V。
GND(8)接地。
级联:
DS输入的数据,当11英尺时SH_CP如果产生上升边缘,第一个数据将发送到第一个移位寄存器的最高水平,然后发送另一个数据,然后第一个数据运行到第七个移位寄存器,第二个数据运行到第八个移位寄存器,16次,最后第一个数据运行到第二个移位寄存器,第二个数据运行到第二个移位寄存器位上。第16位数据跑到第一片的第八位上,再给ST_CP一个上升沿,16位数据就会都输出出去,通过两片你的Q0~Q7。第一片输出的9~16位,第二片输出的1~8位。
再详细看下原理图:
两个595的时钟线(11和12脚分别接在一起)接在一起,输入端接在第一片(14),另一片的输入接在级联的输出端。电源端加上滤波电容(C1、C2)。
市面上的大点阵屏基本都是由8*8拼接的,就像之前看到的。室外的都是防水的,室内的防水效果就没那么好,其它都是相同的。
看看手册
供电电压2~6V。
引脚图和真值表:
G如果为高,那么QA~QH其它三个不管什么状态,输出为高阻态。G为低,SCLR为低,那么就清除移位锁存器内容。
SCK位上升沿时,移位寄存器移位。RCK为上升沿就把移位寄存器内容传输到输出锁存器。
工作电源要求:
最小2V,最大6V,输出电压最小0,最大VCC。
直流电气特性,作为初学者不用看,成为高手自己设计电路需要了解。
VIN最小输入高电平电压有一个要求,VCC为4.5V,输入还有温度限制,不能低于3.15V,不然就检测不到,不认为是高电平。
VIL最大低电平电压,VCC为4.5V,低电平最大电压不能超过1.35V,超过就不认为是低电平。
这个输出电流只有在级联多片点阵的时候需要考虑的到,如果电流过低,点阵屏就会很暗,就需要做一个电流放大。
交流特性:
内部结构图:
时序图:
直插的外部封装:
上面,了解了点阵工作原理,点亮灯,动态扫描,学习了74HC595,串入并出,优点节省IO口,熟悉怎么进行串行输入和并行输出,给14输入,再给11接上时钟线,给一个上升沿,数据就进入了移位寄存器,还没输出,输出时,只要给12一个上升沿,8位移位寄存器的数据就输出了。级联,9脚接到下一个芯片的14脚,不论级联多少都只需要3个IO口做输入。串行输入时要搞清楚级联时数据的高低字节。
为了使电子显示屏不闪屏,都是需要用并行输出的,串行可能会闪屏。
proteus仿真问题:
- CON6是接插件、插针端子,叫CONN-H6
- 点阵屏上面引脚是列,高有效,从左到右是1~8列,下面引脚是行,低有效,从左到右是1~8行。即共阴极点阵屏。
- Q0是最高位,Q7是最低位,不知道你们记错没有,反正我记错了哈哈
接下来开始编程
亮左上角第一个灯(应该说是靠近9脚那侧的)
这里应该是讲错了,视频中说Q0是低位,可实际Q0是高位
1 #include<reg51.h>
2
3 #define uchar unsigned char
4 #define uint unsigned int
5
6 sbit DIO=P3^4;
7 sbit S_CLK=P3^5;
8 sbit R_CLK=P3^6;
9
10 //uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
11 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
12
13 void main()
14 {
15 //点亮点阵左上方第一个点row 0x80 , col 0xfe
16 //串入并出,所以要一位一位的发送给DIO
17 uchar i=0,dat;//一个字节数据是一个常量,发数据要进行移位、运算,常量不可以
18 dat=0xfe;//先给列的值,因为列是第二个芯片控制,先给了第一个芯片,当再赋值行时,会把列挤给第二块芯片
19 //并且先发送低位再发送高位
20 for(i=0;i<8;i++)
21 {
22 S_CLK=0;
23 R_CLK=0;
24 if(dat&0x01)
25 DIO=1;
26 else
27 DIO=0;
28 S_CLK=1;
29 dat>>=1;
30 }
31 dat=0x80;
32 for(i=0;i<8;i++)
33 {
34 S_CLK=0;
35 R_CLK=0;
36 if(dat&0x01)
37 DIO=1;
38 else
39 DIO=0;
40 S_CLK=1;
41 dat>>=1;
42 }
43 R_CLK=1;
44 while(1);
45
46 }
实际电路板是这样
查了一遍595个引脚输出,发现输出不对。原因暂未发现,但不影响,将错就错吧。
先把串行输入数据写成函数的形式,再让亮另外一个灯,上面那个
1 #include<reg51.h>
2
3 #define uchar unsigned char
4 #define uint unsigned int
5
6 sbit DIO=P3^4;
7 sbit S_CLK=P3^5;
8 sbit R_CLK=P3^6;
9
10 //uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
11 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
12
13 void Send_Byte(uchar dat);
14
15 void main()
16 {
17 //串入并出,所以要一位一位的发送给DIO
18 //先给列的值,因为列是第二个芯片控制,先给了第一个芯片,当再赋值行时,会把列挤给第二块芯片
19 //并且先发送低位再发送高位
20 Send_Byte(0xfe);
21 Send_Byte(0x40);
22 R_CLK=1;
23 while(1);
24
25 }
26 void Send_Byte(uchar dat)
27 {
28 uchar i=0;
29 S_CLK=0;
30 R_CLK=0;
31 for(i=0;i<8;i++)
32 {
33 if(dat&0x01)
34 DIO=1;
35 else
36 DIO=0;
37 S_CLK=1;
38 dat>>=1;
39 S_CLK=0;
40 }
41 }
接下来显示汉字:电
取字模,我们用到了软件PCtoLCD2002
设置
然后新建8,8
点击生成字模就可以了
{0xEF,0x01,0x6D,0x01,0x6D,0x01,0xEE,0xE0}
这是列选的数据
1 #include<reg51.h>
2 #include<intrins.h>
3
4 #define uchar unsigned char
5 #define uint unsigned int
6
7 sbit DIO=P3^4;
8 sbit S_CLK=P3^5;
9 sbit R_CLK=P3^6;
10
11 uchar code Table[]={0xEF,0x01,0x6D,0x01,0x6D,0x01,0xEE,0xE0};//电,列选table表
12
13 void Send_Byte(uchar dat);
14
15 void main()
16 {
17 uchar j=0,row;
18
19 while(1)
20 {
21 row=0x80;
22 for(j=0;j<8;j++)
23 {
24 Send_Byte(Table[j]);//送每一行的列选值
25 Send_Byte(row);//分别扫描每一行,一次一行
26 R_CLK=1;//Send_Byte中置低了
27 R_CLK=0;//再次变低
28 row=_cror_(row,1);
29 }
30 }
31 }
32 void Send_Byte(uchar dat)
33 {
34 uchar i=0;
35 S_CLK=0;
36 R_CLK=0;
37 for(i=0;i<8;i++)
38 {
39 if(dat&0x01)
40 DIO=1;
41 else
42 DIO=0;
43 S_CLK=1;
44 dat>>=1;
45 S_CLK=0;
46 }
47 }
不过呢,这是倒着的,仿真出不来
但是这个取模软件可以帮助我们
点完后就这样了,然后再生成字模就可以了
接下来显示:电子
1 #include<reg51.h>
2 #include<intrins.h>
3
4 #define uchar unsigned char
5 #define uint unsigned int
6
7 sbit DIO=P3^4;
8 sbit S_CLK=P3^5;
9 sbit R_CLK=P3^6;
10
11 uchar code Table[][8]={
12 0xE0,0xEE,0x01,0x6D,0x01,0x6D,0x01,0xEF,
13 0xE7,0xF7,0xF7,0xF7,0x80,0xF7,0xFB,0xC3
14 };//电,列选table表
15
16 void Send_Byte(uchar dat);
17
18 void main()
19 {
20 uchar j=0,k=0,row;
21
22 while(1)
23 {
24 for(k=0;k<2;k++)
25 {
26 row=0x80;
27 for(j=0;j<8;j++)
28 {
29 Send_Byte(Table[k][j]);//送每一行的列选值
30 Send_Byte(row);//分别扫描每一行,一次一行
31 R_CLK=1;//Send_Byte中置低了
32 R_CLK=0;//再次变低
33 row=_cror_(row,1);
34 }
35 }
36 }
37 }
38 void Send_Byte(uchar dat)
39 {
40 uchar i=0;
41 S_CLK=0;
42 R_CLK=0;
43 for(i=0;i<8;i++)
44 {
45 if(dat&0x01)
46 DIO=1;
47 else
48 DIO=0;
49 S_CLK=1;
50 dat>>=1;
51 S_CLK=0;
52 }
53 }
会发现电和子一起显示了,怎么办?自己想一下办法
你会发现延时不行,原因是,延时的话,每一个点显示的时间很长,而不是一个字
所以我们需要把一个字的时间加长,也就是里面的for循环多来几次
1 #include<reg51.h>
2 #include<intrins.h>
3
4 #define uchar unsigned char
5 #define uint unsigned int
6
7 sbit DIO=P3^4;
8 sbit S_CLK=P3^5;
9 sbit R_CLK=P3^6;
10
11 uchar code Table[2][8]={
12 0xE0,0xEE,0x01,0x6D,0x01,0x6D,0x01,0xEF,
13 0xE7,0xF7,0xF7,0xF7,0x80,0xF7,0xFB,0xC3
14 };//电,列选table表
15
16 void Send_Byte(uchar dat);
17
18 void main()
19 {
20 uchar j=0,k=0,row;
21 uint z;//别写成了uchar...uchar最大256
22 while(1)
23 {
24 for(k=0;k<2;k++)
25 {
26 row=0x80;
27 for(z=0;z<1000;z++)
28 {
29 for(j=0;j<8;j++)
30 {
31 Send_Byte(Table[k][j]);//送每一行的列选值
32 Send_Byte(row);//分别扫描每一行,一次一行
33 R_CLK=1;//Send_Byte中置低了
34 R_CLK=0;//再次变低
35 row=_cror_(row,1);
36 }
37 }
38 }
39 }
40 }
41 void Send_Byte(uchar dat)
42 {
43 uchar i=0;
44 S_CLK=0;
45 R_CLK=0;
46 for(i=0;i<8;i++)
47 {
48 if(dat&0x01)
49 DIO=1;
50 else
51 DIO=0;
52 S_CLK=1;
53 dat>>=1;
54 S_CLK=0;
55 }
56 }