单片机动态扫描驱动数码管.docx
《单片机动态扫描驱动数码管.docx》由会员分享,可在线阅读,更多相关《单片机动态扫描驱动数码管.docx(11页珍藏版)》请在冰豆网上搜索。
单片机动态扫描驱动数码管
跟我学51单片机(五):
单片机动态扫描驱动数码管
原理简介
常用的段式数码管有七段式和八段式,八段比七段多了一个小数点,其他的基本相同。
所谓的几段就是指数码管里有相应的几个小LED发光二极管,通过控制不同的LED的亮灭来显示出不同的字形(见图1(a))。
从各发光二极管的电极连接方式又可以分为共阳极和共阴极两种类型。
共阴极则是所有的二极管的阴极连接在一起,而阳极是分离的(见图1(b));而共阳极就是所有二极管的阳极是公共相连,而阴极则是分离的(见图1(c))。
本学习板采用的是八段共阴极数码管,型号为LG3641AH。
图1数码管内部结构图
前文所述,数码管与发光二极管的工作原理相同,共阳极时,所有正端接电源正极,当负端有低电平时,该段有电流流过,发光管亮,当负端为高电平时,该段无电流流过,发光管不亮。
要显示什么数字,就使对应的段为低电平(见表1)。
共阴极与共阳极的电平变化状态相反。
当每个段的驱动电流为2~20mA,电流越大,发光越亮。
表1显示的数字和七段码各位的对应关系表
常用的七段式数码管的硬件驱动设计方法有:
静态驱动与动态驱动。
静态驱动即指每个数码管的数据线都有一个单独的数据锁存器,数据锁存器输入的数据由使能端控制,当使能端为高电平时,数据线上的数据(要显示的七段码)进入显示器,使能端与地址译码器的输出相连,要显示那位,则选通那位的地址,在软件设计上不要求程序循环,也不存在显示数字发生闪烁。
但是这样会占用很多口线。
动态显示是将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。
这样一来,就没有必要每一位数码管配一个锁存器,从而节省了口线,地简化了硬件电路。
所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。
电路详解
此讲的电路图如图2。
从图2中可以看出,驱动八个八段数码管总共用了6个单片机IO口,其中三个IO通过控制74HC595来实现对数码管中的各段驱动,另外三个IO通过控制74HC138来实现对8个数码管中的公共端驱动。
此外为了增加74HC595输出的驱动能力,在其输出后接了一级74HC245芯片,以提高驱动能力,增加数码管的亮度。
在这里对这三个芯片进行介绍说明。
图2数码管动态驱动电路图
74HC138是常用的3-8线译码器,即具有3个输入端(管脚1,2,3)与8个输出端(管脚15,14,13,12,11,10,9,7),作用为完成3位二进制数据到8位片选的译码。
也就是说,3个输入端对应8个二进制数据(000,001,010,011,100,101,110,111),对于每个输入的数据,输出端相应位输出低电平,其他7位输出高电平。
74HC138具有2个低电平使能端(管脚4,5)与1个高电平使能端(管脚6),当低电平使能端接低电平且高电平使能端接高电平时74HC138才能正常工作,否则8个输出端全部输出高电平。
因此在本学习板上设置一个跳线,如图2中所示中的SM-EN短路块,跳上时表示接低电平,74HC138正常工作,跳开时表示接高电平,74HC138不工作。
74HC138的真值表如表2所示:
H代表高电平,L代表低电平,X代表不定的状态。
表274HC138输入输出真值表
74HC595是8位串行输入/输出或者并行输出移位寄存器芯片,可以将串行的数据,转为并行的输出,这样可以节约控制器的IO口资源,因而广泛应用。
74HC595最多需要5根控制线,即SDI(Pin14)、SCK(Pin11)、RCK(Pin12)、
(Pin10)和
(Pin13)。
图2中将
直接接到高电平,用软件来实现寄存器清零;
直接接到低电平,一直输出有效。
把其余三根线和单片机的I/O口相接,即可实现对74HC595的控制。
数据从SDI口送入74HC595,在每个SCK的上升沿,SDI口上的数据移入寄存器,在SCK的第9个上升沿,数据开始从SDO移出。
如果把第一个74HC595的SDO和第二个74HC595的SDI相接,数据即移入第二个74HC595中,照此一个个接下去,可接任意多个。
数据全部送完后,给RCK一个上升沿,寄存器中的数据即置入锁存器。
此时
为低电平,数据即从并口Q0~Q7输出。
74HC245为八总线收发器芯片,即可以将数据从A总线端口传送到B总线端口,也可将数据从B总线端口传送到A总线端口。
传送方向由方向控制管脚DIR(芯片1脚)输入的逻辑电平而定。
其真值表如表3所示:
表374HC245输入输出真值表
H代表高电平,L代表低电平,X代表不定的状态。
程序设计
本讲设计实例核心程序如下:
……
#defineSDIP2_7
(1)
#defineSCLKP2_6
(2)
#defineRCLKP2_5(3)
……
voiddat_in(unsignedchardat)(4)
{
unsignedchari;(5)
for(i=0;i<8;i++)(6)
{
SCLK=0;(7)
SDI=dat&0X80;(8)
dat《=1;(9)
SCLK=1;(10)
}
RCLK=0;(11)
RCLK=1;(12)
}
程序详细说明:
(1)将数据输出端定义为P2.7管脚。
(2)将数据时钟输出端定义为P2.6管脚。
(3)将寄存器时钟输出端定义为P2.5管脚。
(4)数据传入函数,传入一字节。
(5)定义一个无符号字符型变量。
(6)要因为要传送一个字节,故要8次。
(7)数据时钟先输出低。
(8)让数据管脚输出传入字节的最高位。
(9)传入字节左移一位。
(10)数据时钟输出高,上升沿将数据所存储至74HC595数据寄存器中。
(11)寄存器时钟先输出低。
(12)寄存器时钟输出高,上升沿将数据所存储至74HC595数据寄存器中。
以上字程序的作用,当发送一个字节的显示数据的时候,通过74HC595进行串行转并行的控制,每次从单片机IO发送1Bit出去,循环8次,完成发送一个字节,之后再的输出端以一个字节的方式传输给数码管,实现显示。
调试要点与实验现象
接好硬件电路,通过冷启动方式将程序所生成的。
hex文件下载到单片机运行后,复位单片机,就可以观察到板上8个数码管都点亮,并从数字0到9变化闪烁。
调试的时候需要注意的是,数码管的使能控制端(见图2)必须用跳线帽跳上,从而让74HC138能工作输出。
不需要用到数码管时可以,反之,跳开以节省系统电流损耗。
另外动态扫描过程中,数码管显示的亮度与驱动电流、点亮时间和关断时间有关,所以应当适当调整驱动电流大小和扫描频率,从而控制显示所需要的亮度。
这在驱动尺寸较大的数码管组时更是如此,为了稳定显示,硬件方面必须达到该有的驱动能力,如在驱动端再接达林顿管等。
软件方面,应在实际的调试过程中不断的尝试(见本讲程序中所扫描次数的经验值),找到一个最佳临界点,即要注意动态扫描的延时间隔和扫描次数。
总结
本讲介绍了单片机动态驱动数码管的原理并给出了实例,通过该讲,我们可以总结如下:
动态扫描驱动数码管的优点:
当显示位数较多时,采用动态显示方式比较节省I/O口,硬件电路也较静态显示简单;缺点:
其稳定度不如静态显示方式。
而且在显示位数较多时CPU要轮番扫描,占用CPU较多的时间。
总的来说,无论是动态还是静态显示,其显示更新的速率不能太快,如数据不停变化,太快则无法看清楚显示的内容,在软件设计是必须注意的。
另外,在同等条件下动态显示的亮度比静态显示要差一些,所以在适当提高驱动电流,例如使用限流电阻,就应略小于静态显示电路中的,或者使用缓冲驱动芯片。
学习笔记从零开始学单片机
(2)全八段数码管显示
开发板上有八个八段数码管,现在把它点亮它。
数码管显示有动态和静态两种,本质上没有什么区别,由于单片机接口有限,不可能一对一,所以依次让每一个数码管点亮,那么从视觉角度上看就是一起亮起来。
但是动态显示时,亮度较低。
下面的图是一个八段数码管的原理图,有共阴极和共阳极两种解法,这里是共阴极接法。
a,b,c,d,e,f,g,dp分别对应八个数码管。
为了让八个数码管连起来,该开发板使用了两个八进制三态非反转透明锁存器,74HC573。
它的特性是:
×输出能直接接到CMOS,NMOS和TTL接口上
×操作电压范围:
2.0V~6.0V
×低输入电流:
1.0uA
×CMOS器件的高噪声抵抗特性
D0~D7:
输入
Q0~Q7:
输出
LE:
输入使能
OE:
输出时能
输入
输出
输出使能
锁存性能
D
Q
L
H
H
H
L
H
L
L
L
L
X
不变
H
X
X
Z
X:
随即
Z:
高阻抗
下面是电路原理图,所有数码管的引脚,同时接入DUAN这个锁存器的输出端,锁存器WEI的输出端为8个数码管的片选。
锁存器DUAN的输入使能接到51的P2.6引脚,锁存器WEI的输入使能接到P2.7上,同时它俩的输出使能接地(可能是为了方便点)
原理图很简单,接下来写一个程序,依次点亮数码管,并延时一段时间
#include
unsignedcharcode_table[]=
{
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0
};
sbitLed8En=P2^6;//数码管,锁存器使能信号,高电平有效,数码管输出P0
sbitLed8CS=P2^7;//数码管片选,锁存器使能信号,电平有效,低电平选中
/****************************************************************/
delay循环延时
timesunsignedint延时次数,100*x
/****************************************************************/
voiddelay(unsignedinttimes);
/****************************************************************/
dlight点亮数码管
iunsignedchar片选数码管,点亮第i个灯
numberunsignedchar显示参数,高电平有效
durationunsignedint循环延时次数,100*duration
/****************************************************************/
voiddlight(unsignedchari,unsignedcharnumber,unsignedintduration);
voidmain()
{
unsignedchari=1;
while
(1)
{
for(i=1;i<=8;i++)
{
dlight(i,i,1);
}
}
}
voiddlight(unsignedchari,unsignedcharnumber,unsignedintduration)
{
if(i>8||number>16)
return;
Led8CS=1;
P0=~(1<<(i-1));
Led8CS=0;
Led8En=1;
P0=code_table[number];//.abcdefg,高电平亮
Led8En=0;
delay(duration);
}
voiddelay(unsignedinttimes)
{
unsignedinti,j;
for(i=0;ifor(j=0;j<10;j++)
;
}
最后在数码管上显示87654321