1.单片机数码管的显示原理
由于C51单片机是不断重复一条条代码来完成显示工作的,并且芯片引脚数量比较珍贵,不可能使用多个引脚同时控制数码管以及流水灯,所以单片机同时点亮数码管和流水灯本质上是通过一遍一遍不停扫描再加上人眼的视觉暂留实现的。
2.作者遇到的问题
单片机的灯在不该发光的时候发光了,或者是在该亮的时候不亮,亦或者是在该亮的时候不亮,或者是显示效果不尽人意,亦或者是显示忽明忽暗,都是作者遇到的问题。
3.为什么会出现这种问题?
前面说过,单片机的数码管和流水灯之所以能够显示,是因为它利用了人眼的视觉暂留现象通过快速的亮灯、关灯来实现肉眼看上去的常量效果,也正是因为这种视觉暂留现象,才产生了“鬼影”现象。
而对于忽明忽暗的情况则是因为代码控制的电路进行响应的时候也需要时间,而代码执行的时间一般是要比单片机响应的时间短,所以就有可能出现代码执行完了,但是单片机还没有反应过来的情况,就导致了显示忽明忽暗的效果。
视频展示:
控制C51单片机的流水灯和数码管时遇到的综合问题
代码展示:
#include"STC15F2K60S2.H"
#define uchar unsigned char
#define ulong unsigned long
uchar number[]={0x3f,0x06,0x5b,0xff};//数码管上显示的数字示例
sbit sel=P2^3;//此位作用是选择led灯亮还是数码管亮
uchar led=0x01;
ulong k=0;//统计过了多少ms每10s清零一次
uchar i,j;
void init()//初始化函数
{
P0M1=0x00;
P0M0=0xff;
P2M1=0x00;
P2M0=0xff;
sel=1;//设置LED灯可以亮
P0=0;//将LED灯初始化为全灭
}
void T0init()//设置T0定时器
{
TMOD=0x10;//设置定时器工作模式
EA=1;//打开中断总允许开关
ET0=1;//设置T0可以触发中断
TR0=1;//打开定时器
TF0=0;//将中断触发位设置为未触发
TH0=(65536-10000)/256;//TH0和TL0共同设定每100/12ms触发一次
TL0=(65536-10000)%256;
}
void main()
{
init();
T0init();
while(1)
{
sel=1;
P0=led;
P2=7;
P0=number[1];
}
}
void t0() interrupt 1//触发中断时执行
{
static uchar temp=0;
if(temp==60)//每500ms让流水灯往左流水一位
{
if(led==0x80)
led=0x01;
else
led=led<<1;
temp=0;
}
else
++temp;
TF0=0; 重置定时器
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
}
4.解决办法
对于LED灯上不该亮的灯亮了的解决办法是将main函数中while循环里在sel=1之前把把P0赋值为0来消除视觉上的暂留现象。
while(1)
{
P0=0;
sel=1;
P0=led;
P2=7;
P0=number[1];
}
此时会发现流水灯上的“鬼影”消失了,但是数码管上忽明忽暗的现象仍旧存在。这时你会发现它的闪烁是和流水灯的流动规律是一致的。整好印证了上面对问题的分析,那么此时我们就可以在P0=led之后加上sel=0,让LED灯亮的条件改变成让数码管亮,然后再执行接下来的语句,这样便解决了数码管忽亮忽暗的问题。
while(1)
{
P0=0;
sel=1;
P0=led;
sel=0;
P2=7;
P0=number[1];
}
当我们再来仔细看数码管上的时候我们会发现数码管上还有一条亮度较低的亮条纹随着LED灯的滚动而滚动,此时的原因和数码管忽明忽暗的原因一致,因此我们可以选择加上延时函数来解决或者是让P0=number[1]之前多执行几条语句让单片机能缓过来劲。我选择的是让P0=0多执行几次。
while(1)
{
P0=0;
sel=1;
P0=led;
sel=0;
P2=7;
P0=0;
P0=0;
P0=number[1];
}
至此问题得以解决!