按键控制数码管0-99显示,十位不跳,用定时器T0中断

时间:2022-11-07 23:33:33

如果直接在主函数中写按键控制数码管0-99显示,不管怎么延时数码管十位上的数都会闪,原因就是单片机的机器周器太快,人的按键速度是ms级的,所以等你人操作完了,单片机早就执行了不知道多少遍。

解决方法就是用中断,这里采用定时器T0溢出中断,工作方式1, 2ms中断显示一次,这样的话既不影响按键操作,又不影响显示,一举两得。


以下程序是适用于德飞莱51单片机开发板


#include <reg52.h>


#define uint unsigned int
#define uchar unsigned char
#define DataPort P0 


sbit Seg_Latch = P2^2;    //段锁存
sbit Bit_Latch = P2^3;    //位锁存


sbit key_up = P1^0;      //数字增加按键
sbit key_down = P1^1;    //数字减少按键


uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //数码管显示0-9


uchar code tab[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};    //数码管位选


uchar temp[2];   //存放num十位和个位


void Display(unsigned char FirstBit,unsigned char Num);  //显示函数


void delay(uchar t)  //延时
{
while(--t);
}


void DelayMs(uchar z) //ms级延时
{
while(z--)
{
delay(245);
delay(245);
}
}


void Time0_init()    //定时器T0溢出中断初始化
{
TMOD |= 0x01;      //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
EA = 1;
ET0 = 1;
TR0 = 1;
}


char num = 0;         //0-99数字
uchar key_num = 0;    //按键计数


void main()
{
Time0_init();     //T0中断初始化
key_up = 1;       //使用前先拉高
key_down = 1;
while(1)
{
if(!key_up)
{
DelayMs(10);
if(!key_up)
{
while(!key_up)
{
key_num++;
DelayMs(10);    //10x100 = 1s 按了1s
if(key_num == 100)
{
key_num = 0;    //清零
while(!key_up)
{
if(num < 99)
{
num++;
}
temp[0] = table[num / 10];//及时赋值
temp[1] = table[num % 10];
DelayMs(50);   //数字跳动快慢
}
}
}
key_num = 0;   //防止累加造成错误识别
if(num < 99)
{
num++;
}
}
}

if(!key_down)    //减操作
{
DelayMs(10);
if(!key_down)
{
while(!key_down)
{
key_num++;
DelayMs(10);
if(key_num == 100)
{
key_num = 0;
while(!key_down)
{
if(num > 0)
{
num--;
}
temp[0] = table[num / 10];
temp[1] = table[num % 10];
DelayMs(50);
}
}
}
key_num = 0;
if(num > 0 )
{
num--;
}
}
}
temp[0] = table[num / 10];   //用完赋值
temp[1] = table[num % 10];
}
}


void Display(unsigned char FirstBit,unsigned char Num)    //显示
{
  static unsigned char i = 0;  //静态局部变量,用完后不释放
   DataPort  = 0;   
   Seg_Latch = 1;     
   Seg_Latch = 0;


   DataPort = tab[i+FirstBit]; 
   Bit_Latch=1;     
   Bit_Latch=0;


   DataPort = temp[i]; 
   Seg_Latch=1;     
   Seg_Latch=0;

i++;
if(i == Num)
{
i = 0;
}
}


void Time0_isr() interrupt 1
{
TH0 = (65536 - 2000) / 256;   //取高八位 2ms
TL0 = (65536 - 2000) % 256;   //取低八位
Display(0,2);
}