
3.1实验内容
通过本实验主要学习以下内容:
- GPIO输入功能原理;
- 按键查询输入检测原理;
3.2实验原理
3.2.1GPIO输入功能原理
GD32F303系列MCU GPIO输入配置结构如下图所示,输入可配置上下拉电阻,通过施密特触发器后可通过备用功能输入或者通过输入状态寄存器进行读取。

输入状态寄存器为GPIOx_ISTAT,其状态位定义如下图所示,每个控制位对应相应引脚的输入电平状态。

GPIO引脚输入电平判断阈值如下图所示,当输入电平小于0.3VDD时,可被内部有效识别为低电平;当输入电平大于0.7VDD时,可被内部有效识别为高电平。

3.3硬件设计
GD32F303红枫派开发板具有四个按键,对应电路图如下图所示,该四个按键均具有上拉限流电阻,对引脚防护电阻以及对地消抖电容。在按键未按下时,对应GPIO引脚的电平为高电平,按下引脚后,对应GPIO引脚的电平为低电平,通过读取按键对应GPIO引脚的电平状态可检测对应按键是否被按下。


注意:机械按键在按下或者松开时具有抖动,建议可增加硬件消抖或者软件消抖,以避免按键检测被多次触发。 |
3.4代码解析
本例程实现通过查询的方式可查询按键按下的时间,进而可实现短时间按下和长时间按下的检测。
主函数代码如下,首先进行延迟初始化/按键初始化/LED初始化/串口初始化,并打印Example of key scan detection.之后进入主循环,通过key_scan函数实现对按键的扫描并检测按键按下时间。
| C int main(void) { //系统延时初始化 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); //按键扫描结果检查:检测任意按键和多按键组合按下时间,所有按键弹起后有效 if(SET==key_scan(1)) { //检测按键组合按下时长 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; } //检测任意按键按下时长 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"); } } //按键扫描结果检查:检测任意按键有按下 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); } } } |
按键初始化函数如下,通过KEY_DEF定义相关按键参数,之后调用bsp_key_init对按键进行分别初始化。
| 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中断模式,默认状态高 KEY_DEF(KEY1,E,3,IN_PU,SET,NULL); // PE3定义为KEY1非中断模式,默认状态高 KEY_DEF(KEY2,E,4,IN_PU,SET,NULL); // PE4定义为KEY2非中断模式,默认状态高 KEY_DEF(WKUP,A,0,IN_PU,SET,NULL); // PA0定义为KEY2非中断模式,默认状态高 |
通过key_scan进行按键扫描,实现对按键按下时间长度范围的检测。
| 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) //持续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实验结果
将本例程烧录到红枫派开发板中,连接USB串口通过Type C接口,上电后打开串口调试助手,先按下复位按键,让系统复位运行。
首先在串口调试助手上打印:Example of key scan detection.
之后按下任意按键,松开后将会打印按键按下的时间范围。
具体现象如下所示。

本教程由GD32 MCU方案商聚沃科技原创发布,了解更多GD32 MCU教程,关注聚沃科技官网
-
单片机
+关注
关注
6074文章
45340浏览量
663598 -
嵌入式
+关注
关注
5186文章
20151浏览量
328876 -
开发板
+关注
关注
25文章
6125浏览量
113362 -
GPIO
+关注
关注
16文章
1313浏览量
55728
发布评论请先 登录
STM32CUBEMX开发GD32F303(6)----GPIO输入函数说明
【星空派GD32F303开发板试用体验】开发记录汇总
【星空派GD32F303开发板试用体验】开箱+环境搭建
【星空派GD32F303开发板试用体验】开箱+环境搭建
【星空派GD32F303开发板试用体验】+板卡概览
GD32F303固件库开发
【GD32F303红枫派开发板使用手册】第二讲 GPIO-流水灯实验
【GD32F303红枫派开发板使用手册】第五讲 FMC-片内Flash擦写读实验
【GD32F303红枫派开发板使用手册】第十六讲 USART-DMA串口收发实验
【GD32F303红枫派开发板使用手册】第二十讲 SPI-SPI NAND FLASH读写实验

【GD32F303红枫派开发板使用手册】第三讲 GPIO-按键查询检测实验
评论