当前位置:   article > 正文

嵌入式蓝桥杯单按键,双击按键,长按键的实现(含按键消抖)_蓝桥杯嵌入式双击

蓝桥杯嵌入式双击

介绍

          按键消抖:使用定时器每10ms的中断来实现消抖,因为按键的抖动查不到在5-10ms之间,所以使用定时器跳过这10ms的抖动

         按键的单按键,双击按键和长按键使用定时器轮询4个按键+状态机的方式实现

步骤

①cubemx配置

        使用定时器6来实现每10ms轮询4个按键

        开启定时器中断

②代码编写

按键结构体的声明

  1. struct key
  2. {
  3. uint8_t keyJudge; //按键状态机的状态
  4. bool keyState; //按键电平状态
  5. bool keySingle; //单击按键
  6. bool keyDouble; //双击按键
  7. bool keyLong; //长按按键
  8. int keyTime; //用于按键计时
  9. bool keyUp; //检测按键抬起的一瞬间,可用于长按抬手盘判断
  10. bool keyDown; //检测按键按下的一瞬间
  11. };
  12. //按键初始化
  13. struct key keys[4] = {{0,1,0,0,0,0,0,0},{0,1,0,0,0,0,0,0},{0,1,0,0,0,0,0,0},{0,1,0,0,0,0,0,0}};

按键状态机编写

  1. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定时器的中断回调处理函数
  2. {
  3. if(htim->Instance == TIM6)
  4. {
  5. //每10ms获取一次按键状态
  6. keys[0].keyState = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
  7. keys[1].keyState = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
  8. keys[2].keyState = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
  9. keys[3].keyState = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
  10. //使用for循环轮询4个按键
  11. for(int i = 0;i<4;i++)
  12. {
  13. switch(keys[i].keyJudge) //每个按键所处的状态
  14. {
  15. case 0: //按键空闲状态:等待按键按下
  16. {
  17. if(keys[i].keyState==0) //按键按下,进入下一个状态
  18. {
  19. keys[i].keyJudge=1;
  20. }
  21. }
  22. break;
  23. case 1: //按键按下消抖状态
  24. {
  25. if(keys[i].keyState==0) //确认按键按下,进入下一个状态
  26. {
  27. keys[i].keyJudge = 2;
  28. }else{
  29. keys[i].keyJudge = 0; //按键抖动,回到上一个状态
  30. }
  31. }
  32. break;
  33. case 2: //判断是否是长按键
  34. {
  35. if(keys[i].keyState==0)
  36. {
  37. keys[i].keyTime++; //按键按下时,每10ms加1
  38. if(keys[i].keyTime>=100) //按键长按超过1s(10ms*100),确认是长按键
  39. {
  40. keys[i].keyLong = 1;
  41. keys[i].keyJudge=0;
  42. keys[i].keyTime=0;
  43. }
  44. }else{ //按键松手
  45. keys[i].keyJudge=3;
  46. }
  47. }
  48. break;
  49. case 3: //判断是单击还是双击
  50. {
  51. if(keys[i].keyState==1) //如果按键确认松手,进入下一个状态
  52. {
  53. if(keys[i].keyTime<100)
  54. {
  55. keys[i].keyTime=0;
  56. keys[i].keyJudge=4;
  57. }
  58. }else{ //按键抖动,回到上一个状态
  59. keys[i].keyJudge=2;
  60. }
  61. }
  62. break;
  63. case 4: //判断是单击还是双击的状态
  64. {
  65. if(keys[i].keyState==1)
  66. {
  67. keys[i].keyTime++; //按键松手是开始计时
  68. if(keys[i].keyTime>=40) //如果松手超过400ms还没有再次按下按键
  69. {
  70. keys[i].keySingle=1; //单击按键标志位置1
  71. keys[i].keyJudge = 0;
  72. keys[i].keyTime = 0;
  73. }
  74. }else{ //在400ms内检测到按键再次按下,进入下一个状态
  75. keys[i].keyJudge = 5;
  76. }
  77. }
  78. break;
  79. case 5: //按键二次按下消抖
  80. {
  81. if(keys[i].keyState==0)
  82. {
  83. if(keys[i].keyTime<40) //确认是双按键或者长按,进入下一个状态
  84. {
  85. keys[i].keyTime = 0;
  86. keys[i].keyJudge = 6;
  87. }
  88. }else{ //按键抖动,回到上一个状态
  89. keys[i].keyJudge = 4;
  90. }
  91. }
  92. break;
  93. case 6: //按键第二次按下判断是否是长按
  94. {
  95. if(keys[i].keyState==0)
  96. {
  97. keys[i].keyTime++;
  98. if(keys[i].keyTime>=100) //按键按下超过1s,这次按键操作归为长按
  99. {
  100. keys[i].keyLong = 1;
  101. keys[i].keyJudge=0;
  102. keys[i].keyTime=0;
  103. }
  104. }else{ //按键松手
  105. keys[i].keyJudge = 7;
  106. }
  107. }
  108. break;
  109. case 7: //按键松手消抖
  110. {
  111. if(keys[i].keyState==1) //按键确认松手
  112. {
  113. if(keys[i].keyTime<100) //按键不是长按键,则是双击按键
  114. {
  115. keys[i].keyDouble = 1;
  116. }
  117. keys[i].keyJudge = 0;
  118. keys[i].keyTime = 0;
  119. }else{
  120. keys[i].keyJudge = 6;
  121. }
  122. }
  123. break;
  124. }
  125. }
  126. }
  127. }

main函数测试

  1. //main函数测试三个按键模式
  2. if(keys[3].keySingle) //单击,LED1点亮
  3. {
  4. LED1_ON;
  5. keys[3].keySingle = 0;
  6. }
  7. if(keys[3].keyDouble) //双击,LED1熄灭
  8. {
  9. LED1_OFF;
  10. keys[3].keyDouble = 0;
  11. }
  12. if(keys[3].keyLong) //长按,LED1不断翻转
  13. {
  14. LED1_TOGGLE;
  15. keys[3].keyLong = 0;
  16. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/912984
推荐阅读
相关标签
  

闽ICP备14008679号