找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2097|回复: 4
打印 上一主题 下一主题
收起左侧

单片机按键消抖有反应,但是仿真的时候数码管显示乱抖

[复制链接]
跳转到指定楼层
楼主
#include<reg51.h>
#include<intrins.h>
#include<ctype.h>
#include<string.h>
#include<math.h>
#include<stdio.h>


#define uchar unsigned char
#define uint unsigned int
#define key_group P1

uint time=0;
uint ss=00;
uint key_time;

uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//共阳极0-9的段码
uchar key,key_temp,state_key;



int clock=0;   //时钟初值,默认为0
int coundown=60; //倒计时,默认60s
int kaiji=0;  //上电后进行时钟的设置
char num_show[4];
int show_num=0;
int up=0;  //按键松开
int choose_num=0;
int state=0;
int count_state=0;
int count=0;
int num1=0,num2=0;
int result=0,add_state=0;
int stopwatch_state=0;
int clock_time=0,clock_ss=0;
int mm=0;

void Display();
void Type();
void anjian4();
void anjian3();
void anjian2();
void anjian1();
void jiafa();
void shizhong();
void miaobiao();
void daojishi();
void keyscan();

void main()
{
                        num_show[0]=clock/60/10;
                        num_show[1]=clock/60%10;
                        num_show[2]=clock%60/10;
                        num_show[3]=clock%60%10;
        TMOD=0x01;//计时器0以工作方式1计时
        EA=1;//打开全局中断允许
        ET0=1;//打开定时器0中断允许位
        TR0=1;//启动定时器0
        TH0=(65535-1000)/256;    //定时器初值  1ms
        TL0=(65535-1000)%256;
        
        while(1)
        {
                Display();         
        }
}




void ET_T0() interrupt 1
{
        TH0=(65535-1000)/256;    //定时器初值  1ms
        TL0=(65535-1000)%256;
        show_num++;
        if(show_num>7)
                show_num=0;
        key_time++;
        keyscan();
        if(kaiji==2)   //两个初值都设置完毕
        {
  anjian1();
  }
  anjian3();
  anjian2();
        anjian4();
        if(count_state==1)  //倒计时的状态变量
        {
         daojishi();
        }
        if(stopwatch_state==1)  //秒表的状态变量
        {
                miaobiao();
        }                        
        if(kaiji==2)
        {
    shizhong();
        }
}




void Display(void)
{
switch(show_num)
{
        case 0:
                        
                                 P2=0XF0;
              P0=table[num_show[0]];
                                break;
        case 1:
               P0=table[num_show[0]];
              P2=0XF1;
                          break;
        case 2:
                         P2=0XF0;
             P0=table[num_show[1]];
                         break;
  case 3:        
              P0=table[num_show[1]];
              P2=0xF2;
                          break;
  case 4:
                         P2=0XF0;
             P0=table[num_show[2]];
                         break;
  case 5:        
             P0=table[num_show[2]];
             P2=0xF4;
                         break;
        case 6:
                                P2=0XF0;
              P0=table[num_show[3]];
                                break;
        case 7:
              P0=table[num_show[3]];
              P2=0xF8;
              break;
        default:break;
}
}

void Type(void)
{
switch(state)
  {
         case 0:  //时钟模式
                                count_state=0;
                                stopwatch_state=0;
                                num_show[0]=clock/60/10;
                                num_show[1]=clock/60%10;
                                num_show[2]=clock%60/10;
                                num_show[3]=clock%60%10;                                
              break;
         case 1: //加法模式
                                count_state=0;
                                stopwatch_state=0;
                                choose_num=0;
                                num_show[0]=num1/1000;
                                num_show[1]=num1%1000/100;
                                num_show[2]=num1%100/10;
                                num_show[3]=num1%10;                                
                          break;
          case 2: //倒计时模式
                                count_state=0;
                                stopwatch_state=0;
                                time=0;
                                ss=0;
                                num_show[0]=coundown/1000;
                                num_show[1]=coundown%1000/100;
                                num_show[2]=coundown%100/10;
                                num_show[3]=coundown%10;                                
                          break;
                        case 3:  //秒表模式
                                count_state=0;
                                stopwatch_state=0;
                                time=0;
                                ss=0;
                                num_show[0]=ss/1000;
                                num_show[1]=ss%1000/100;
                                num_show[2]=ss%100/10;
                                num_show[3]=ss%10;                                
                          break;
      default:break;
        }
}




void keyscan(void)
{
switch(state_key)
{
  case 0:
                key_temp=(key_group&0x0f);
          if(key_temp!=0x0f)
                 {
                  key_time=0;
                        state_key=1;
                 }
  break;
        case 1:if(key_time>=1000)
               {
                                 if(key_temp==0x0f)
                                  {
                                         state_key=0;
                                        }
                                 else
                                 {
                                        state_key=2;
                                  break;
                                        }
                                 }
                                 break;
        case 2:if(key_temp==0x0e)
                    {key=1;}
                                 else if(key_temp==0x0d)
                                      {key=2;}
                                 else if(key_temp==0x0b)
                                      {key=3;}
                                 else if(key_temp==0x07)
                                      {key=4;}
                                 else
                                 {
                                  key_temp=0x0f;
                                        state_key=0;
                                        key=0;
                                        break;
                                 }
         state_key=3;
                                 break;
        case 3:if((key_group&0x0f)==0x0f)
               {
                                  key_temp=0x0f;
                                  state_key=0;
                                 }
         break;
}
}




void anjian4(void)
{
if(key==4)  //切换数字|等于按键/倒计时,秒表开始暂停按键
        {
                if(kaiji==0)
                {
                        kaiji=1;
                        choose_num=0;
                        if((num_show[0]*10+num_show[1])<=23&&num_show[2]*10+num_show[3]<=59)  //小于23:59
                                 clock=(num_show[0]*10+num_show[1])*60+num_show[2]*10+num_show[3];   //不然还是默认值
                        
                        num_show[0]=coundown/1000;
                        num_show[1]=coundown%1000/100;
                        num_show[2]=coundown%100/10;
                        num_show[3]=coundown%10;                        
                }
                else if(kaiji==1)
                {
                        kaiji=2;
                        choose_num=0;
              coundown=num_show[0]*1000+num_show[1]*100+num_show[2]*10+num_show[3];
      //开始时钟
                        num_show[0]=clock/60/10;
                        num_show[1]=clock/60%10;
                        num_show[2]=clock%60/10;
                        num_show[3]=clock%60%10;                              
                }
                if(state==2)  //倒计时
                {
                        if(count_state==0)
                        {
                                count_state=1;    //开始
                        }
                        else
                        {
                                count_state=0;   //暂停
                        }
                }
                else if(state==3)  //秒表
                {
                        if(stopwatch_state==0)
                        {
                                stopwatch_state=1;    //开始
                        }
                        else
                        {
                                stopwatch_state=0;   //暂停
                        }
                }
                else if(state==1)  //加法
                {
                        jiafa();
                }
        }
}


void anjian3()
{
        if(key==3)  //切换数码管按键||秒表清零键||倒计时复位键
        {
                up=1;
                if(kaiji<=1||state==1)
                {
                        choose_num++;
                        if(choose_num>=4)
                                choose_num=0;
                }
                if(state==2)
                {
                        if(count_state==0)
                        {
                                num_show[0]=coundown/1000;
                                num_show[1]=coundown%1000/100;
                                num_show[2]=coundown%100/10;
                                num_show[3]=coundown%10;                                
                                ss=0;
                                time=0;
                        }
                }
                if(state==3)
                {
                        if(stopwatch_state==0)
                        {
                                ss=0;
                                num_show[0]=ss/1000;
                                num_show[1]=ss%1000/100;
                                num_show[2]=ss%100/10;
                                num_show[3]=ss%10;                                
                                
                                time=0;
                        }
                }
        }
}


void anjian2(void)
{
        if(key==2)  //加1键
        {
                if(kaiji<=1||state==1)
                {
                        if(num_show[choose_num]<9)
                        {
                                num_show[choose_num]++;
                        }
                        else
                                num_show[choose_num]=0;
                }
        }
}



void anjian1(void)
{
                if(key==1)   //模式切换按键
                {
                        state++;
                        Type();
                        if(state>3)
                        state=0;
                }
}



/**************加法模块***************/
void jiafa()
{
      add_state++;
                        if(add_state==1)
                        {
                                num1=num_show[0]*1000+num_show[1]*100+num_show[2]*10+num_show[3];
                                choose_num=0;   //位选归0
                                        num_show[0]=num2/1000;
                                        num_show[1]=num2%1000/100;
                                        num_show[2]=num2%100/10;
                                        num_show[3]=num2%10;                                
                        }
                        if(add_state==2)  //计算结果
                        {
                                num2=num_show[0]*1000+num_show[1]*100+num_show[2]*10+num_show[3];
                                result=num1+num2;
                                if(result<=9999)
                                {
                                        num_show[0]=result/1000;
                                        num_show[1]=result%1000/100;
                                        num_show[2]=result%100/10;
                                        num_show[3]=result%10;                                       
                                }
                                else
                                {
                                        num_show[0]=9999/1000;
                                        num_show[1]=9999%1000/100;
                                        num_show[2]=9999%100/10;
                                        num_show[3]=9999%10;                                
                                }
                        }
                        if(add_state>=3)
                        {
                                add_state=0;
                                num1=0;
                                num2=0;
                                result=0;
                                choose_num=0;
                                num_show[0]=num1/1000;
                                num_show[1]=num1%1000/100;
                                num_show[2]=num1%100/10;
                                num_show[3]=num1%10;                                       
                        }
}


/*************时钟模块************/
void shizhong(void)
{
                clock_time++;
                if(clock_time>=1000) //1ms*1000=1s
                {
                        clock_time=0;
                        clock_ss++;
                        if(clock_ss>=60)
                        {
                                clock++;
                                clock_ss=0;
                                if(clock==1440)
                                        clock=0;
                                if(state==0)
                                {
                                 num_show[0]=clock/60/10;
                           num_show[1]=clock/60%10;
                           num_show[2]=clock%60/10;
                           num_show[3]=clock%60%10;
                                }
      }
    }
}



/*************秒表模块*************/
void miaobiao(void)
{
time++;
                if(time==1000)  //1ms*1000=1s
                {
                        time=0;
                        if(ss!=9999)
                          ss++;
                        else
                                stopwatch_state=0;
                                num_show[0]=ss/1000;
                                num_show[1]=ss%1000/100;
                                num_show[2]=ss%100/10;
                                num_show[3]=ss%10;        
    }
}


/**********倒计时模块**********/
void daojishi(void)
{
        time++;
                if(time==1000)  //1s
                {
                        if(ss!=coundown)
                          ss++;
                        else
                                count_state=0;
                        time=0;
                                num_show[0]=(coundown-ss)/1000;
                                num_show[1]=(coundown-ss)%1000/100;
                                num_show[2]=(coundown-ss)%100/10;
                                num_show[3]=(coundown-ss)%10;        
     }
}

捕获.PNG (24.06 KB, 下载次数: 21)

这是我的电路图

这是我的电路图
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:447891 发表于 2019-6-9 10:14 | 只看该作者
请大家帮忙看一下按键消抖和按键功能模块那里哪里出错了
回复

使用道具 举报

板凳
ID:332444 发表于 2019-6-9 20:02 | 只看该作者
几个按键实现什么功能?请说清楚。
回复

使用道具 举报

地板
ID:294235 发表于 2019-6-9 20:07 来自手机 | 只看该作者
消抖的时间?
回复

使用道具 举报

5#
ID:517466 发表于 2019-6-9 23:29 | 只看该作者
按键扫描放定时器处理里,显示处理倒是放在了主循环处理中了?感觉逻辑挺奇怪的。一般键盘扫描在主循环中做啊。消除抖动的处理逻辑一般是:判断按键是否按下?是,则延迟20ms后再次检查是不是这个按键被按下。是则继续检测按键是否松开,是则表示一次完整的按键按下和松开。松开那部分也可以不做,主要是避免速度太快,按下还没有松开时,相同处理被多次执行。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表