amoBBS 阿莫电子论坛

 找回密码
 注册
搜索
bottom↓
查看: 6141|回复: 5

一个按键状态机程序怎么检测等待按键释放后执行相关处理程序?

[复制链接]
发表于 2010-4-7 16:50:52 | 显示全部楼层 |阅读模式
bit flag_keyscan_enable = 0;


unsigned char read_key(void)//马老师状态扫描按键
{
                static unsigned char key_state = 0;
                unsigned char key_press, key_return = 0;

                key_press = key_input;                                // 读按键I/O电平
                _nop_();
                key_press = key_input;                                // 读按键I/O电平

                switch (key_state)
                {
                        case key_state_0:                                // 按键初始态
                                if (!key_press)
                                {
                                        key_state = key_state_1; //键被按下,状态转换到键确认态
                                }
                                break;
                        case key_state_1:                                // 按键确认态
                                if (!key_press)
                                {
                                        key_return = 1;                         // 按键仍按下,按键确认输出为"1" (1)
                                        key_state = key_state_2; //状态转换到键释放态
                                }
                                else
                                        {
                                                key_state = key_state_0; //按键已抬起,转换到按键初始态
                                        }       
                                break;
                        case key_state_2:
                                if (key_press)
                                {
                                        key_state = key_state_0; //按键已释放,转换到按键初始态
                                }
                                break;
                }       
            return key_return;
}


while(1)//主函数循环
                 {
                         v_ClockUpdata_f();
                         
                         if(flag_keyscan_enable)//10ms定时扫描键盘
                         {         
                                 flag_keyscan_enable = 0;//
                                 if(read_key()) // 返回1 变量加一,
                                {       
                                           Count_number ++;                               
                                        if(Count_number > 999)//如果大于999,计数器置1从头开始
                                        {
                                                Count_number = 1;
                                        }                                                                        
                                   Print_data(); //打印输出函数,将变量Counter_number 输出
                                }
                         }
                 }

请教马老师及大家们,学习了马老师的状态机按键。检测一个按键成功了。但是现在有个问题是:主程序里我这样写的话好像就是函数返回1就说明有键按下,就开始执行变量加一,再打印输出。是按键按下就执行了,我现在想要等按键放开的时候再执行变量加一以及打印输出,该怎么检测啊?谢谢!!
发表于 2010-4-7 21:45:00 | 显示全部楼层
1. 你为什么要“等按键放开的时候再执行变量加一以及打印输出”?如果用户不熟悉的话,会一直按着不放,等着打印输出。如果该键的功能是单一的,不需要区分短按和长按的话,还是只要确认有按键按下,不管是否已经释放,都执行按键处理。这个按键扫描的代码不管是短按,还是长按,都是确定只有一次按键按下的。

2。如果你喜欢“等按键放开的时候再执行变量加一以及打印输出”,改动也是非常简单的,就是一条指令的位置变化。为什么你不会仔细体会这个代码,自己做修改尝试呢?连20行不到的代码都不能体会里面的思路与方法,那以后如何设计更复杂的东西。
 楼主| 发表于 2010-4-9 08:57:44 | 显示全部楼层
谢谢马老师,昨天晚上回家,修改了程序,已经改成可以按键放开后执行了。有看了琢磨了状态机,看来真的还不错!谢谢!!!
 楼主| 发表于 2010-4-9 09:02:10 | 显示全部楼层
马老师,这个状态图还不会怎么看?谢谢


(原文件名:未命名.JPG)
发表于 2015-6-19 22:50:03 | 显示全部楼层
//在定时器中,定时10ms,定时到后在中断服务程序中调用上述函数,
//每次执行的间隔10ms,可以有效的消除消抖,提高CPU的利用率。
//PTD10,11,12,13,14
#include "key.h"
uint8 kk=0; //六个按键标志
uint8 rr=0; //松手检测标志位
void key_gpio_init()
{
  GPIO_InitTypeDef gpio_init;
  gpio_init.GPIO_PTx=PTD;
  gpio_init.GPIO_Pins=GPIO_Pin10|GPIO_Pin11|GPIO_Pin12|GPIO_Pin13|GPIO_Pin14;
  gpio_init.GPIO_PinControl=INPUT_PULL_UP|INPUT_PF_EN;
  gpio_init.GPIO_Dir=DIR_INPUT;
  LPLD_GPIO_Init(gpio_init); //GPIO通用初始化函数.0--配置错误;1--配置成功
}
void key_scan()
{
    static enum key_states_e key_state=KEY_S1; //声明枚举变量,并且赋予枚举值
    switch(key_state)
    {
        case KEY_S1:         //按下
          {
            if((PTD10_I==0)||(PTD11_I==0)||(PTD12_I==0)||(PTD13_I==0)||(PTD14_I==0)) key_state = KEY_S2;
            else key_state = KEY_S1;
            break;
          }
        case KEY_S2:        //防抖
          {
            if((PTD10_I==0)||(PTD11_I==0)||(PTD12_I==0)||(PTD13_I==0)||(PTD14_I==0))
            {
               key_state = KEY_S3;
               if(PTD10_I==0) rr=1;      //用于确定是哪个按键再松手之前按下
               if(PTD11_I==0) rr=2;
               if(PTD12_I==0) rr=3;
               if(PTD13_I==0) rr=4;
               if(PTD14_I==0) rr=5;
            }
            else key_state = KEY_S1;
            break;
          }
        case KEY_S3:        //松手
          {
            if((PTD10_I==1)&&(PTD11_I==1)&&(PTD12_I==1)&&(PTD13_I==1)&&(PTD14_I==1))
            {
               key_state = KEY_S1;
               if(rr==1) {rr=0;kk=1;}
               if(rr==2) {rr=0;kk=2;}
               if(rr==3) {rr=0;kk=3;}
               if(rr==4) {rr=0;kk=4;}
               if(rr==5) {rr=0;kk=5;}
            }
//            else key_state = KEY_S1;   //此语句应删除
            break;
          }
        default:
            key_state = KEY_S1;
            break;
    }
}
发表于 2016-6-5 18:20:01 | 显示全部楼层
試看看是否有達到你要的功能


bit flag_keyscan_enable = 0;

unsigned char read_key(void)//馬老師狀態掃瞄按鍵
{
                static unsigned char key_state = 0;
                unsigned char key_press, key_return = 0;

                key_press = key_input;                                // 讀按鍵I/O電平
                _nop_();
                key_press = key_input;                                // 讀按鍵I/O電平

                switch (key_state)
                {
                        case key_state_0:                                // 按鍵初始態
                                if (!key_press)
                                {
                                        key_state = key_state_1; //鍵被按下,狀態轉換到鍵確認態
                                }
                                break;
                        case key_state_1:                                // 按鍵確認態
                                if (!key_press)
                                {
                                        key_return = 1;                         // 按鍵仍按下,按鍵確認輸出為"1" (1)
                                        key_state = key_state_2; //狀態轉換到鍵釋放態
                                }
                                else
                                        {
                                                key_state = key_state_0; //按鍵已抬起,轉換到按鍵初始態
                                        }        
                                break;
                        case key_state_2:
                                if (key_press)
                                {
                                        key_state = key_state_0; //按鍵已釋放,轉換到按鍵初始態
                       key_return =2;
                                }
                                break;
                }        
            return key_return;
}


while(1)//主函數循環
      {
                         v_ClockUpdata_f();
                        
                         if(flag_keyscan_enable)//10ms定時掃瞄鍵盤
              {         
                                 flag_keyscan_enable = 0;//
                                 if(read_key()==2) // 返回1 變數加一,
                   {        
                                                               
                                        if(++Count_number > 999)//如果大於999,計數器置1從頭開始
                        {
                                                Count_number = 1;
                                         }                                                                        
                                                  Print_data(); //列印輸出函數,將變數Counter_number 輸出
                   }
                         }
                 }
友情提示:标题不合格、重复发帖,将会被封锁ID。详情请参考:论坛通告:封锁ID、获得注册邀请码、恢复被封ID、投诉必读
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|阿莫电子论坛(原ourAVR/ourDEV) ( 公安备案:44190002001997(交互式论坛) 工信部备案:粤ICP备09047143号 )

GMT+8, 2019-8-22 07:42

阿莫电子论坛, 原"中国电子开发网"

© 2004-2018 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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