第11集
一、数码管工作原理
数码管显示亮度高,响应速度快,可以在一些比较差的环境中使用。有1位、2位、4位、8位连体等。。。也有专用于显示时间的数码管。
如图,一位数码管由8个二极管构成,7个构成“日”字型,1个是小圆点。分共阴和共阳。 共阴:所有二极管的负极连接在一起,接到电源负极。共阳:所有二极管的正极连接在一起,接到电源正极。(图(a)引脚画错了。)
驱动的原理都很简单,如共阳型数码管的驱动。图(b)右边的电路图可以看出,所有的二极管正极都接在电源正极,a、b、c、d、e、f、g、dp都接在单片机的IO口上,在《51单片机复习笔记1》:http://www.51hei.com/mcu/2111.html 中介绍过驱动二极管的原理,所以这里只需要在相应的二极管负极给低电平即可让相应的二极管发光。
这里补充一下,为什么给高电平二极管就不亮,给低电平就亮呢。因为单片机是TTL电平,也就是说高电平即输出5V,低电平就不输出电压0V,二极管的正极接在电源的正极那就是5V,那么二极管的负极如果也给高电平的话,那么就相当于在二极管的负极也接到了5V,二极管两端都是5V 没有电势差,就相当于没有通电一样,自然不会发光。给低电平即0V,那么二极管就有一个5V的电势差且是正向偏置,二极管自然就发光了,共阴型恰好相反。
看下图(设共阳型),假如我们要让数码管显示‘1’,那么只需要给b、c段的二极管低电平,其他为高电平即可让数码管显示‘1’。假如我们要让数码管显示‘2’,那么只给a、b、g、e、d低电平即可让数码管显示‘2’。要显示什么,只给相应的发光二极管低电平即可。
那么在实际编程中应该怎么写程序呢。
我们将a、b、c、d、e、f、g、dp八个引脚接到单片机的P1口,P1^0←a、P1^1←b.....P1^7←dp。画红框的是低四位。那么如果要显示2。
P1^0 = a =0、P1^1 = b = 0、P1^6 = g = 0、P1^4 = e = 0、P1^3 = d = 0
剩余的为1那么就是:1010 0100 = 0xA4
程序代码中将0xA4赋值给P1即可,如 P1 = 0xA4; 看图。
由于数码管需要占用单片机的IO口很多,所以一般会搭配74HC573芯片来扩展IO口。《51单片机复习笔记1》有介绍该芯片的使用方法。驱动原理一样。
数码管显示方式有两种:
静态显示:其实和上面一样,如P1=0xA4; 那么P1一直维持0xA4那么数码管的每一段二极管的状态都会保持字形不变。变动P1的电平状态才会改变新字形。优点是占用CPU时间少。缺点是占用IO口多硬件设计复杂,特别是控制多位数码管时尤为占用IO口,成本较高。
动态显示:动态其实就是利用发光二极管的余晖和人眼视觉暂留作用。控制多位数码管时,将所有数码管的段选并联在一起,由位选线控制是哪位数码管接受段选编码。如下图一样。
例如:
P0组是并联所有数码管的段选。P2^6、P2^7选择哪位数码管。我要显示520,那么 首先选中第一位数码管,然后送数字5的段编码控制段选的P0口。
然后再选中第二位数码管,再送数字2的段选编码给P0,这时候第一位数码管虽然断电,但是二极管并没有瞬间熄灭,所以还有余晖保持字形。
继续再选中第三位数码管送数字0的段选编码给P0,这时候第一、第二位数码管虽然都断电,但由于切换速度太快,余晖仍没有完全熄灭就造成三位数码管同时显示不同的数字字型的假象。
上图是六位共阴型数码管搭配两片74HC573芯片的电路图。L2是控制数码管的a、b、c、d、e、f、g、dp,L3是选择要显示的数码管。
下图是74HC573芯片接在单片机上的10个IO口。(完美诠释74HC573的实用性,哈哈~)
下图是编码列表
利用数码管显示秒表程序源码:
/*****************************************
* 说明:动态显示方式控制数码管。秒表源码
* 设计者:L、QQ:1007566569
* 开发板:DB-51 Ver2.1
* 数码管:六位共阴型
******************************************/
#include<reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit dual = P2^6;// 控制 L2的74HC573芯片是否锁存
sbit weal = P2^7;// 控制 L3的74HC573芯片是否锁存
uchar aa;
// 数码管显示数字的编码 table[0] 就是显示 0
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
// 要显示指定数字的数码管
uchar code tablewe[]={
0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
#define Time 50000
#define YsTime 1
void ShowTime(uchar bai, uchar shi, uchar ge);
void delay(uint z);
/******** 主函数 ********/
void main()
{
uchar b, s, g;
TMOD = 0x01;// 选择定时器工作方式 1
TH0=(65536-Time)/256;// (65536 - (50000/(12*(1/12))))/256 ;
TL0=(65536-Time)%256;// (65536 - (50000/(12*(1/12))))%256 ;
EA=1; // 开启总中断
ET0=1;// 开启定时器 0 中断
TR0=1;// 启动定时器 0
while(1)
{
if(aa == 20)// 50ms*20 = 1000ms = 1s
{
aa = 0;
g ++; // 个位自增
if(g == 10)
{
s++; // 十位自增
g = 0;
}
if(s == 10)
{// 百位自增
b++;
s = g = 0;
}
if(b == 10)
b = s = g = 0;
}
ShowTime(table[b], table[s], table[g]);
}
}
/******** 数码管显示函数 ********/
void ShowTime(uchar bai, uchar shi, uchar ge)
{
// 显示百位
dual = 1;
P0 = bai;
dual = 0;
P0 = 0xff;
weal = 1;
P0 = 0xfe;
weal = 0;
delay(YsTime);
// 显示十位
dual = 1;
P0 = shi;
dual = 0;
P0 = 0xff;
weal = 1;
P0 = 0xfd;
weal = 0;
delay(YsTime);
// 显示个位
dual = 1;
P0 = ge;
dual = 0;
P0 = 0xff;
weal = 1;
P0 = 0xfb;
weal = 0;
delay(YsTime);
}
/******** 延时函数 ********/
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/******** 中断函数 每50ms触发一次 ********/
void timer0() interrupt 1
{
TH0=(65536-Time)/256;
TL0=(65536-Time)%256;
aa++;
}
也有采用BCD-7段译码芯片:共阳型的74LS48、74LS49、CD4511。共阴的74LS46、74LS47、CD4513。
第十二集
霖锋教程中的是两个四位一体共阴型数码管,通过一片74HC573芯片控制两个四位数码管的段选,通过一片74HC138芯片选择位数码管(即位选)。
74HC138的引脚说明:
先把一些简单的引脚说一下:
GND接地、VCC接电源正极。
E1、E2:低电平有效,如果其中一个为高电平则无法操控芯,Y0 — Y7 输出全高电平。
E3:高电平有效,如果为低电平则无法操控芯片,Y0 — Y7 输出全高电平。
如果要控制芯片首先是 VCC和GND接电源,E1、E2低电平或接低,E3高电平。
下面这三个引脚是比较重要的:
A组IO口是输入,Y组端口是输出。
A0、A1、A2是用来控制Y0 — Y7 输出电平状态,往里面输入八进制数即可指定Y0 — Y7中其中一个为低电平。例如想要 Y5 为低电平,那么5的八进制为101,只需要给 A2 = 1、A1=0、A0=1,即可让Y5为低电平。想要Y3为低电平,那么3的八进制为011,只需要给A2 = 0、A1 = 1、A0 = 0 即可。
记住,A组IO只是控制Y组的某一IO输出低电平而已,其余都为高电平。
教程中有八位数码管,所有刚好Y组全部都用上。