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

发布者:温暖的拥抱最新更新时间:2024-12-03 来源: elecfans关键字:GD32F303  GPIO 手机看文章 扫描二维码
随时随地手机看文章

3.1实验内容

通过本实验主要学习以下内容:

  • GPIO输入功能原理;

  • 按键查询输入检测原理;

3.2实验原理

3.2.1GPIO输入功能原理

GD32F303系列MCU GPIO输入配置结构如下图所示,输入可配置上下拉电阻,通过施密特触发器后可通过备用功能输入或者通过输入状态寄存器进行读取。

wKgZomZX3JGAdK5HAADPIZJd4gI263.png?imageView2/2/w/1000

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

wKgZomZX3KaAKvvqAAGLa0IjgTQ084.png?imageView2/2/w/1000

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

wKgZomZX3LGASiI1AAGjTlTXPNA045.png?imageView2/2/w/1000

3.3硬件设计

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

wKgZomZX3MSAK3pWAAGJFdLauno447.png?imageView2/2/w/1000wKgZomZX3b2AFHHxAAGFPZspFEc711.png?imageView2/2/w/1000

注意:机械按键在按下或者松开时具有抖动,建议可增加硬件消抖或者软件消抖,以避免按键检测被多次触发。

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.rn');


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.rn');
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.rn');
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 .rn');
}
else if(KEY0.press_timerms >= PRESS_5000MS)
{
KEY0.press_timerms=PRESS_NONE;
printf('KEY0 press more than 5000ms.rn');
}
else if(KEY0.press_timerms >= PRESS_DOWN)
{
KEY0.press_timerms=PRESS_NONE;
printf('KEY0 press briefly.rn');
}

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 .rn');
}
else if(KEY1.press_timerms >= PRESS_5000MS)
{
KEY1.press_timerms=PRESS_NONE;
printf('KEY1 press more than 5000ms.rn');
}
else if(KEY1.press_timerms >= PRESS_DOWN)
{
KEY1.press_timerms=PRESS_NONE;
printf('KEY1 press briefly.rn');
}

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 .rn');
}
else if(KEY2.press_timerms >= PRESS_5000MS)
{
KEY2.press_timerms=PRESS_NONE;
printf('KEY2 press more than 5000ms.rn');
}
else if(KEY2.press_timerms >= PRESS_DOWN)
{
KEY2.press_timerms=PRESS_NONE;
printf('KEY2 press briefly.rn');
}

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 .rn');
}
else if(WKUP.press_timerms >= PRESS_5000MS)
{
WKUP.press_timerms=PRESS_NONE;
printf('WKUP press more than 5000ms.rn');
}
else if(WKUP.press_timerms >= PRESS_DOWN)
{
WKUP.press_timerms=PRESS_NONE;
printf('WKUP press briefly.rn');
}
}

//按键扫描结果检查:检测任意按键有按下
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.

之后按下任意按键,松开后将会打印按键按下的时间范围。

具体现象如下所示。

wKgZomZX3f2ACnYwAAC_A1OSc68148.png?imageView2/2/w/1000

关键字:GD32F303  GPIO 引用地址:【GD32F303红枫派开发板使用手册】第三讲 GPIO-按键查询检测实验

上一篇:采用GD32F470高性能MCU的PowerWriter X1多功能调试烧录器
下一篇:关于GD32F207ZE的燃料电池监测系统的介绍和应用分析

推荐阅读最新更新时间:2026-03-25 12:13

GD32F303红枫开发板使用手册】第二十讲八 USB-虚拟串口实验
28.USB-虚拟串口实验 28.1实验内容 通过本实验主要学习以下内容: CDC虚拟串口协议原理及使用 CDC虚拟串口通信操作 28.2实验原理 USB的CDC类是USB通信设备类(Communication Device Class)的简称。CDC类是USB组织定义的一类专门给各种通信设备使用的USB子类。该设备类采用批量传输。 本例程中实现了CDC设备类的相关请求,包括SET_LINE_CODING、GET_LINE_CODING、SET_CONTROL_LINE_STATE等。后续将会在代码解析章节进行介绍。 有关CDC协议可以通过以下USB官网下载或者通过红枫派开发板配套资料获取。 大家可以在学习的过程中结合历程代
[单片机]
【<font color='red'>GD32F303</font><font color='red'>红枫</font><font color='red'>派</font><font color='red'>开发板</font>使用手册】第二十讲八 USB-虚拟串口实验
GD32F303红枫开发板使用手册】第十五讲 USART-printf打印实验
15.1实验内容 通过本实验主要学习以下内容: 串口简介 GD32F303串口工作原理 使用printf打印信息 15.2实验原理 15.2.1串口简介 串口,从广义上看,指所有串行通信接口,比如RS232、RS422、RS485、SPI、IIC等。串行通讯是指仅用一根接收线和一根发送线就能将数据以位进行传输的通讯方式。和串行通讯相对应的是并行通讯,并行通信指一个传输接口可以传输8个bit即一个byte(有时甚至更多),虽然串行通信比并行通信慢,但是串口可以在仅仅使用两根线的情况下就能实现数据的传输。 对于GD32F303来说,串口一般特指USART(通用同步异步收发器 )和UART(通用异步收发器 )。USART/U
[单片机]
【<font color='red'>GD32F303</font><font color='red'>红枫</font><font color='red'>派</font><font color='red'>开发板</font>使用手册】第十五讲 USART-printf打印实验
GD32F303红枫开发板使用手册】第四讲 GEXTI-按键中断检测实验
4.1实验内容 通过本实验主要学习以下内容: EXTI中断原理; 按键中断检测原理; 4.2实验原理 4.2.1NVIC中断向量控制器 介绍EXTI之前,首先为各位读者介绍NVIC中断向量控制器,NVIC为M4内核组件,用于实现高效的异常和中断处理。NVIC可以支持抢占以及咬尾中断,具有多达68种外设中断以及4位中断优先等级配置(最多支持16个中断有限等级),当中断或异常产生时,系统自动将当前处理器工作状态压栈,在执行完中断服务子程序(ISR) 后自动将其出栈。 GD32F303系列MCU的中断向量表如下表所示(包含异常中断)。 有关NVIC中断相关配置函数可参考gd32f30x_misc.c,其中主要有以下几个函数
[单片机]
【<font color='red'>GD32F303</font><font color='red'>红枫</font><font color='red'>派</font><font color='red'>开发板</font>使用手册】第四讲 GEXTI-<font color='red'>按键</font>中断检测实验
GD32F303红枫开发板使用手册】第三十讲 CAN -CAN通信实验
30.1实验内容 通过本实验主要学习以下内容: CAN的简介 GD32F303 CAN工作原理 通过CAN实现回环收发 30.2实验原理 30.2.1CAN概述 CAN 是Controller Area Network的缩写,是由德国BOSCH公司开发的,已成为ISO国际标准化的串行通信协议。其主要应用场合为汽车和工业控制。CAN具有传输距离长,传输可靠、强大的纠错机制等特点,其高性能和可靠性已被广泛认同,现在已经成为汽车、工业自动化、医疗设备等领域应用最广泛的总线之一。 30.2.2CAN总线拓扑 CAN总线拓扑图如下: CAN 控制器根据两根线上的电位差来判断总线电平,一般将两根线分别命名为CAN_H和CAN_L。
[单片机]
【<font color='red'>GD32F303</font><font color='red'>红枫</font><font color='red'>派</font><font color='red'>开发板</font>使用手册】第三十讲 CAN -CAN通信实验
GD32F303红枫开发板使用手册】第十讲 FWDGT-独立看门狗实验
10.1实验内容 通过本实验主要学习以下内容: 独立看门狗的原理 独立看门狗功能介绍 实现独立看门狗功能 10.2实验原理 10.2.1看门狗的原理 一般来说,搭配MCU的产品都需要有长期运行的需求,特别像一些工业设备,可能要求运行个几年都不关机,但谁也不能保证在这几年里,MCU里面的代码不出任何问题,更何况自然环境中还存在很多电磁干扰、静电等,都可能会导致MCU出现运行异常的情况,比如程序卡死啦,进入错误状态啦等等,这个时候,我们就可以通过一个非常可爱的外设——看门狗,来帮助MCU从异常状态复位,让程序重新开始从头运行。 看门狗实际上是一个定时器,它的工作原理是:将看门狗定时器的计数器设定一个初始值,看门狗开始运行后,定
[单片机]
【<font color='red'>GD32F303</font><font color='red'>红枫</font><font color='red'>派</font><font color='red'>开发板</font>使用手册】第十讲 FWDGT-独立看门狗实验
【改进Poll定时查询】IMX257实现GPIO-IRQ中断按键获取键值驱动程序
按键驱动程序中,如果不使用read函数中使程序休眠的,而是还是使用查询方式的话,可以使用Poll函数,来控制一定时间内,如果有按键发生,则立即返回键值。 同时,poll也可以同时监控多个(比如说按键,鼠标,等)一旦发生事件则立即返回。 我们在linux查看帮助: 从帮助中的说明得知, poll, ppoll - wait for some event on a file descriptor poll就是监控某个设备的事件。 修改驱动程序 1.增加头文件 #include linux/poll.h 2.增加key_poll 方法 static unsigned key_poll(struct file *fil
[单片机]
【改进Poll定时<font color='red'>查询</font>】IMX257实现<font color='red'>GPIO</font>-IRQ中断<font color='red'>按键</font>获取键值驱动程序
STM32CUBEMX开发GD32F303(4)----GPIO输出模式,速率测试、开漏和输出说明
概述 以STM32CUBEMX创建STM32F103工程,同时移植在GD32F303中,同时通过GD32303C_START开发板内进行验证。 需要样片的可以加Qun申请:615061293。 硬件准备 这里准备了2块开发板进行验证,分别是GD32303C_START开发板。 开发板管脚配置 在GD32303C_START中的LED管脚配置如下所示。 不同速率对应的波形 以PC3为例,在推挽输出无上下拉情况下,输出速率主要有4种,一般的低端MCU只有3种,没有Very High。 下面是ST的配置图。 在固件库中,定义如下所示。 LOW速率 Medium速率 High速率 Very High速率 可以
[单片机]
STM32CUBEMX开发<font color='red'>GD32F303</font>(4)----<font color='red'>GPIO</font>输出模式,速率测试、开漏和输出说明
STM32CUBEMX开发GD32F303(5)----GPIO输出函数说明
概述 本章STM32CUBEMX配置STM32F103,并且在GD32F303中进行开发,同时通过GD32303C_START开发板内进行验证。 样品申请 https://www.wjx.top/vm/mB2IKus.aspx 硬件准备 这里准备了2块开发板进行验证,分别是GD32303C_START开发板。 开发板管脚配置 在GD32303C_START中的LED管脚配置如下所示。 HAL_GPIO_Init()函数 该函数的作用是根据GPIO_Init中指定的参数初始化GPIOx外设。 由于是对管脚进行初始化定义,一般在mian()函数初始化中。 而在主程序的初始化中,有个注释是初始化所有配置的外设,点击查看这
[单片机]
STM32CUBEMX开发<font color='red'>GD32F303</font>(5)----<font color='red'>GPIO</font>输出函数说明
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved