找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机状态机来扫描键盘程序 调时状态加减会出问题

[复制链接]
跳转到指定楼层
楼主
ID:1095802 发表于 2023-10-25 17:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用状态机来扫描键盘,有时按了会出现错乱,不知道哪里出问题了
单片机源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #define SXLed_P P0
  4. #define K5 0x07
  5. #define K4 0x0b
  6. #define K3 0x0d
  7. #define K2 0x0e
  8. unsigned int i;
  9. unsigned char KeyValue,KeyValueTemp,StateNo,Flag_Time;
  10. bit Flag_05s,Flag_1s,Flag_Change,Flag_Hide;                                                        //位标志
  11. unsigned char SX[8];                        //数码管数据缓存,位标志
  12. unsigned char Hour,Minute,Second;        //时分秒
  13. sbit SXLed_W=P2^7;                                //数码管位选
  14. sbit SXLed_D=P2^6;                                //数码管段选
  15. sbit bp=P2^3;
  16. unsigned  char code Number[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7F,
  17. 0x6F,0x40,0x80,0x00};                                //共阴极数码管0-9-.灭
  18. void Delay(unsigned char ); //毫秒延时函数
  19. void Init(void);                                                //数据初始化函数
  20. void T0_Init(void);                                        //T0中断初始化函数
  21. void SXLed (unsigned char location,unsigned char Num);//数码管显示函数
  22. void Start_Screen(void);                //开机显示画面函数
  23. void Time(void);                                                //时分秒进位函数
  24. void Hex_BCD(void);                                        //数据转换并送到数码管数缓存函数
  25. void KeyScan(void);                                        //按键扫描函数(状态机法)
  26. void KeyProcess(void);                        //按键处理函数
  27. void main(void)
  28. {
  29.         Delay(100);                                                                //开机延时
  30.         Init();                                                                                //变量初始化                                
  31.         T0_Init();                                                                //定时器T0初始化
  32.   Start_Screen();                                                //开机画面
  33. //        P1=0x00;
  34.         while(1)
  35.         {        
  36.                 if(Flag_05s==1)        //0.5秒到了
  37.                 {        
  38.                         Flag_05s=0;//0.5秒到状态清0
  39.                         Hex_BCD();//数据转换并送到数码管数缓存
  40.                         if(Flag_Change!=0)//调时状态
  41.                         {
  42.                                 Flag_Hide=!Flag_Hide;//隐藏标志
  43.                                 if ((Flag_Hide==1)&&(Flag_Time==0))//调时状态时闪烁
  44.                                 {
  45.                                         SX[7]=12;
  46.                                         SX[6]=12;
  47.                                 }
  48.                                 if ((Flag_Hide==1)&&(Flag_Time==1))//调时状态分闪烁
  49.                                 {
  50.                                         SX[4]=12;
  51.                                         SX[3]=12;
  52.                                 }
  53.                                 if ((Flag_Hide==1)&&(Flag_Time==2))//调时状态秒闪烁
  54.                                 {
  55.                                         SX[1]=12;
  56.                                         SX[0]=12;
  57.                                 }
  58.                         }
  59.                 }        
  60.         }                        
  61. }
  62. void Init(void)
  63. {
  64.         i=0;
  65.         Hour=23;
  66.         Minute=59;
  67.         Second=50;
  68.         Flag_05s=0;
  69.         Flag_1s=0;
  70.         Flag_Change=0;
  71.         Flag_Hide=0;
  72.         StateNo=1;
  73.         KeyValue=0;
  74.         KeyValueTemp=0;
  75.         Flag_Time=0;
  76. }
  77. void T0_Timer(void) interrupt 1
  78. {
  79.         TH0=0xf8;                                                                        //定时2毫秒高四位初值重装
  80.         TL0=0xcd;                                                                        //定时2毫秒高四位初值重装
  81.         SXLed(i%8,SX[i%8]);                                //数码管扫描显示
  82.         i++;
  83.         if(!(i%5))        KeyScan();                //按键扫描
  84.         if(!(i%250))                                                        //0.5秒到了
  85.         {        
  86. //                P1=~P1;                                                                //指示灯0.5秒交替闪烁
  87.                 Flag_05s=1;                                                        //0.5秒标志置1
  88.                 Flag_1s=!Flag_1s;                                //1秒标志置取反
  89.                 if(Flag_1s==0)                                        //1秒到了
  90.                         if(Flag_Change==1)                //是否调时状态
  91.                                 _nop_();                                                //是,啥也不干
  92.                         else
  93.                         Time();                                                                //否,时间变动
  94.         }
  95. }

  96. void         KeyProcess(void)
  97. {
  98.         switch (KeyValue)
  99.         {
  100.                 case K2:
  101.                                                 if(Flag_Change==1)
  102.                                                 {
  103.                                                         Flag_Time++;
  104.                                                         if(Flag_Time==3)Flag_Time=0;
  105.                                                 }
  106.                                                 break;
  107.                 case K3:
  108.                                                 if(Flag_Change==1)
  109.                                                 {
  110.                                                         if(Flag_Time==0)        
  111.                                                         {
  112.                                                                 Hour++;
  113.                                                                 if(Hour==23)Hour=0;
  114.                                                         }
  115.                                                         if(Flag_Time==1)        
  116.                                                         {
  117.                                                                 Minute++;
  118.                                                                 if(Minute==59)Minute=0;
  119.                                                         }
  120.                                                         if(Flag_Time==2)        
  121.                                                         {
  122.                                                                 Second++;
  123.                                                                 if(Second==59)Second=0;
  124.                                                         }
  125.                                                 }        
  126.                                                 break;                                       
  127.                 case K4:
  128.                                                 if(Flag_Change==1)
  129.                                                 {
  130.                                                         if(Flag_Time==0)        
  131.                                                         {
  132.                                                                 Hour--;
  133.                                                                 if(Hour==0)Hour=23;
  134.                                                         }
  135.                                                         if(Flag_Time==1)        
  136.                                                         {
  137.                                                                 Minute--;
  138.                                                                 if(Minute==0)Minute=59;
  139.                                                         }
  140.                                                         if(Flag_Time==2)        
  141.                                                         {
  142.                                                                 Second--;
  143.                                                                 if(Second==0)Second=59;
  144.                                                         }
  145.                                                 }
  146.                                                 break;
  147.                 case K5:        
  148.                                                 if(Flag_Change==0)
  149.                                                         Flag_Change=1;
  150.                                                 else
  151.                                                         Flag_Change=0;
  152.                                                 break;
  153.                 default:
  154.                                                 Flag_Change=0;        
  155.                                                 break;        
  156.         }
  157. }
  158. void KeyScan(void)
  159. {
  160.         P3=P3|0x0f;
  161.         if (StateNo==1)
  162.         {
  163.                 if ((P3&0x0f)!=0x0f)
  164.                         StateNo=2;
  165.                 else
  166.                         StateNo=1;
  167.         }
  168.         else if (StateNo==2)
  169.         {
  170.                 if ((P3&0x0f)!=0x0f)
  171.                 {
  172.                         KeyValueTemp=P3&0x0f;
  173.                         StateNo=3;
  174.                 }
  175.                 else
  176.                         StateNo=1;               
  177.         }        
  178.         else if (StateNo==3)
  179.         {
  180.                 if ((P3&0x0f)==0x0f)
  181.                 {
  182.                         KeyValue=KeyValueTemp;
  183.                         StateNo=4;
  184.                 }
  185.                 else
  186.                 {
  187.                         ;
  188.                 }        
  189.         }
  190.         else if (StateNo==4)
  191.         {
  192.                 KeyProcess();
  193.                 StateNo=1;
  194.         }
  195.         else
  196.                 StateNo=1;               
  197. }
  198. void Hex_BCD(void)
  199. {
  200.         SX[0]=Second%10;
  201.         SX[1]=Second/10;
  202.         SX[2]=10;
  203.         SX[3]=Minute%10;
  204.         SX[4]=Minute/10;
  205.         SX[5]=10;
  206.         SX[6]=Hour%10;
  207.         SX[7]=Hour/10;
  208. }
  209. void Time(void)
  210. {
  211.         Second++;
  212.         if (Second==60)
  213.         {
  214.                 Second=0;
  215.                 Minute++;
  216.                 if(Minute==60)
  217.                 {
  218.                         Minute=0;
  219.                         Hour++;
  220.                         if(Hour==24)Hour=0;
  221.                 }
  222.         }
  223. }
  224. void T0_Init(void)
  225. {
  226.         TMOD|=0x01;                                                                //定时器T0工作在16位定时模式
  227.         EA=1;                                                                                        //开总中断
  228.         ET0=1;                                                                                //开定时器中断
  229.         TR0=1;                                                                                //启动定时器
  230.         TH0=0xf8;                                                                        //定时2毫秒高四位初值重装
  231.         TL0=0xcd;                                                                        //定时2毫秒高四位初值重装
  232. }
  233. void SXLed (unsigned char location,unsigned char Num)//location显示位置,num显示数字
  234. {
  235.         SXLed_P=0xff;                                                                        //消影
  236.         SXLed_W=1;                                                                                //打开位选锁存器
  237.         SXLed_P=~(0x80>>location);                //送位码
  238.         SXLed_W=0;                                                                                //锁存位选数据
  239.         SXLed_D=1;                                                                                //打开段选锁存器
  240.         SXLed_P=Number[Num];                                        //送段码
  241.         SXLed_D=0;                                                                                //锁存段选数据
  242. }
  243. void Start_Screen(void)                                        //开机显示画面
  244. {
  245.         unsigned char k,j;
  246.         for (k=0;k<11;k++)
  247.         {
  248.                 for (j=0;j<8;j++)
  249.                         if(k==0)
  250.                                 SX[j]=10;
  251.                         else
  252.                                 SX[j]=k-1;
  253.                 Delay(1000);
  254.         }
  255. }
  256. void Delay(unsigned char ms)                        //@11.0592MHz延时
  257. {
  258.         unsigned char data i, j;
  259.         while(ms--)
  260.         {
  261.                 _nop_();
  262.                 i = 2;
  263.                 j = 198;
  264.                 do
  265.                 {
  266.                         while (--j);
  267.                 } while (--i);
  268.         }
  269. }
复制代码

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2023-10-25 21:01 | 只看该作者
void KeyProcess(void)
{
        switch(KeyValue)
        {
                case K2:/* */break;
                case K3:/* */break;
                case K4:/* */break;
                case K5:/* */break;
        }
        KeyValue=0x00;//键值用后要清0
}

void KeyScan(void)
{
        P3=0x0f;
        if(P3!=0x0f)
                KeyValue=P3;
        KeyProcess();
}
回复

使用道具 举报

板凳
ID:1095802 发表于 2023-10-26 15:31 | 只看该作者
wulin 发表于 2023-10-25 21:01
void KeyProcess(void)
{
        switch(KeyValue)

你这样就不是用状态机的方式了,我找到原因了,是值设置的不对,还有调时进去时默认改时。
                case K3:
                                                if(Flag_Change==1)
                                                {
                                                        if(Flag_Time==0)       
                                                        {
                                                                Hour++;
                                                                if(Hour==24)Hour=0;
                                                        }
                                                        if(Flag_Time==1)       
                                                        {
                                                                Minute++;
                                                                if(Minute==60)Minute=0;
                                                        }
                                                        if(Flag_Time==2)       
                                                        {
                                                                Second++;
                                                                if(Second==60)Second=0;
                                                        }
                                                }       
                                                break;                       
case K4:
                                                if(Flag_Change==1)
                                                {
                                                        if(Flag_Time==0)       
                                                        {
                                                                Hour--;
                                                                if(Hour==255)Hour=23;
                                                        }
                                                        if(Flag_Time==1)       
                                                        {
                                                                Minute--;
                                                                if(Minute==255)Minute=59;
                                                        }
                                                        if(Flag_Time==2)       
                                                        {
                                                                Second--;
                                                                if(Second==255)Second=59;
                                                        }
                                                }
                                                break;
                case K5:       
                                                if(Flag_Change==0)
                                                {
                                                        Flag_Change=1;
                                                        Flag_Time=0;
                                                }
                                                else
                                                        Flag_Change=0;
                                                break;
、、、、、、、、、、、、、、、、、、、、、、、、、、、

回复

使用道具 举报

地板
ID:1097455 发表于 2023-10-27 09:27 | 只看该作者
大体看了一下你的代码框架,写8位机思路是对的,但是按键的处理是不建议放中段处理的,你中断定时到了后,在While大循环里去刷新按键进行消抖        
keytemp=0;
  if(pin_adkey==0)     //               adckeyvolt<=20      
        {
                  keytemp=1;
        }

直接向上面给出键值而后对键值进行定时刷新
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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