如果你对开发板原理图上译码器和锁存器和还有与非门连接的电路还不够了解,那么请看:
蓝桥杯单片机(一)LED
首先我们分析数码管依旧从原理图开始:
蓝桥杯单片机开发板上一共有8根数码管,与上图一一对应,我们先单独讲第一排数码管,数码管下面一共有两排引脚,a1-dp1和com1-4,其中数码管a1-dp1是对应一个数码管上的每一段(图中也标识出来了),所以如果想显示0,a1-dp1=1100 0000,当然这是共阳数码管,如果是共阴数码管则是0011 1111,蓝桥杯开发板上是共阳数码管。然后com1-4对应的是数码管未选,比如com1等于1,第一个数码管就被选上了,然后以此类推。
a1-dp1接到了a-dp然后接到了锁存器的Q1-Q8,锁存器另外一端是P0口,所以数码管依然由P0控制,com1-4接到了另外一个锁存器,锁存器另外一端也仍然由P0控制,所以数码管的位选(亮几根数码管)和怎么亮都由P0控制,但是每个锁存器的控制端LE接到了与非门然后连接到了译码器,译码器的输入就是P2的高三位。
所以控制数码管就是先打开P2到数码管位选,使用P0控制显示几根数码管,再又用P2到单根数码管来使用P0显示对应的符号。
所以对应的程序为:
P2=0XC0;//P2打开数码管位选锁存器
P0=0XFF;//FF=1111 1111 意为打开所有数码管
P2=0XE0;//P2打开数码管锁存器
P0=0xC0;//C0=1100 0000 意为所有数码管显示0
但是如果所有数码管都只能显示一样的数字,那么这样八根数码管的设计显得毫无意义。
所以接下来介绍动态数码管。
动态数码管就是利用人眼的视觉缺陷来显示数码管,例如:平时生活中的灯其实都是在快速闪烁,只是频率太高,人眼看不见。
动态数码管也是如此,每次只打开一根数码管,显示数字,然后快速切换到第二个数码管,然后依次循环,这样人眼就能看见数码管显示不同的数字了。
下面是动态数码管的程序:
unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
//tab数组存放了数码管0-9和全熄
unsigned char SMG[8];
//SMG数组用于存放数码管显示tab的数字几
void SMG_output(void)
{
unsigned char i;
for(i=0;i<8;i++)
{
P2=(P2&0X1F)|0Xc0;
P0=(1<<i);
P2=(P2&0X1F)|0Xe0;
P0=tab[SMG[i]];
delayms(1);
}
//最后消隐
P2=(P2&0X1F)|0Xc0;
P0=0Xff;
P2=(P2&0X1F)|0Xe0;
P0=0Xff;
}
首先定义tab和SMG两个数组。进入数码管显示函数,用循环来对应0-7个数码管,首先用P2选中位选锁存器,P0=(1<
接下来使用数码管写一个99秒倒计时程序:
#include
#include"intrins.h"
#define uchar unsigned char
void SMG_output(void);
void init(void);
void Delay1ms(void);
uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
uchar SMG[8]={10,10,10,10,10,10,10,10};
uchar time=99;
uchar num=0;
void main(void)
{
init();
while(1)
{
num++;
if(num==1000/8)
{
num=0;
time--;
}
SMG[0]=time/10;
SMG[1]=time%10;
SMG_output();
}
}
void SMG_output(void)
{
uchar i;
for(i=0;i<8;i++)
{
P2=(P2&0X1F)|0Xc0;
P0=(1<<i);
P2=(P2&0X1F)|0Xe0;
P0=tab[SMG[i]];
Delay1ms();
}
P2=(P2&0X1F)|0Xc0;
P0=0Xff;
P2=(P2&0X1F)|0Xe0;
P0=0Xff;
}
void Delay1ms(void) //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
//初始化程序,上电关闭LED,蜂鸣器,继电器,数码管
void init(void)
{
P2=(P2&0X1F)|0XA0;
P0=0X00;
P2=(P2&0X1F)|0X80;
P0=0Xff;
P2=(P2&0X1F)|0Xc0;
P0=0Xff;
P2=(P2&0X1F)|0Xe0;
P0=0Xff;
}
由于数码管每次选择都会延时1ms,所以每次进入SMG_output都会延时8ms,每次主函数循环num++,记为一次8ms,当num==1000ms/8ms时,也就是1m时,num=0,然后时间变量time减一,由于时没有用定时器来计时,所以实际显示时间可能不是特别准确。
效果如下:
有问题可以评论和私信