/********************************************************************************
数码管动态显示 + 中断 消除闪烁
定时器定时1ms,数码管以秒表计时
加上中断可消除数码管刷新时的闪烁问题
闪烁问题是由while语句中分离数字时计算造成的
因为每次1s时间到,在数码管刷新前都要进行计算,耽误了时间,所以闪烁
加了中断以后则是先刷新数码管再分离数字
********************************************************************************/
数码管动态显示 + 中断 消除闪烁
定时器定时1ms,数码管以秒表计时
加上中断可消除数码管刷新时的闪烁问题
闪烁问题是由while语句中分离数字时计算造成的
因为每次1s时间到,在数码管刷新前都要进行计算,耽误了时间,所以闪烁
加了中断以后则是先刷新数码管再分离数字
********************************************************************************/
#include<reg52.h>
unsigned char code LedChar[] = {
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E //0到的F十六进制
};
unsigned char LedBuff[4] = {
0xFF,0xFF,0xFF,0xFF //4个数码管的显示缓冲区
};
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E //0到的F十六进制
};
unsigned char LedBuff[4] = {
0xFF,0xFF,0xFF,0xFF //4个数码管的显示缓冲区
};
unsigned int cnt = 0;
unsigned char i = 0;
unsigned char i = 0;
void main()
{
unsigned long sec = 0;
{
unsigned long sec = 0;
TMOD = 0x01; //定时器模式寄存器TMOD选择模式1
TH0 = 0xFC; //高8位
TL0 = 0x18; //低8位 //定时器0定时1ms
TR0 = 1; //定时器0运行控制位置1,开定时器0
TH0 = 0xFC; //高8位
TL0 = 0x18; //低8位 //定时器0定时1ms
TR0 = 1; //定时器0运行控制位置1,开定时器0
EA = 1; //打开总中断
ET0 = 1; //打开定时器0的中断
ET0 = 1; //打开定时器0的中断
while(1)
{
if (cnt>=1000) //1s到
{
cnt = 0;
sec++; //总时间加1s
LedBuff[0] = LedChar[sec%10]; //分离每一位上的数字
LedBuff[1] = LedChar[sec/10%10];
LedBuff[2] = LedChar[sec/100%10];
LedBuff[3] = LedChar[sec/1000%10];
}
}
}
{
if (cnt>=1000) //1s到
{
cnt = 0;
sec++; //总时间加1s
LedBuff[0] = LedChar[sec%10]; //分离每一位上的数字
LedBuff[1] = LedChar[sec/10%10];
LedBuff[2] = LedChar[sec/100%10];
LedBuff[3] = LedChar[sec/1000%10];
}
}
}
//定时器0中断函数
void InterruptTimer0() interrupt 1 /*关键字interrupt代表这是一个中断函数,1是定时器0的中断入口号。
中断入口号计算方法:中断入口号*8+3=中断向量地址(把十六进制换算为十进制)*/
{
TH0 = 0xFC;
TL0 = 0x18;
cnt++;
P2 = 0xFF; /*此句为消除瞬间错误,例如case1下,P0已刷新而P2暂留在case0状态瞬间,
会造成case0下数码管瞬间显示错误数值,在每次进入开关语句前关闭所有数码管即可消除该错误*/
switch(i) //使四位数码管以1ms间隔轮流刷新,即每个数码管隔3ms刷新一次
{
case 0: P0 = LedBuff[0]; P2 = 0x7F; i++; break; //段选P0,位选P2 ,P0、P2已在<reg52.h>中sfr
case 1: P0 = LedBuff[1]; P2 = 0xBF; i++; break;
case 2: P0 = LedBuff[2]; P2 = 0xDF; i++; break;
case 3: P0 = LedBuff[3]; P2 = 0xEF; i=0; break;
default : break;
}
}
void InterruptTimer0() interrupt 1 /*关键字interrupt代表这是一个中断函数,1是定时器0的中断入口号。
中断入口号计算方法:中断入口号*8+3=中断向量地址(把十六进制换算为十进制)*/
{
TH0 = 0xFC;
TL0 = 0x18;
cnt++;
P2 = 0xFF; /*此句为消除瞬间错误,例如case1下,P0已刷新而P2暂留在case0状态瞬间,
会造成case0下数码管瞬间显示错误数值,在每次进入开关语句前关闭所有数码管即可消除该错误*/
switch(i) //使四位数码管以1ms间隔轮流刷新,即每个数码管隔3ms刷新一次
{
case 0: P0 = LedBuff[0]; P2 = 0x7F; i++; break; //段选P0,位选P2 ,P0、P2已在<reg52.h>中sfr
case 1: P0 = LedBuff[1]; P2 = 0xBF; i++; break;
case 2: P0 = LedBuff[2]; P2 = 0xDF; i++; break;
case 3: P0 = LedBuff[3]; P2 = 0xEF; i=0; break;
default : break;
}
}