之前有人問了關於檢測按鍵按下時間長短的問題,這里記錄一種解決的辦法
這個工程我也分享在百度網盤
鏈接:https://pan.baidu.com/s/18nLuknQdWnysi7i7zNeZnA
提取碼:hi3r
思路:通過開啟按鍵GPIO的雙邊沿中斷,和TIM1計數來記錄按鍵按下的時間
現在我們來實現一下!!!
1、打開MX選擇一款IC,這里我用的開發板是stm32f103vet6
2、在MX中配置SW模式下載
3、配置外部高速晶振,低速的就是32.768k了RTC用的,這里用不上就不開了
4、配置好上面必要的步驟后,來看看我們按鈕原理圖和接到了哪個IO口
5、上圖一眼就能看出是接到了PE2,而且不按下默認已經和GND連接了,這個也方便我們之后不用內部下拉,那么把PE2配置成中斷吧
6、那么配置PE2要選擇雙邊沿中斷,如下圖配置
7、其他的就不用配置成內部上拉或者下拉了
8、把GPIO的中斷打開,順便把中斷降級,別和其他中斷沖突了
9、配置一下usart1設置成異步
10、我們先別急配置TIM1先去配置一下時鍾樹,我們用的8M晶振倍頻為72M,這里記住APB2的晶振是72M,我們TIM1用的是APB2
11、現在我們回去配置TIM1,打開TIM1的時鍾
12、接下來配置TIM1的預分頻值和重裝載值
這里很重要需要解釋一下
我們的晶振是72M也就是一秒記72 00 0000次,72 00 0000Hz
Prescaler預分頻值設置7200-1是因為預分頻值從0開始
我們把72M除以預分頻值7200就是我們定時器速度,速度變為了一秒記10000次
Counter Period重裝載值設置為10000,也就是定時器從0開始記了10000次以后就又回歸從0開始計算到10000一直循環
我們定時器的速度為1秒記10000次,重裝載值也剛好是10000,那么記一次重裝載要的時間就是1秒,那么速度剛好是1Hz
比如我們設置重裝載值為1000,定時器速度是10000Hz,記一次重裝載值的速度只要0.1秒也是10Hz
定時器的10000除以重裝載的1000也就是10,就是定時器配置成了10Hz
13、我們配置好后順便打開定時器的中斷,因為不知道是哪個我們先把兩個都打開,之后寫完代碼在來看看是哪個有效
14、也要給TIM1的中斷降級避免沖突
15、設置好這些之后我們配置下工程的名稱,路徑和開發工具
16、把這個打鈎代表生成單獨的配置文件,不用全部塞在main.c比較好看
17、我們要先測試一下printf能不能正常打印程序,這里之前已經寫過博客,只復制鏈接不重復介紹了https://www.cnblogs.com/hjf-log/p/12522796.html
18、我們到中斷函數中可以看到我們配置的中斷函數
19、我們程序進入中斷都會執行對應的callback函數也就是回調函數中,我們進入中斷函數就可以看到
20、我們將callback函數復制到main.c的保護區測試一下,不是main里面
這個效果是按鍵按下到釋放,一共打印2次,因為我們之前配置的是雙邊沿中斷,按下低變高是上升沿,釋放是高變低下降沿,打印2次沒錯,這里就不截圖串口助手了
21、因為我們要使用TIM1定時器,定時器有個初始化代碼要放在main中我們可以在下圖中找到
23、把初始化TIM1定時器放在這里
24、進入定時器中斷也一個callback函數,我們也復制到main.c中,就是下圖這個
25、復制到main.c我們寫一段代碼測試一下,效果是一秒打印一次test2
26、我們現在就可以寫我們要的功能了,先初始三個函數
27、修改GPIO中斷callback里面的代碼,下面也會貼出

1 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) 2 { 3 if(GPIO_Pin == GPIO_PIN_2) 4 { 5 if(i == 0) 6 { 7 state = 1; 8 i=1; 9 printf("state:1\r\n"); 10 } 11 else if(i == 1) 12 { 13 state = 0; 14 i = 0; 15 printf("按下按鍵的秒數:%0.2f\r\n",seconds/10); 16 seconds = 0; 17 printf("state:0\r\n"); 18 } 19 } 20 }
28、修改TIM1的中斷的callback代碼

1 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 2 { 3 if(htim->Instance == TIM1) 4 { 5 if(state == 1) 6 { 7 seconds++; 8 } 9 } 10 }
29、將代碼燒入IC中,然后按下按鍵可以看到串口助手效果
打印state:1表示按下,然后放開按鍵會打印按下的秒數和state:0
30、這里只精確到了個位的秒數,怎么修改按下的精度呢
我們接下來說一下如何把精度修改為0.1秒
回到MX中,將重裝載值修改為1000,就和我們上面說的一樣現在定時器為10Hz
原本我們的定時器速度是1Hz,一秒記一次,我們的定時器中斷的效果就是每記一次seconds數加1
現在把速度改為10Hz,記一次時間是0.1s,記一次seconds+1那么seconds記到的數單位就是0.1秒
因為原本的seconds定義成了int,之后要修改為float
記10次就seconds加到了10,也就是1秒,所以seconds除以10才是秒數嘛
printf("按下按鍵的秒數:%0.2f\r\n",seconds/10);
我們看看效果
31、好吧就記錄到這里,還有在上面關於開啟了兩個tim1中斷的問題我們來看看是哪個在起作用
喲注釋掉了第一組TIM1_BRK串口助手還能正常打印數據說明這個沒用上
我們回到MX關掉中斷在重新生成一遍工程就行了
到此結束啦加油啊