ITPub博客

首页 > 嵌入式/内核开发 > 嵌入式/内核开发 > [蓝桥杯嵌入式有手就行]5_GPIO(下)

[蓝桥杯嵌入式有手就行]5_GPIO(下)

原创 嵌入式/内核开发 作者:工具人呵呵 时间:2023-10-14 10:37:25 0 删除 编辑


前言

一、内部结构

1、Input driver(上方的虚线框)

1、浮空输入模式

2、输入上拉模式

3、输入下拉模式

4、高阻态模拟输入模式

2、I/O引脚(两个虚线框右侧)

二、按键模块原理分析

1、原理图

2、抖动问题

三、软件部分

1、cubemx配置

2、代码示例

四、问题

1、按键扫描相对消耗资源,是否有其他办法

总结

前言

注:本系列基于2023年蓝桥杯实战情况就行编写,所有软件均采用2023年赛点资源包

本文将讲解GPIO输入(不含复用)部分。在板子上的体现,就是按键。


一、内部结构

下图在参考手册9.1节。本文主讲输入,所以我们只看上面一个虚线框,以及右侧I/O引脚。

在这里插入图片描述


1、Input driver(上方的虚线框)

1、浮空输入模式

在这里插入图片描述


2、输入上拉模式

在这里插入图片描述


3、输入下拉模式

在这里插入图片描述


4、高阻态模拟输入模式

在这里插入图片描述

注意:此模式的时候,信号不经过TTL施密特触发器


2、I/O引脚(两个虚线框右侧)

在这里插入图片描述

我们可以看到,这里有2个电阻,2个二极管。在配置为输入模式时,通过上下拉电阻和开关(可以通过寄存器控制开关状态)把输入线电平拉高或者降低,电阻值大概在40kΩ。这里两个保护二极管,可以理解为这两个二极管将外部输入的电压钳制在VDDIOX和Vss 之间(一般是VDD和GND),从而防止过高或过低的电流进入,导致芯片损坏。


二、按键模块原理分析

1、原理图

在这里插入图片描述

通过原理图,我们可以发现其一段是保护电阻,另一端通过按钮接地

对引脚状态进行分析。


按键     状态 效果

按下      引脚接地,输入低电平

松开      引脚通过一个保护电阻接VDD,输入高电平

2、抖动问题

通过原理图,我们可以发现按键没有并联电容,因机械结构特性,在按下或者松开的瞬间,信号不可避免的会出现一些波动。

这个信号不好捕捉,百度找的图。我实测大概1ms左右。但是,对80M主频的单片机 来说,太慢了。所以消抖是一定要做的。

在这里插入图片描述


三、软件部分

1、cubemx配置

我们只需要将引脚功能配置为GPIO_Input。

在这里插入图片描述


2、代码示例

按键扫描程序


unsigned char key_scan(void)
{
  unsigned char unkey_val = 0;
  if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET)    unkey_val = 1;
  if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET)    unkey_val = 2;
  if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET)    unkey_val = 3;
  if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)    unkey_val = 4;
  return unkey_val;
}



按键功能实现。以上一篇的led 为例。这里的代码相对完善,当然我们完全可以对其进行优化以便适应要求。


unsigned char uwTick_key;
unsigned char uckey_val, uckey_down, uckey_old, uckey_up;
void key_proc(void)
{
  if ((uwTick - uwTick_key) < 50) return;//这里延时50ms,为了消抖,可满足大部分题目要求
  uwTick_key = uwTick;
  uckey_val - key_scan();
  uckey_down = uckey_val & (uckey_old ^ uckey_val);
  uckey_up = ~uckey_val & (uckey_old ^ uckey_val);
  uckey_old = uckey_val;
  switch (uckey_down)
  {
  
case 1:  led_disp(1);  break;
  
case 2:  led_disp(2);  break;
 case 3:  led_disp(3);  break;
  
case 4:  led_disp(4);  break;
 default: led_disp(0);  break;//注意上一节中的代码要修改,0是没有反应的
  }
}

四、问题

1、按键扫描相对消耗资源,是否有其他办法

当我们没有同时使用B1和B4按钮的时候,我们可以将引脚配置为GPIO_EXITx,并设置为External Interrupt Mode with Falling edge trigger detection或者External Interrupt Mode with Rising/Falling edge trigger detection这样我们就可以通过外部中断的形式获取按键状态。

这里以PA0(也就是B4按键)为例,此时PB0(B1按键)无法设置为外部中断0

在这里插入图片描述


只有按下按钮,产生了一个下降沿事件,才会进入外部中断,才会去执行按键相关程序。

而上升沿检测,主要是为了实现长短按的区分。具体需要根据实际情况去选择。

而代码上相对上面就会简洁许多。


void HAL_GPIO_EXIT_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_0) key_down=4;
}



总结

至此,GPIO(不含复用)部分的内容就粗略的讲完了,应对比赛就足够了。接下来就LCD屏幕了。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70050091/viewspace-3117696/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-01-01

  • 博文量
    35
  • 访问量
    5027