軟件版本:
STM32CubeMX V4.25.0
System Workbench V2.4
硬件:OneNet 麒麟座V2.3
在STM32CubeMX中新建項(xiàng)目,選擇正確的MCU型號(hào)
然后設(shè)置RCC和SYS,然后根據(jù)板子實(shí)際情況設(shè)置時(shí)鐘(麒麟座外部晶振是12M,STM32F103x的最高主頻是72M)
然后設(shè)置GPIO_Output (連接到LED) 和GPIO_Input(連接到按鍵)。注意上一篇文章里面按鍵連接的引腳設(shè)置為外部中斷模式,這里只需要設(shè)置為GPIO_Input就可以了。
GPIO_Output的具體設(shè)置如下:
GPIO_Input設(shè)置如下
這里按鍵我用了SW1/2/3/4。
同樣修改
Project - setting ,ToolChain/IDE選擇 SW4STM32
還要勾選這里
然后生成代碼,打開項(xiàng)目。
編輯stm32f1xx_it.h,函數(shù)聲明那里增加一行 :
void Key_Scan(void);
然后編輯stm32f1xx_it.c 增加如下代碼:
- /* USER CODE BEGIN 0 */
- uint8_t sw1Count,sw2Count,sw3Count,sw4Count;
- uint8_t pushFlag1,pushFlag2,pushFlag3,pushFlag4;
- extern uint8_t swState1,swState2,swState3,swState4;
- void Key_Scan(void)
- {
- /*檢測(cè)SW1是否按下 */
- if( HAL_GPIO_ReadPin(SW1_GPIO_Port,SW1_Pin) == GPIO_PIN_RESET )
- {
- sw1Count++; //SW1鍵按下,計(jì)數(shù)sw1Count加1
- if(sw1Count>=32) //1MS中斷一次,sw1Count大于等于32,即按鍵已按下32ms
- {
- if(pushFlag1==0) //判斷有沒(méi)有重按鍵,1為有,0為沒(méi)有
- {
- swState1=1; //設(shè)置按鍵標(biāo)志
- sw1Count=0;
- pushFlag1=1; //設(shè)置重按鍵標(biāo)志
- }
- else
- sw1Count=0;
- }
- else
- swState1=0;
- }
- else //無(wú)按鍵按下
- {
- sw1Count=0; //清零sw1Count
- swState1=0; //清除按鍵標(biāo)志
- pushFlag1=0; //清除重按鍵標(biāo)志
- }
- /*檢測(cè)SW2是否按下 */
- if( HAL_GPIO_ReadPin(SW2_GPIO_Port,SW2_Pin) == GPIO_PIN_RESET )
- {
- sw2Count++; //SW2鍵按下,計(jì)數(shù)sw2Count加1
- if(sw2Count>=32) //1MS中斷一次,sw2Count大于等于32,即按鍵已按下32ms
- {
- if(pushFlag2==0) //判斷有沒(méi)有重按鍵,1為有,0為沒(méi)有
- {
- swState2=1; //設(shè)置按鍵標(biāo)志
- sw2Count=0;
- pushFlag2=1; //設(shè)置重按鍵標(biāo)志
- }
- else
- sw2Count=0;
- }
- else
- swState2=0;
- }
- else //無(wú)按鍵按下
- {
- sw2Count=0; //清零sw2Count
- swState2=0; //清除按鍵標(biāo)志
- pushFlag2=0; //清除重按鍵標(biāo)志
- }
- /*檢測(cè)SW3是否按下 */
- if( HAL_GPIO_ReadPin(SW3_GPIO_Port,SW3_Pin) == GPIO_PIN_RESET )
- {
- sw3Count++; //SW3鍵按下,計(jì)數(shù)sw3Count加1
- if(sw3Count>=32) //1MS中斷一次,sw3Count大于等于32,即按鍵已按下32ms
- {
- if(pushFlag3==0) //判斷有沒(méi)有重按鍵,1為有,0為沒(méi)有
- {
- swState3=1; //設(shè)置按鍵標(biāo)志
- sw3Count=0;
- pushFlag3=1; //設(shè)置重按鍵標(biāo)志
- }
- else
- sw3Count=0;
- }
- else
- swState3=0;
- }
- else //無(wú)按鍵按下
- {
- sw3Count=0; //清零sw3Count
- swState3=0; //清除按鍵標(biāo)志
- pushFlag3=0; //清除重按鍵標(biāo)志
- }
- /*檢測(cè)SW4是否按下 */
- if( HAL_GPIO_ReadPin(SW4_GPIO_Port,SW4_Pin) == GPIO_PIN_RESET )
- {
- sw4Count++; //SW4鍵按下,計(jì)數(shù)sw4Count加1
- if(sw4Count>=32) //1MS中斷一次,sw4Count大于等于32,即按鍵已按下32ms
- {
- if(pushFlag4==0) //判斷有沒(méi)有重按鍵,1為有,0為沒(méi)有
- {
- swState4=1; //設(shè)置按鍵標(biāo)志
- sw4Count=0;
- pushFlag4=1; //設(shè)置重按鍵標(biāo)志
- }
- else
- sw4Count=0;
- }
- else
- swState4=0;
- }
- else //無(wú)按鍵按下
- {
- sw4Count=0; //清零sw4Count
- swState4=0; //清除按鍵標(biāo)志
- pushFlag4=0; //清除重按鍵標(biāo)志
- }
- }
- /* USER CODE END 0 */
然后在SysTick中斷處理函數(shù)增加一行 void Key_Scan(void);, 代碼如下:
- /**
- * @brief This function handles System tick timer.
- */
- void SysTick_Handler(void)
- {
- /* USER CODE BEGIN SysTick_IRQn 0 */
- Key_Scan();
- /* USER CODE END SysTick_IRQn 0 */
- HAL_IncTick();
- HAL_SYSTICK_IRQHandler();
- /* USER CODE BEGIN SysTick_IRQn 1 */
- /* USER CODE END SysTick_IRQn 1 */
- }
在gpio.c 中增加如下兩處代碼:
- /* USER CODE BEGIN 1 */
- GPIO_TypeDef* GPIO_PORT[] = {LED1_GPIO_Port,
- LED2_GPIO_Port,
- LED3_GPIO_Port,
- LED4_GPIO_Port};
- const uint16_t GPIO_PIN[] = {LED1_Pin,
- LED2_Pin,
- LED3_Pin,
- LED4_Pin};
- /* USER CODE END 1 */
- /* USER CODE BEGIN 2 */
- void LED_Toggle(Led_TypeDef Led)
- {
- HAL_GPIO_TogglePin(GPIO_PORT[Led], GPIO_PIN[Led]);
- }
- /* USER CODE END 2 */
然后編輯main.c,增加如下兩處代碼:
- /* USER CODE BEGIN 0 */
- uint8_t swState1,swState2,swState3,swState4;
- /* USER CODE END 0 */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- if ( swState1 == 1 )
- {
- LED_Toggle(LED1);
- // HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
- HAL_Delay(1);
- }
- if ( swState2 == 1 )
- {
- LED_Toggle(LED2);
- // HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);
- HAL_Delay(1);
- }
- if ( swState3 == 1 )
- {
- LED_Toggle(LED3);
- // HAL_GPIO_TogglePin(LED3_GPIO_Port,LED3_Pin);
- HAL_Delay(1);
- }
- if ( swState4 == 1 )
- {
- LED_Toggle(LED4);
- // HAL_GPIO_TogglePin(LED4_GPIO_Port,LED4_Pin);
- HAL_Delay(1);
- }
- /* USER CODE END WHILE */
注意 如下兩個(gè)語(yǔ)句是等效的,我注釋掉了HAL_GPIO_TogglePin()。因?yàn)槲覀兪褂妹杜e重新定義了LED狀態(tài)切換的函數(shù)LED_Toggle()。
- 1. LED_Toggle(LED1);
- 2. HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
然后右鍵點(diǎn)擊項(xiàng)目,選擇Properties, Run-Debug Settings, 點(diǎn)擊右側(cè)的New,在彈出對(duì)話框中選擇Ac6 STM32 Debugging。
然后任務(wù)欄上點(diǎn)擊Run圖,當(dāng)然會(huì)報(bào)錯(cuò)的,原因請(qǐng)查看另一篇我的博客(https://blog.csdn.net/toopoo/article/details/79680323),所以需要右鍵點(diǎn)擊 項(xiàng)目名Run.cfg ,給它改個(gè)名字,
然后右鍵點(diǎn)擊項(xiàng)目樹里面的項(xiàng)目名稱,選擇“Propeties”,然后在Run/Debug Settings-選擇項(xiàng)目名-Edit-Main-C/C++Application那里點(diǎn)擊“Search Project”,然后選擇出現(xiàn)的默認(rèn)的elf文件:
然后在Debugger-User Defined-Browse 那里選擇你自己改名的配置文件:
然后右鍵點(diǎn)擊那個(gè)新的cfg文件,選擇"Open With - Text Editor", 進(jìn)行如下更改:
source [find interface/stlink.cfg] 更改為 source [find interface/stlink-v2.cfg]
reset_config srst_only srst_nogate connect_assert_srst 這一行改為 reset_config none
然后再Run一下,就可以了。
就實(shí)現(xiàn)四個(gè)按鍵分別控制LED的開關(guān)切換并實(shí)現(xiàn)了軟件去抖,不會(huì)產(chǎn)生誤動(dòng)作了。
本文參考了如下文章: