shgdd520com 发表于 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就说明有键按下,就开始执行变量加一,再打印输出。是按键按下就执行了,我现在想要等按键放开的时候再执行变量加一以及打印输出,该怎么检测啊?谢谢!!

machao 发表于 2010-4-7 21:45:00

1. 你为什么要“等按键放开的时候再执行变量加一以及打印输出”?如果用户不熟悉的话,会一直按着不放,等着打印输出。如果该键的功能是单一的,不需要区分短按和长按的话,还是只要确认有按键按下,不管是否已经释放,都执行按键处理。这个按键扫描的代码不管是短按,还是长按,都是确定只有一次按键按下的。

2。如果你喜欢“等按键放开的时候再执行变量加一以及打印输出”,改动也是非常简单的,就是一条指令的位置变化。为什么你不会仔细体会这个代码,自己做修改尝试呢?连20行不到的代码都不能体会里面的思路与方法,那以后如何设计更复杂的东西。

shgdd520com 发表于 2010-4-9 08:57:44

谢谢马老师,昨天晚上回家,修改了程序,已经改成可以按键放开后执行了。有看了琢磨了状态机,看来真的还不错!谢谢!!!

shgdd520com 发表于 2010-4-9 09:02:10

马老师,这个状态图还不会怎么看?谢谢

http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_544679.JPG
(原文件名:未命名.JPG)

rundream 发表于 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;
    }
}

jxchen 发表于 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 輸出
                   }
                         }
               }
页: [1]
查看完整版本: 一个按键状态机程序怎么检测等待按键释放后执行相关处理程序?