0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

聚沃科技 2024-05-30 10:02 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

wKgaomZVdiiAfR9BAB3mDFhHnZc972.png

3.1实验内容

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

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

3.2实验原理

3.2.1GPIO输入功能原理

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

wKgZomZX3JGAdK5HAADPIZJd4gI263.png

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

wKgZomZX3KaAKvvqAAGLa0IjgTQ084.png

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

wKgZomZX3LGASiI1AAGjTlTXPNA045.png

3.3硬件设计

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

wKgZomZX3MSAK3pWAAGJFdLauno447.pngwKgZomZX3b2AFHHxAAGFPZspFEc711.png

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

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.

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

具体现象如下所示。

wKgZomZX3f2ACnYwAAC_A1OSc68148.png

教程GD32 MCU方案商聚沃科技原创发布,了解更多GD32 MCU教程,关注聚沃科技官网

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6074

    文章

    45340

    浏览量

    663598
  • 嵌入式
    +关注

    关注

    5186

    文章

    20151

    浏览量

    328876
  • 开发板
    +关注

    关注

    25

    文章

    6125

    浏览量

    113362
  • GPIO
    +关注

    关注

    16

    文章

    1313

    浏览量

    55728
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    STM32CUBEMX开发GD32F303(6)----GPIO输入函数说明

    本章STM32CUBEMX配置STM32F103,并且在GD32F303中进行开发,同时通过GD32303C_START开发板内进行验证。
    的头像 发表于 11-25 16:06 2627次阅读
    STM32CUBEMX<b class='flag-5'>开发</b><b class='flag-5'>GD32F303</b>(6)----<b class='flag-5'>GPIO</b>输入函数说明

    GD32F303】星空介绍

    一、开发板介绍星空GD开发板是由旗点科技推出的一款GD32开发板,板载
    发表于 09-11 17:55

    【星空GD32F303开发板试用体验】开发记录汇总

    本帖最后由 申小林一号 于 2021-10-15 14:47 编辑 开贴日期:2021年10月11日该贴主要是用于记录星空开发板使用记录以及学习GD32F303芯片的一个过程,将所有的
    发表于 10-11 16:09

    【星空GD32F303开发板试用体验】开箱+环境搭建

    本帖最后由 lustao 于 2021-10-19 09:29 编辑 感谢 发烧友学院以及广州旗点智能科技有限公司为我和孩子提供此产品星空GD32F303开发板。收到了星空
    发表于 10-18 14:15

    【星空GD32F303开发板试用体验】开箱+环境搭建

    https://bbs.elecfans.com/jishu_2179209_1_1.html感谢 发烧友学院以及广州旗点智能科技有限公司为我和孩子提供此产品星空gd32F303开发板。收到了星空
    发表于 11-02 15:36

    【星空GD32F303开发板试用体验】+板卡概览

    本帖最后由 cooldog123pp 于 2021-11-6 21:07 编辑 星空GD开发板是由旗点科技推出的一款GD32开发板
    发表于 11-06 21:05

    星空GD32F303开发板的相关资料下载

    一、开发板介绍星空GD开发板是由旗点科技推出的一款GD32开发板,板载
    发表于 12-10 08:27

    STM32CUBEMX开发GD32F303(14)----IIC之配置OLED

    本章STM32CUBEMX配置STM32F103,并且在GD32F303中进行开发,同时通过开发板内进行验证。
    的头像 发表于 07-26 13:52 3509次阅读
    STM32CUBEMX<b class='flag-5'>开发</b><b class='flag-5'>GD32F303</b>(14)----IIC之配置OLED

    GD32F303固件库开发

    的可以加群申请:615061293 。 GD32F303固件库开发(1)----前期准备与烧录 使用GDLINK、jlink、串口下载程序到GD芯片。 [https://blog.csdn.net
    的头像 发表于 07-27 09:27 2235次阅读
    <b class='flag-5'>GD32F303</b>固件库<b class='flag-5'>开发</b>

    GD32H757Z海棠开发板使用手册】第二 GPIO-按键查询检测实验

    2.1实验内容通过本实验主要学习以下内容:GPIO输入功能原理;按键查询输入检测原理;2.2
    的头像 发表于 04-17 10:42 1477次阅读
    【<b class='flag-5'>GD</b>32H757Z海棠<b class='flag-5'>派</b><b class='flag-5'>开发板</b><b class='flag-5'>使用手册</b>】第二<b class='flag-5'>讲</b> <b class='flag-5'>GPIO-</b><b class='flag-5'>按键</b><b class='flag-5'>查询</b><b class='flag-5'>检测</b><b class='flag-5'>实验</b>

    GD32F470紫藤开发板使用手册】第二 GPIO-按键查询实验

    通过本实验主要学习以下内容: GPIO输入功能原理; 按键查询输入检测原理;
    的头像 发表于 04-30 11:39 1645次阅读
    【<b class='flag-5'>GD32F</b>470紫藤<b class='flag-5'>派</b><b class='flag-5'>开发板</b><b class='flag-5'>使用手册</b>】第二<b class='flag-5'>讲</b> <b class='flag-5'>GPIO-</b><b class='flag-5'>按键</b><b class='flag-5'>查询</b><b class='flag-5'>实验</b>

    GD32F303红枫开发板使用手册】第二 GPIO-流水灯实验

    GD32F303系列MCU最多可支持 112 个通用I/O 引脚(GPIO),分别为 PA0 ~ PA15, PB0 ~ PB15, PC0 ~ PC15,PD0 ~ PD15, PE0
    的头像 发表于 05-29 10:02 4518次阅读
    【<b class='flag-5'>GD32F303</b><b class='flag-5'>红枫</b><b class='flag-5'>派</b><b class='flag-5'>开发板</b><b class='flag-5'>使用手册</b>】第二<b class='flag-5'>讲</b> <b class='flag-5'>GPIO-</b>流水灯<b class='flag-5'>实验</b>

    GD32F303红枫开发板使用手册】第五 FMC-片内Flash擦写读实验

    MC即Flash控制器,其提供了片上Flash操作所需要的所有功能,在GD32F303系列MCU中,Flash前256K字节空间内, CPU执行指令零等待,具有相同主频下最快的代码执行效率。FMC也
    的头像 发表于 06-02 10:05 2220次阅读
    【<b class='flag-5'>GD32F303</b><b class='flag-5'>红枫</b><b class='flag-5'>派</b><b class='flag-5'>开发板</b><b class='flag-5'>使用手册</b>】第五<b class='flag-5'>讲</b> FMC-片内Flash擦写读<b class='flag-5'>实验</b>

    GD32F303红枫开发板使用手册】第十六 USART-DMA串口收发实验

    在前面ADC章节中,我们介绍了DMA的工作原理,这里就不多做介绍。从GD32F303用户手册中可以查到,各串口的TX和RX分别对应DMA的不同通道,比如USART0的TX对应DMA0的通道3,而RX对应DMA0的通道4。
    的头像 发表于 06-15 09:54 2679次阅读
    【<b class='flag-5'>GD32F303</b><b class='flag-5'>红枫</b><b class='flag-5'>派</b><b class='flag-5'>开发板</b><b class='flag-5'>使用手册</b>】第十六<b class='flag-5'>讲</b> USART-DMA串口收发<b class='flag-5'>实验</b>

    GD32F303红枫开发板使用手册】第二十 SPI-SPI NAND FLASH读写实验

    通过本实验主要学习以下内容: •SPI通信协议,参考19.2.1东方红开发板使用手册GD32F303 SPI操作方式,参考19.2.2东方红
    的头像 发表于 06-20 09:50 2926次阅读
    【<b class='flag-5'>GD32F303</b><b class='flag-5'>红枫</b><b class='flag-5'>派</b><b class='flag-5'>开发板</b><b class='flag-5'>使用手册</b>】第二十<b class='flag-5'>讲</b> SPI-SPI NAND FLASH读写<b class='flag-5'>实验</b>