解决按键控制数码管带来闪灭显示问题的项目工程(优化版一)
/***** 为什么按下按键到按键抬起后,会干扰到数码管的显示?原因:如果按键扫描 函数和数码管显示函数都放在主函数的固定循环内,当按键按下后,按键扫描 函数进行按键扫描,在扫描到按键延时后,CPU被限制在按键延时处进行计时, 却无法运行其他程序,从而导致数码管显示函数无法运行,就会出现数码管闪 灭显示问题。人能看到数码管闪烁是因为人眼能识别高频率(人眼看不到闪烁 的频率为50Hz)低于50Hz,即1/50Hz=0.02秒,因此要想让人眼看不到数码管闪 烁,数码管显示函数的显示频率至少是50Hz,即1/50Hz=0.02秒,也不是越高 好,还要结合按键扫描函数的按键延时来取出最恰当的显示频率。 本程序分两个程序。一个是程序一,按键控制数码管带来闪灭显示问题的程序。 另一个是程序二,解决按键控制数码管带来闪灭显示问题的程序。通过把数码 管显示函数放在定时器中断子程序中,以及把按键扫描函数放在主函数固定循 环内。提醒:先试程序一,再试程序二,之后两者对比,找出不同点,取最适 合的。 *****/ //程序一:按键控制数码管带来闪灭显示问题的程序 //#include<reg51.h> //#define uchar unsigned char //#define uint unsigned int //sbit add=P3^0; //sbit dec=P3^4; //uchar lingweiflag; //uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f} ; //共阴数码管段码数字0~9字码表,高电平点亮数码管段码数字0~9。 //uint num; //uint qian,bai,shi,ge;//定义拆字变量 // /**ms级延时子程序**/ // void delay(uint x) //{ // uint i,j; // for(i=0;i<x;i++) // for(j=0;j<110;j++); // } // void display() //{ // qian=num/1000;//取得千位数字 // bai=num%1000/100;//取得百位数字 // shi=num%100/10;//取得十位数字 // ge=num%10;//取得个位数字 // // P2=0xfe;//数码管千位显示位 // P1=table[qian];//数码管千位数值显示 // delay(2);//延时 // // P2=0xfd;//数码管百位显示位 // P1=table[bai];//数码管百位数值显示 // delay(2);//延时 // // P2=0xfb;//数码管十位显示位 // P1=table[shi];//数码管十位数值显示 // delay(2);//延时 // // P2=0xf7;//数码管个位显示位 // P1=table[ge];//数码管个位数值显示 // delay(2);//延时 // } // void keyscan() //{ // if(add==0) // { // delay(5); // if(add==0) // { // num++; // while(!add); // lingweiflag=0; // } // } // if(dec==0&&lingweiflag==0) // { // delay(5); // if(dec==0) // { // num--; // while(!dec); // } // } // if(num>9999) // { // num=0; // } // if(num==0) // { // num=0; // lingweiflag=1; // } // } // void main() //{ // while(1) // { // display(); // keyscan(); // } // } //程序二:解决按键控制数码管带来闪灭显示问题的程序 #include<reg51.h> #define uchar unsigned char #define uint unsigned int sbit add=P3^0; sbit dec=P3^4; uchar lingweiflag; uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f} ; //共阴数码管段码数字0~9字码表,高电平点亮数码管段码数字0~9。 uint num; uint qian,bai,shi,ge;//定义拆字变量 /**ms级延时子程序**/ void delay(uint x) { uint i,j; for(i=0;i<x;i++) for(j=0;j<110;j++); } void display() { qian=num/1000;//取得千位数字 bai=num%1000/100;//取得百位数字 shi=num%100/10;//取得十位数字 ge=num%10;//取得个位数字 P2=0xfe;//数码管千位显示位 P1=table[qian];//数码管千位数值显示 delay(2);//延时 P2=0xfd;//数码管百位显示位 P1=table[bai];//数码管百位数值显示 delay(2);//延时 P2=0xfb;//数码管十位显示位 P1=table[shi];//数码管十位数值显示 delay(2);//延时 P2=0xf7;//数码管个位显示位 P1=table[ge];//数码管个位数值显示 delay(2);//延时 } void keyscan() { if(add==0) { delay(5); if(add==0) { num++; while(!add); lingweiflag=0; } } if(dec==0&&lingweiflag==0) { delay(5); if(dec==0) { num--; while(!dec); } } if(num>9999) { num=0; } if(num==0) { num=0; lingweiflag=1; } } void Time0_init() { TMOD=0x01; TH0=(65536-10000)/256;//为什么取定时器中断时间为10000微妙,即10毫秒,亦0.01秒,则频率为1/0.01S=100Hz?由于人眼能看到数码管闪烁是源于人眼能识别高频率(人眼看不到闪烁的频率为50Hz)低于50Hz,即1/50Hz=0.02秒,因此要想让人眼看不到数码管闪烁,数管显示函数的显示频率至少是50Hz,即1/50Hz=0.02秒,也不是越高越好,还要结合按键扫描函数的按键延时来取出最恰当的显示频率。 TL0=(65536-10000)%256; EA=1; ET0=1; TR0=1; } void time0() interrupt 1 { TH0=(65536-10000)/256; TL0=(65536-10000)%256; display(); } void main() { Time0_init(); while(1) { keyscan(); } }
//uchar lingweiflag;
//uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f} ; //共阴数码管段码数字0~9字码表,高电平点亮数码管段码数字0~9。