其他分享
首页 > 其他分享> > 解决按键控制数码管带来闪灭显示问题的项目工程(优化版三)

解决按键控制数码管带来闪灭显示问题的项目工程(优化版三)

作者:互联网

/*****
承接上一个解决按键控制数码管带来闪灭显示问题的项目工程(优化版一)来
做解决按键控制数码管带来闪灭显示问题的项目工程(优化版三)。为何呢?
由于上一个解决按键控制数码管带来闪灭显示问题的项目工程(优化版一)
程序内按键扫描函数和数码管显示函数存在大量的不精准延时,导致CPU消耗
过大,拖慢CPU处理指令的速度。如何来解决呢?请看下面讲解。
为什么按下按键到按键抬起后,会干扰到数码管的显示?原因:如果按键扫描
函数和数码管显示函数都放在主函数的固定循环内,当按键按下后,按键扫描
函数进行按键扫描,在扫描到按键延时后,CPU被限制在按键延时处进行计时,
却无法运行其他程序,从而导致数码管显示函数无法运行,就会出现数码管闪
灭显示问题。人能看到数码管闪烁是因为人眼能识别高频率(人眼看不到闪烁
的频率为50Hz)低于50Hz,即1/50Hz=0.02秒,因此要想让人眼看不到数码管闪
烁,数码管显示函数的显示频率至少是50Hz,即1/50Hz=0.02秒,也不是越高
好,还要结合按键扫描函数的按键延时来取出最恰当的显示频率。
除了以上问题,解决按键控制数码管带来闪灭显示问题的项目工程(优化版一)
还存在程序内按键扫描函数和数码管显示函数存在大量的不精准延时,导致CPU
消耗过大,拖慢CPU处理指令的速度。
本程序分两个程序。一个是程序一,按键控制数码管带来闪灭显示问题的程序。
另一个是程序二,解决按键控制数码管带来闪灭显示问题的项目工程(优化版
三)。通过去掉按键控制数码管带来闪灭显示问题的项目工程(优化版一)程
序内按键扫描函数和数码管显示函数存在大量的不精准延时。定时器解决按键
消抖原理:1、在按键扫描函数中判断按键是否按下。2、若检测到有按键按下,
则开启定时器计时,定时时间为10ms左右。按键按下后发生抖动的时间段是定
时器定时10ms后进入定时中断的时间段,也就是这个定时器定时10ms后进入定
时中断的时间段用来消耗按键按下后发生抖动的时间段。此时设个消抖标志位
变量置1。3、在消抖标志位变量置1下,再次在按键扫描函数中判断按键是否按
下。4、实现相应功能,等待按键松开。提醒:先试程序一,再试程序二,之后
两者对比,找出不同点,取最适合的。
*****/
//程序一:按键控制数码管带来闪灭显示问题的程序
//#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;//转速/10000的余数/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 count;//定时器中断次数变量
uchar xiaodouflag;//消抖标志位变量
uchar lingweiflag;//显示0标志位变量
uchar code weima[]={0xfe,0xfd,0xfb,0xf7};//数码管位码表
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;//转速/10000的余数/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 display()//显示程序
//{
//   static uchar i;
//   P1=0x00;
//   P2=0xff;
//   switch(i)
// {
//    case 0:
//           P2=weima[i];
//           P1=table[num/1000];
//           i++;
//           break;
//    case 1:
//           P2=weima[i];
//           P1=table[num%1000/100];
//           i++;
//           break;
//    case 2:
//           P2=weima[i];
//           P1=table[num%100/10];
//           i++;
//           break;
//    case 3:
//           P2=weima[i];
//           P1=table[num%10];
//           i++;
//           break;
//    default : break;//自定义 
//   }
//   if(i>3)
//   i=0;
// }
  void display()//显示程序
{
   static uchar i;
   P1=0x00;
   P2=weima[i];
   switch(i)
 {
    case 0:
           P1=table[num/1000];
           break;
    case 1:
           P1=table[num%1000/100];
           break;
    case 2:
           P1=table[num%100/10];
           break;
    case 3:
           P1=table[num%10];
           break;
  }
   i++;
   i%=4;
 }
  void keyscan()
{
//   if(add==0)
// {         
//    delay(5);
//    if(add==0)
//  {
//     num++;
//     while(!add);
//     lingweiflag=0;
//    }
//   }
   if(add==0)
 {         
    TR1=1; 
    if(xiaodouflag==1)
  {
     if(add==0)
   {         
      num++;
      while(!add);
      lingweiflag=0;
     } 
    }
   }
//   if(dec==0&&lingweiflag==0)
// {         
//    delay(5);
//    if(dec==0)
//  {
//     num--;
//     while(!dec);
//    }
//   }
   if(dec==0&&lingweiflag==0)
 {         
    TR1=1;
   if(xiaodouflag==1)
 {  
    if(dec==0)
  {         
     num--;
     while(!dec);
    }
   }
  }
   if(num>9999)
 {
    num=0;
   }
   if(num==0)
 {
    num=0;
    lingweiflag=1;
   }
 }
  void Time0_Time1_init()
{
   TMOD=0x11;
   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;
   TH1=(65536-10000)/256;//为什么取定时器中断时间为10000微妙,即10毫秒,亦0.01秒,则频率为1/0.01S=100Hz?由于人眼能看到数码管闪烁是源于人眼能识别高频率(人眼看不到闪烁的频率为50Hz)低于50Hz,即1/50Hz=0.02秒,因此要想让人眼看不到数码管闪烁,数管显示函数的显示频率至少是50Hz,即1/50Hz=0.02秒,也不是越高越好,还要结合按键扫描函数的按键延时来取出最恰当的显示频率。
   TL1=(65536-10000)%256;
   EA=1;
   ET0=1;
   TR0=1;
   ET1=1;
   TR1=0;
  }
  void time0() interrupt 1
{
   TH0=(65536-10000)/256;
   TL0=(65536-10000)%256;
   display();
  }
  void time1() interrupt 3
{
   TH1=(65536-10000)/256;
   TL1=(65536-10000)%256;
   count++;
   if(count==1)
   count=0;
   xiaodouflag=1;
  }
  void main()
{
   Time0_Time1_init();
   while(1)
 {
    keyscan();
   }
  }

 

标签:显示,函数,50Hz,数码管,闪灭,num,按键
来源: https://www.cnblogs.com/AChenWeiqiangA/p/12933763.html