电竞比分网-中国电竞赛事及体育赛事平台

分享

STM32CubeMX學習教程之三:GPIO輸入之利用SysTick中斷給按鍵去抖

 Allen 圖書館 2019-06-17

本文主要討論軟件去抖。實現(xiàn)方法是通過SysTick中斷每1ms對按鍵進行掃描,當檢測到連續(xù)的穩(wěn)定無抖動電平信號(長度可設置)之后,才進行相應的邏輯操作。

軟件版本:
STM32CubeMX V4.25.0  
System Workbench V2.4

硬件:OneNet 麒麟座V2.3

在STM32CubeMX中新建項目,選擇正確的MCU型號

然后設置RCC和SYS,然后根據(jù)板子實際情況設置時鐘(麒麟座外部晶振是12M,STM32F103x的最高主頻是72M)

然后設置GPIO_Output (連接到LED) 和GPIO_Input(連接到按鍵)。注意上一篇文章里面按鍵連接的引腳設置為外部中斷模式,這里只需要設置為GPIO_Input就可以了。

GPIO_Output的具體設置如下:

GPIO_Input設置如下

這里按鍵我用了SW1/2/3/4。

同樣修改

Project - setting ,ToolChain/IDE選擇 SW4STM32

還要勾選這里

然后生成代碼,打開項目。

編輯stm32f1xx_it.h,函數(shù)聲明那里增加一行 :

void Key_Scan(void);

然后編輯stm32f1xx_it.c 增加如下代碼:

  1. /* USER CODE BEGIN 0 */
  2. uint8_t sw1Count,sw2Count,sw3Count,sw4Count;
  3. uint8_t pushFlag1,pushFlag2,pushFlag3,pushFlag4;
  4. extern uint8_t swState1,swState2,swState3,swState4;
  5. void Key_Scan(void)
  6. {
  7. /*檢測SW1是否按下 */
  8. if( HAL_GPIO_ReadPin(SW1_GPIO_Port,SW1_Pin) == GPIO_PIN_RESET )
  9. {
  10. sw1Count++; //SW1鍵按下,計數(shù)sw1Count加1
  11. if(sw1Count>=32) //1MS中斷一次,sw1Count大于等于32,即按鍵已按下32ms
  12. {
  13. if(pushFlag1==0) //判斷有沒有重按鍵,1為有,0為沒有
  14. {
  15. swState1=1; //設置按鍵標志
  16. sw1Count=0;
  17. pushFlag1=1; //設置重按鍵標志
  18. }
  19. else
  20. sw1Count=0;
  21. }
  22. else
  23. swState1=0;
  24. }
  25. else //無按鍵按下
  26. {
  27. sw1Count=0; //清零sw1Count
  28. swState1=0; //清除按鍵標志
  29. pushFlag1=0; //清除重按鍵標志
  30. }
  31. /*檢測SW2是否按下 */
  32. if( HAL_GPIO_ReadPin(SW2_GPIO_Port,SW2_Pin) == GPIO_PIN_RESET )
  33. {
  34. sw2Count++; //SW2鍵按下,計數(shù)sw2Count加1
  35. if(sw2Count>=32) //1MS中斷一次,sw2Count大于等于32,即按鍵已按下32ms
  36. {
  37. if(pushFlag2==0) //判斷有沒有重按鍵,1為有,0為沒有
  38. {
  39. swState2=1; //設置按鍵標志
  40. sw2Count=0;
  41. pushFlag2=1; //設置重按鍵標志
  42. }
  43. else
  44. sw2Count=0;
  45. }
  46. else
  47. swState2=0;
  48. }
  49. else //無按鍵按下
  50. {
  51. sw2Count=0; //清零sw2Count
  52. swState2=0; //清除按鍵標志
  53. pushFlag2=0; //清除重按鍵標志
  54. }
  55. /*檢測SW3是否按下 */
  56. if( HAL_GPIO_ReadPin(SW3_GPIO_Port,SW3_Pin) == GPIO_PIN_RESET )
  57. {
  58. sw3Count++; //SW3鍵按下,計數(shù)sw3Count加1
  59. if(sw3Count>=32) //1MS中斷一次,sw3Count大于等于32,即按鍵已按下32ms
  60. {
  61. if(pushFlag3==0) //判斷有沒有重按鍵,1為有,0為沒有
  62. {
  63. swState3=1; //設置按鍵標志
  64. sw3Count=0;
  65. pushFlag3=1; //設置重按鍵標志
  66. }
  67. else
  68. sw3Count=0;
  69. }
  70. else
  71. swState3=0;
  72. }
  73. else //無按鍵按下
  74. {
  75. sw3Count=0; //清零sw3Count
  76. swState3=0; //清除按鍵標志
  77. pushFlag3=0; //清除重按鍵標志
  78. }
  79. /*檢測SW4是否按下 */
  80. if( HAL_GPIO_ReadPin(SW4_GPIO_Port,SW4_Pin) == GPIO_PIN_RESET )
  81. {
  82. sw4Count++; //SW4鍵按下,計數(shù)sw4Count加1
  83. if(sw4Count>=32) //1MS中斷一次,sw4Count大于等于32,即按鍵已按下32ms
  84. {
  85. if(pushFlag4==0) //判斷有沒有重按鍵,1為有,0為沒有
  86. {
  87. swState4=1; //設置按鍵標志
  88. sw4Count=0;
  89. pushFlag4=1; //設置重按鍵標志
  90. }
  91. else
  92. sw4Count=0;
  93. }
  94. else
  95. swState4=0;
  96. }
  97. else //無按鍵按下
  98. {
  99. sw4Count=0; //清零sw4Count
  100. swState4=0; //清除按鍵標志
  101. pushFlag4=0; //清除重按鍵標志
  102. }
  103. }
  104. /* USER CODE END 0 */

然后在SysTick中斷處理函數(shù)增加一行 void Key_Scan(void);, 代碼如下:

  1. /**
  2. * @brief This function handles System tick timer.
  3. */
  4. void SysTick_Handler(void)
  5. {
  6. /* USER CODE BEGIN SysTick_IRQn 0 */
  7. Key_Scan();
  8. /* USER CODE END SysTick_IRQn 0 */
  9. HAL_IncTick();
  10. HAL_SYSTICK_IRQHandler();
  11. /* USER CODE BEGIN SysTick_IRQn 1 */
  12. /* USER CODE END SysTick_IRQn 1 */
  13. }

 在gpio.c 中增加如下兩處代碼:

  1. /* USER CODE BEGIN 1 */
  2. GPIO_TypeDef* GPIO_PORT[] = {LED1_GPIO_Port,
  3. LED2_GPIO_Port,
  4. LED3_GPIO_Port,
  5. LED4_GPIO_Port};
  6. const uint16_t GPIO_PIN[] = {LED1_Pin,
  7. LED2_Pin,
  8. LED3_Pin,
  9. LED4_Pin};
  10. /* USER CODE END 1 */
  1. /* USER CODE BEGIN 2 */
  2. void LED_Toggle(Led_TypeDef Led)
  3. {
  4. HAL_GPIO_TogglePin(GPIO_PORT[Led], GPIO_PIN[Led]);
  5. }
  6. /* USER CODE END 2 */

然后編輯main.c,增加如下兩處代碼:

  1. /* USER CODE BEGIN 0 */
  2. uint8_t swState1,swState2,swState3,swState4;
  3. /* USER CODE END 0 */
  1. /* USER CODE BEGIN WHILE */
  2. while (1)
  3. {
  4. if ( swState1 == 1 )
  5. {
  6. LED_Toggle(LED1);
  7. // HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
  8. HAL_Delay(1);
  9. }
  10. if ( swState2 == 1 )
  11. {
  12. LED_Toggle(LED2);
  13. // HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);
  14. HAL_Delay(1);
  15. }
  16. if ( swState3 == 1 )
  17. {
  18. LED_Toggle(LED3);
  19. // HAL_GPIO_TogglePin(LED3_GPIO_Port,LED3_Pin);
  20. HAL_Delay(1);
  21. }
  22. if ( swState4 == 1 )
  23. {
  24. LED_Toggle(LED4);
  25. // HAL_GPIO_TogglePin(LED4_GPIO_Port,LED4_Pin);
  26. HAL_Delay(1);
  27. }
  28. /* USER CODE END WHILE */

注意 如下兩個語句是等效的,我注釋掉了HAL_GPIO_TogglePin()。因為我們使用枚舉重新定義了LED狀態(tài)切換的函數(shù)LED_Toggle()。

  1. 1. LED_Toggle(LED1);
  2. 2. HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);

然后右鍵點擊項目,選擇Properties, Run-Debug Settings, 點擊右側的New,在彈出對話框中選擇Ac6 STM32 Debugging。

然后任務欄上點擊Run圖,當然會報錯的,原因請查看另一篇我的博客(https://blog.csdn.net/toopoo/article/details/79680323),所以需要右鍵點擊  項目名Run.cfg ,給它改個名字,

然后右鍵點擊項目樹里面的項目名稱,選擇“Propeties”,然后在Run/Debug Settings-選擇項目名-Edit-Main-C/C++Application那里點擊“Search Project”,然后選擇出現(xiàn)的默認的elf文件:

然后在Debugger-User Defined-Browse 那里選擇你自己改名的配置文件:

然后右鍵點擊那個新的cfg文件,選擇"Open With - Text Editor", 進行如下更改:

source [find interface/stlink.cfg] 更改為 source [find interface/stlink-v2.cfg]

reset_config srst_only srst_nogate connect_assert_srst 這一行改為 reset_config none 

然后再Run一下,就可以了。

就實現(xiàn)四個按鍵分別控制LED的開關切換并實現(xiàn)了軟件去抖,不會產生誤動作了。

本文參考了如下文章:

http://www./study/article-630-1.html

https://blog.csdn.net/yongyooh/article/details/21877227

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多