
3.1實(shí)驗(yàn)內(nèi)容
通過(guò)本實(shí)驗(yàn)主要學(xué)習(xí)以下內(nèi)容:
- GPIO輸入功能原理;
- 按鍵查詢輸入檢測(cè)原理;
3.2實(shí)驗(yàn)原理
3.2.1GPIO輸入功能原理
GD32F303系列MCU GPIO輸入配置結(jié)構(gòu)如下圖所示,輸入可配置上下拉電阻,通過(guò)施密特觸發(fā)器后可通過(guò)備用功能輸入或者通過(guò)輸入狀態(tài)寄存器進(jìn)行讀取。

輸入狀態(tài)寄存器為GPIOx_ISTAT,其狀態(tài)位定義如下圖所示,每個(gè)控制位對(duì)應(yīng)相應(yīng)引腳的輸入電平狀態(tài)。

GPIO引腳輸入電平判斷閾值如下圖所示,當(dāng)輸入電平小于0.3VDD時(shí),可被內(nèi)部有效識(shí)別為低電平;當(dāng)輸入電平大于0.7VDD時(shí),可被內(nèi)部有效識(shí)別為高電平。

3.3硬件設(shè)計(jì)
GD32F303紅楓派開(kāi)發(fā)板具有四個(gè)按鍵,對(duì)應(yīng)電路圖如下圖所示,該四個(gè)按鍵均具有上拉限流電阻,對(duì)引腳防護(hù)電阻以及對(duì)地消抖電容。在按鍵未按下時(shí),對(duì)應(yīng)GPIO引腳的電平為高電平,按下引腳后,對(duì)應(yīng)GPIO引腳的電平為低電平,通過(guò)讀取按鍵對(duì)應(yīng)GPIO引腳的電平狀態(tài)可檢測(cè)對(duì)應(yīng)按鍵是否被按下。


注意:機(jī)械按鍵在按下或者松開(kāi)時(shí)具有抖動(dòng),建議可增加硬件消抖或者軟件消抖,以避免按鍵檢測(cè)被多次觸發(fā)。 |
3.4代碼解析
本例程實(shí)現(xiàn)通過(guò)查詢的方式可查詢按鍵按下的時(shí)間,進(jìn)而可實(shí)現(xiàn)短時(shí)間按下和長(zhǎng)時(shí)間按下的檢測(cè)。
主函數(shù)代碼如下,首先進(jìn)行延遲初始化/按鍵初始化/LED初始化/串口初始化,并打印Example of key scan detection.之后進(jìn)入主循環(huán),通過(guò)key_scan函數(shù)實(shí)現(xiàn)對(duì)按鍵的掃描并檢測(cè)按鍵按下時(shí)間。
C int main(void) { //系統(tǒng)延時(shí)初始化 driver_init(); //按鍵組初始化 bsp_key_group_init(); //LED組初始化 bsp_led_group_init(); //板載UART初始化 bsp_uart_init(&BOARD_UART); delay_ms(1000); printf("Example of key scan detection.\r\n"); while (1) { delay_ms(1); //按鍵掃描結(jié)果檢查:檢測(cè)任意按鍵和多按鍵組合按下時(shí)間,所有按鍵彈起后有效 if(SET==key_scan(1)) { //檢測(cè)按鍵組合按下時(shí)長(zhǎng) if(KEY1.press_timerms >= PRESS_3000MS && KEY2.press_timerms >= PRESS_3000MS && WKUP.press_timerms >= PRESS_3000MS) { printf("KEY0/KEY1/KEY2 pressed together for more than 3000ms.\r\n"); KEY1.press_timerms=PRESS_NONE;; KEY2.press_timerms=PRESS_NONE; WKUP.press_timerms=PRESS_NONE; } else if(KEY1.press_timerms >= PRESS_50MS && KEY2.press_timerms >= PRESS_50MS && WKUP.press_timerms >= PRESS_50MS) { printf("KEY0/KEY1/KEY2 pressed together for more than 50ms.\r\n"); KEY1.press_timerms=PRESS_NONE;; KEY2.press_timerms=PRESS_NONE; WKUP.press_timerms=PRESS_NONE; } //檢測(cè)任意按鍵按下時(shí)長(zhǎng) if(KEY0.press_timerms >= PRESS_200MS && KEY0.press_timerms < PRESS_5000MS) { KEY0.press_timerms=PRESS_NONE; printf("KEY0 press more than 200ms, less than 5000ms .\r\n"); } else if(KEY0.press_timerms >= PRESS_5000MS) { KEY0.press_timerms=PRESS_NONE; printf("KEY0 press more than 5000ms.\r\n"); } else if(KEY0.press_timerms >= PRESS_DOWN) { KEY0.press_timerms=PRESS_NONE; printf("KEY0 press briefly.\r\n"); } if(KEY1.press_timerms >= PRESS_200MS && KEY1.press_timerms < PRESS_5000MS) { KEY1.press_timerms=PRESS_NONE; printf("KEY1 press more than 200ms, less than 5000ms .\r\n"); } else if(KEY1.press_timerms >= PRESS_5000MS) { KEY1.press_timerms=PRESS_NONE; printf("KEY1 press more than 5000ms.\r\n"); } else if(KEY1.press_timerms >= PRESS_DOWN) { KEY1.press_timerms=PRESS_NONE; printf("KEY1 press briefly.\r\n"); } if(KEY2.press_timerms >= PRESS_200MS && KEY2.press_timerms < PRESS_5000MS) { KEY2.press_timerms=PRESS_NONE; printf("KEY2 press more than 200ms, less than 5000ms .\r\n"); } else if(KEY2.press_timerms >= PRESS_5000MS) { KEY2.press_timerms=PRESS_NONE; printf("KEY2 press more than 5000ms.\r\n"); } else if(KEY2.press_timerms >= PRESS_DOWN) { KEY2.press_timerms=PRESS_NONE; printf("KEY2 press briefly.\r\n"); } if(WKUP.press_timerms >= PRESS_200MS && WKUP.press_timerms < PRESS_5000MS) { WKUP.press_timerms=PRESS_NONE; printf("WKUP press more than 200ms, less than 5000ms .\r\n"); } else if(WKUP.press_timerms >= PRESS_5000MS) { WKUP.press_timerms=PRESS_NONE; printf("WKUP press more than 5000ms.\r\n"); } else if(WKUP.press_timerms >= PRESS_DOWN) { WKUP.press_timerms=PRESS_NONE; printf("WKUP press briefly.\r\n"); } } //按鍵掃描結(jié)果檢查:檢測(cè)任意按鍵有按下 if(KEY0.press_timerms == PRESS_DOWN) { KEY0.press_timerms=PRESS_NONE; bsp_led_toggle(&LED0); } else if(KEY1.press_timerms == PRESS_DOWN) { KEY1.press_timerms=PRESS_NONE; bsp_led_toggle(&LED0); } else if(KEY2.press_timerms == PRESS_DOWN) { KEY2.press_timerms=PRESS_NONE; bsp_led_toggle(&LED0); } else if(WKUP.press_timerms == PRESS_DOWN) { WKUP.press_timerms=PRESS_NONE; bsp_led_toggle(&LED0); } else { bsp_led_off(&LED0); } //直接讀取按鍵有按下 if(bsp_key_state_get(&KEY0)==SET) { bsp_led_toggle(&LED1); } else if(bsp_key_state_get(&KEY1)==SET) { bsp_led_toggle(&LED1); } else if(bsp_key_state_get(&KEY2)==SET) { bsp_led_toggle(&LED1); } else if(bsp_key_state_get(&WKUP)==SET) { bsp_led_toggle(&LED1); } else { bsp_led_off(&LED1); } } } |
按鍵初始化函數(shù)如下,通過(guò)KEY_DEF定義相關(guān)按鍵參數(shù),之后調(diào)用bsp_key_init對(duì)按鍵進(jìn)行分別初始化。
C void bsp_key_group_init(void) { uint8_t i; for(i=0;i { bsp_key_init(((typdef_bsp_key *)KEY_INIT_GROUP[i])); } } KEY_DEF(KEY0,E,2,IN_PU,SET,NULL); // PE2定義為KEY0中斷模式,默認(rèn)狀態(tài)高 KEY_DEF(KEY1,E,3,IN_PU,SET,NULL); // PE3定義為KEY1非中斷模式,默認(rèn)狀態(tài)高 KEY_DEF(KEY2,E,4,IN_PU,SET,NULL); // PE4定義為KEY2非中斷模式,默認(rèn)狀態(tài)高 KEY_DEF(WKUP,A,0,IN_PU,SET,NULL); // PA0定義為KEY2非中斷模式,默認(rèn)狀態(tài)高 |
通過(guò)key_scan進(jìn)行按鍵掃描,實(shí)現(xiàn)對(duì)按鍵按下時(shí)間長(zhǎng)度范圍的檢測(cè)。
C bit_status key_scan(uint16_t scan_ms_cycle) { uint8_t i; bit_status press_flag=RESET; for(i=0;i { // ((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_timerms=press_none; if(bsp_key_state_get((typdef_bsp_key *)KEY_INIT_GROUP[i])==SET && ((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_cycle_count<0xffff){ ((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_timerms =PRESS_DOWN; ((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_cycle_count+=scan_ms_cycle; } } for(i=0;i { if(bsp_key_state_get((typdef_bsp_key *)KEY_INIT_GROUP[i])==SET && ((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_cycle_count < 0xffff) //持續(xù)60s被按下按鍵可能損壞 ??????? { return press_flag; } } for(i=0;i { if(((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_cycle_count>PRESS_50MS) { press_flag=SET; if(((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_cycle_count > PRESS_5000MS){ ((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_timerms=PRESS_5000MS; } else if(((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_cycle_count>PRESS_4000MS){ ((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_timerms=PRESS_4000MS; } else if(((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_cycle_count>PRESS_3000MS){ ((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_timerms=PRESS_3000MS; } else if(((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_cycle_count>PRESS_2000MS){ ((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_timerms=PRESS_2000MS; } else if(((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_cycle_count>PRESS_1000MS){ ((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_timerms=PRESS_1000MS; } else if(((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_cycle_count>PRESS_500MS){ ((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_timerms=PRESS_500MS; } else if(((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_cycle_count>PRESS_200MS){ ((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_timerms=PRESS_200MS; } else{ ((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_timerms=PRESS_50MS; } } if(bsp_key_state_get((typdef_bsp_key *)KEY_INIT_GROUP[i])==RESET){ ((typdef_bsp_key *)KEY_INIT_GROUP[i])->press_cycle_count=0; } } return press_flag; } |
3.5實(shí)驗(yàn)結(jié)果
將本例程燒錄到紅楓派開(kāi)發(fā)板中,連接USB串口通過(guò)Type C接口,上電后打開(kāi)串口調(diào)試助手,先按下復(fù)位按鍵,讓系統(tǒng)復(fù)位運(yùn)行。
首先在串口調(diào)試助手上打?。篍xample of key scan detection.
之后按下任意按鍵,松開(kāi)后將會(huì)打印按鍵按下的時(shí)間范圍。
具體現(xiàn)象如下所示。

本教程由GD32 MCU方案商聚沃科技原創(chuàng)發(fā)布,了解更多GD32 MCU教程,關(guān)注聚沃科技官網(wǎng)
-
單片機(jī)
+關(guān)注
關(guān)注
6067文章
44992瀏覽量
650597 -
嵌入式
+關(guān)注
關(guān)注
5152文章
19675瀏覽量
317662 -
開(kāi)發(fā)板
+關(guān)注
關(guān)注
25文章
5682瀏覽量
104839 -
GPIO
+關(guān)注
關(guān)注
16文章
1280瀏覽量
54121
發(fā)布評(píng)論請(qǐng)先 登錄
STM32CUBEMX開(kāi)發(fā)GD32F303(6)----GPIO輸入函數(shù)說(shuō)明

【GD32F303】星空派介紹
【星空派GD32F303開(kāi)發(fā)板試用體驗(yàn)】開(kāi)發(fā)記錄匯總
【星空派GD32F303開(kāi)發(fā)板試用體驗(yàn)】開(kāi)箱+環(huán)境搭建
【星空派GD32F303開(kāi)發(fā)板試用體驗(yàn)】開(kāi)箱+環(huán)境搭建
【星空派GD32F303開(kāi)發(fā)板試用體驗(yàn)】+板卡概覽
星空派GD32F303開(kāi)發(fā)板的相關(guān)資料下載
STM32CUBEMX開(kāi)發(fā)GD32F303(14)----IIC之配置OLED

GD32F303固件庫(kù)開(kāi)發(fā)

【GD32H757Z海棠派開(kāi)發(fā)板使用手冊(cè)】第二講 GPIO-按鍵查詢檢測(cè)實(shí)驗(yàn)

【GD32F470紫藤派開(kāi)發(fā)板使用手冊(cè)】第二講 GPIO-按鍵查詢實(shí)驗(yàn)

【GD32F303紅楓派開(kāi)發(fā)板使用手冊(cè)】第二講 GPIO-流水燈實(shí)驗(yàn)

【GD32F303紅楓派開(kāi)發(fā)板使用手冊(cè)】第五講 FMC-片內(nèi)Flash擦寫(xiě)讀實(shí)驗(yàn)

【GD32F303紅楓派開(kāi)發(fā)板使用手冊(cè)】第十六講 USART-DMA串口收發(fā)實(shí)驗(yàn)

【GD32F303紅楓派開(kāi)發(fā)板使用手冊(cè)】第二十講 SPI-SPI NAND FLASH讀寫(xiě)實(shí)驗(yàn)

評(píng)論