数码管动态显示 + 中断 消除闪烁

来源:互联网 发布:软件测试的基础知识 编辑:程序博客网 时间:2024/05/29 15:13
/********************************************************************************
         数码管动态显示 + 中断  消除闪烁
     定时器定时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个数码管的显示缓冲区
 };
unsigned int cnt = 0;
unsigned char i = 0;
void main()
{   
 unsigned long sec = 0;
 TMOD = 0x01;  //定时器模式寄存器TMOD选择模式1
 TH0 = 0xFC;   //高8位
 TL0 = 0x18;   //低8位   //定时器0定时1ms
 TR0 = 1;   //定时器0运行控制位置1,开定时器0
 EA = 1;      //打开总中断
 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];
  }
 }
}
//定时器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; 
 }
  
}
原创粉丝点击