废话不多说,直接进入今天的主题
数码管
数码管其实就是由8个LED灯组成,也就是8个发光二极管,上篇文章中对LED进行了介绍,想让LED点亮也就是给两端形成电位差,看图,图中的数码管分为两种,上方的为共阴极数码管,可以发现所有二极管的负极(阴极)都接在一起,那么下方的数码管就是共阳极数码管。
接下来介绍如何实现一个数码管的点亮,以及让他显示具体的数字。
这是四个一体的数码管,如果想要点亮其中一个,我们首先要进行的一个操作就是位选,位选简单来说就是,选中其中一位数码管。
拿共阴极举例来说
现在我们要选中第一位数码管,要在COM段(8个LED的阴极端)提供一个低电平,阴极必然要提供低电平,提供低电平后也就选中这个数码管了,接下来我们要对这单个数码管来进行操作了。
在具体操作前,来介绍一个控制这个数码管位选的芯片(74HC138译码器)
LED(1-8)不就是我们的数码管,位选由这个译码器控制,刚才我们要选中第一个数码管(LED8),可以从图中看出,LED8是由Y7控制,那么如何选中Y7,看图中左上角,P22,P23,
P23,分别对应A-B-C,这A-B-C对应二进制的1,2,4,选中Y7,也就是让着A-B-C之和为7,之前我们讲过控制单一引脚时只需要给其高低电平即可1/0,在这里对应法则简单记就是我只要给它1,那么就能启动1-2-4.比如我令P22=1;对应的1就有效;
同理,选中Y7=(P22=1)+(P23=1)+(P24=1)=1+2+4=7;位选到此结束。
接下来就是段选
何为段选,就是对单个数码管中的每一段LED进行操作,编码时采用16进制控制,一个数码管由8个LED组成,刚好8位二进制→16进制。
看右上角,a-b-c-d-e-f-g-dp,这就是数码管的段,连接着LED的正极,我们控制时需要给其高电平,对应端口为P0,其实操作每一个段时也可以用二进制单独操作,但是过于麻烦,直接对P0端口进行16进制操作。
想让数码管显示数字,我们要学会推数字对应的段码(16进制编码号),以数字“1”为例
想让这个数码管亮1,就是让b-c段点亮,其他段熄灭,即b-c段LED给高电平1,其他段给低电平0,我们先从二进制开始,顺序记着要倒着来(dp-a),0(dp)0(g)0(f)0(e)0(d)1(c)1(b)0(a)→0000 0110→0x06,ok到这里段选部分也就没什么可说的了。
对了,上面一张图中有个芯片74HC245是一个缓冲器,简单来说就是提高驱动能力,直白点就是单片机的六味地黄丸。
OK,接下来就是静态显示了,说白了就是显示一个数字,用代码来讲。
#include <REGX52.H>
unsigned char Seg_Buf[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//数字段码
void Seg_Disp(unsigned char Location,Number)//数码管显示函数
{
switch(Location)
{
case 1:P2_2=1;P2_3=1;P2_4=1;break;
case 2:P2_2=0;P2_3=1;P2_4=1;break;
case 3:P2_2=1;P2_3=0;P2_4=1;break;
case 4:P2_2=0;P2_3=0;P2_4=1;break;
case 5:P2_2=1;P2_3=1;P2_4=0;break;
case 6:P2_2=0;P2_3=1;P2_4=0;break;
case 7:P2_2=1;P2_3=0;P2_4=0;break;
case 8:P2_2=0;P2_3=0;P2_4=0;break;
}
P0=Seg_Buf[Number];
}
void main()
{
Seg_Disp(8,9);
while(1)
{
}
}
其中数码管显示函数中case1-7就是位选,通过给P22-P23-P24三个引脚不同的电平来选中不同的数码管,效果图如下
接下来是动态显示,为什么要分为静态和动态,因为这个单片机上,控制每一位数码管的段选引脚是一样的,假如我选中两位数码管,这两位数码管他们所接受的段码是一样的,也就是显示出来的数字是相同的,那么我们要实现多个数码管同时显示不同的数字就要采取动态显示
其实动态显示主要采用的就是利用不断刷新数码管的显示来迷惑人眼,因为人眼无法观察到数码管的刷新频率。
具体怎么操作呢?请看代码
#include <REGX52.H>
#include <intrins.h>
unsigned char Seg_Buf[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void Delay(unsigned int xms) //@11.0592MHz
{
unsigned char i, j;
while(xms--)
{
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void Seg_Disp(unsigned char Location,Number)
{
switch(Location)
{
case 1:P2_2=1;P2_3=1;P2_4=1;break;
case 2:P2_2=0;P2_3=1;P2_4=1;break;
case 3:P2_2=1;P2_3=0;P2_4=1;break;
case 4:P2_2=0;P2_3=0;P2_4=1;break;
case 5:P2_2=1;P2_3=1;P2_4=0;break;
case 6:P2_2=0;P2_3=1;P2_4=0;break;
case 7:P2_2=1;P2_3=0;P2_4=0;break;
case 8:P2_2=0;P2_3=0;P2_4=0;break;
}
P0=Seg_Buf[Number];//
Delay(1);//
P0=0x00;//
}
void main()
{
while(1)
{
Seg_Disp(1,1);
Seg_Disp(2,2);
Seg_Disp(3,3);
}
}
其中后面打斜杠的代码其绝对作用,称为数码管消影,就是在第二个数码管接受新的段码时将前一个数码管的段码清零,以此来达到效果,直接上图
ok,这样动态数码管也就实现了,今天就到此为止吧。