stm32按键 长按 短按 函数 一

发布时间 2023-07-21 08:50:18作者: SymPny

 

在stm32工程中,长按和短按的代码书写, 调用的读取按键状态的底层函数。封装成的按键函数代码。下面是函数的头文件,和.c文件的代码。使用定时器来扫描按键。

  1. #define KEY_ON 1
  2. #define KEY_OFF 0
  3. #define KEY_NULL 0
  4. #define KEY_SHORT 1
  5. #define KEY_LONG 10
  6. #define SHORT_TIME 200
  1. uint8_t Key_state(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
  2. {
  3. static uint8_t key_value = KEY_NULL;
  4. static uint16_t longtime;
  5. if( (longtime == 0) && (key_value != KEY_NULL)) //当按键状态为长按或者短按时,而longtime 不为零,则按键状态清零
  6. {
  7. key_value = KEY_NULL;
  8. }
  9. if ( time == 5 ) /* 5 * 1 ms = 5ms 定时时间到 */
  10. {
  11. time = 0;
  12. if(KEY_PRESS(GPIOx,GPIO_Pin)) //按键按下
  13. {
  14. longtime++;
  15. }
  16. else //按键松开
  17. {
  18. if((longtime >= 3) && (longtime <= SHORT_TIME)) //短按
  19. {
  20. key_value = KEY_SHORT;
  21. }
  22. else if( longtime > SHORT_TIME ) //长按
  23. {
  24. key_value = KEY_LONG;
  25. }
  26. else //去抖动
  27. {
  28. key_value = KEY_NULL;
  29. }
  30. longtime = 0; //清零
  31. }
  32. }
  33. return key_value;
  34. }

上面的代码,是按键松开才能判断按键的状态,是长按还是短按。在实际项目中我需要,按键按下一段时间后,判断为按键长按,不用松开,返回按键长按。参考网上的代码,使用状态机写了如下代码

  1. #define KEY_PRESS(GPIOx,GPIO_Pin) GPIO_ReadInputDataBit(GPIOx,GPIO_Pin)
  2. #define KEY_INPUT KEY_PRESS(GPIOx,GPIO_Pin) //读取按键状态
  3. #define KEY_STATE_0 0 // 按键状态位
  4. #define KEY_STATE_1 1
  5. #define KEY_STATE_2 2
  6. #define KEY_STATE_3 3
  7. #define LONG_KEY_TIME 300 //长按的3秒时间
  8. #define SINGLE_KEY_TIME 3 // 短按的消抖时间
  9. #define N_KEY 0 // 无状态
  10. #define S_KEY 1 // 单击
  11. #define L_KEY 10 // 长按

 

 

 

 

 

 

函数的主体部分,代码中按下按键读取到高电平。

  1. unsigned char key_driver(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin))
  2. {
  3. static unsigned char key_state = 0; // 按键状态变量
  4. static unsigned int key_time = 0; // 按键计时变量
  5. unsigned char key_press, key_return;
  6. key_return = N_KEY; // 清除 返回按键值
  7. key_press = KEY_INPUT; // 读取当前键值
  8. switch (key_state)
  9. {
  10. case KEY_STATE_0: // 按键状态0:判断有无按键按下
  11. if (key_press == KEY_ON) // 有按键按下
  12. {
  13. key_time = 0; // 清零时间间隔计数
  14. key_state = KEY_STATE_1; // 然后进入 按键状态1
  15. }
  16. break;
  17. case KEY_STATE_1: // 按键状态1:软件消抖(确定按键是否有效,而不是误触)。按键有效的定义:按键持续按下超过设定的消抖时间。
  18. if (key_press == KEY_ON)
  19. {
  20. key_time++; // 一次10ms
  21. if(key_time>=SINGLE_KEY_TIME) // 消抖时间为:SINGLE_KEY_TIME*10ms = 30ms;
  22. {
  23. key_state = KEY_STATE_2; // 如果按键时间超过 消抖时间,即判定为按下的按键有效。按键有效包括两种:单击或者长按,进入 按键状态2, 继续判定到底是那种有效按键
  24. }
  25. }
  26. else key_state = KEY_STATE_0; // 如果按键时间没有超过,判定为误触,按键无效,返回 按键状态0,继续等待按键
  27. break;
  28. case KEY_STATE_2: // 按键状态2:判定按键有效的种类:是单击,还是长按
  29. if(key_press == KEY_OFF) // 如果按键在 设定的长按时间 内释放,则判定为单击
  30. {
  31. key_return = S_KEY; // 返回 有效按键值:单击
  32. key_state = KEY_STATE_0; // 返回 按键状态0,继续等待按键
  33. }
  34. else
  35. {
  36. key_time++;
  37. if(key_time >= LONG_KEY_TIME) // 如果按键时间超过 设定的长按时间(LONG_KEY_TIME*10ms=200*10ms=2000ms), 则判定为 长按
  38. {
  39. key_return = L_KEY; // 返回 有效键值值:长按
  40. key_state = KEY_STATE_3; // 去状态3,等待按键释放
  41. }
  42. }
  43. break;
  44. case KEY_STATE_3: // 等待按键释放
  45. if (key_press == KEY_OFF)
  46. {
  47. key_state = KEY_STATE_0; // 按键释放后,进入 按键状态0 ,进行下一次按键的判定
  48. }
  49. break;
  50. default: // 特殊情况:key_state是其他值得情况,清零key_state。这种情况一般出现在 没有初始化key_state,第一次执行这个函数的时候
  51. key_state = KEY_STATE_0;
  52. break;
  53. }
  54. return key_return; // 返回 按键值
  55. }
  1. unsigned char key_handle(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
  2. {
  3. unsigned char key_value;
  4. if ( time >= 10 ) /* 10 * 1 ms = 10ms 定时器 */
  5. {
  6. time = 0;
  7. key_value = key_driver(GPIOx,GPIO_Pin);
  8. }
  9. return key_value;
  10. }

time 这个变量,定义在了定时器文件中

 在main.c中调用

  1. int main(void)
  2. {
  3. int8_t key_value;
  4. /* led 初始化*/
  5. LED_GPIO_Config();
  6. BASIC_TIM_Init();
  7. Key_GPIO_Config();
  8. while(1)
  9. {
  10. // key_value = Key_state(KEY1_GPIO_PORT,KEY1_GPIO_PIN);
  11. key_value = key_handle(KEY1_GPIO_PORT,KEY1_GPIO_PIN);
  12. if(key_value == KEY_SHORT)
  13. {
  14. LED1_TOGGLE;
  15. }
  16. else if(key_value == KEY_LONG)
  17. {
  18. LED2_TOGGLE;
  19. }
  20. }
  21. }

这样可以实现长按不松手,执行长按的代码。以后遇到好的思想会继续学习,总结下来。

代码风格不是特别好,很早之前写的了,放在这里了,仅供参考

链接    提取码:66zh

 

https://blog.csdn.net/xiaohu1996/article/details/103236089

这个是我写的按键二的博客,一些思想可以提供学习