GPIO:LED和按键

2023-12-22 12:33:38

1.前言

? ? ? ? 上一篇文章讲解了如何快速点灯,当一名点灯工程师(o(* ̄▽ ̄*)ブ)这一章加入按键,快速实现GPIO的输入和输出功能,实现按键按下,灯的状态进行取反的操作。

2.查看硬件原理图

? ? ? ? 一般来说查看硬件原理图看硬件,应该在建立工程根据数据手册和需求分配引脚时进行查看,但是由于写博客还是要分一些先后顺序,故将查看硬件原理图放在第二步。同时一般在使用CubeMX创建工程时,基本也不太需要查看数据手册进行引脚的判别,因为CubeMX都将引脚都呈现出来了。

3.建立工程

? ? ? ? 每次创建工程有两项都是恒定不变的,配置RCC和配置Debug,后续的章节中都将省略具体截图步骤,取名老三样,因为配置了三个项目

3.1配置RCC

? ? ? ? 配置RCC,在第一张说设置好那几个参数之后按Resovle Clock Issues,后来发现不如直接按回车好用

3.2Debug
3.3配置GPIO

? ? ? ? 配置PB12为输出引脚,推挽输出模式,默认高电平,LED灭,无上下拉,配置PA0为输入模式,无上下拉,根据原理图来分析,在按键按下时,输入为低电平,松开时输入为高电平。选择上下拉和默认高低电平,要根据硬件原理图和需求来进行分析选择。

????????

3.4生成工程

4.代码编写

? ? ? ? 相关的代码编写也是很简单的,因为CubeMX都自动生成好了,一个电平反转函数,一个读GPIO电平函数。

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
    
  /* USER CODE END 2 */
    
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
      if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET)
      {
        HAL_Delay(100);    //软件消抖
        if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET)
        {
            HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_12);
        }
      }
  }
  /* USER CODE END 3 */
}

5.相关函数分析

5.1HAL_GPIO_ReadPin:读取电平

? ? ? ? 首先建立一个bitstatus变量,是GPIO_PinState类型,PIO_PinState是一个枚举,参数为GPIO_PIN_RESET = 0,GPIO_PIN_SET,GPIO_PIN_SET默认为GPIO_PIN_SET=1。

? ? ? ? 接着是断言,检查是不是GPIO口,从GPIO_PIN_0到GPIO_PIN_ALL。

? ? ? ? 然后是if else,判断GPIO的IDR寄存器与上GPIO_Pin是否等于GPIO_PIN_RESET也就是0,不等于0,返回GPIO_PIN_SET也就是1。

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  GPIO_PinState bitstatus;

  /* Check the parameters */
  assert_param(IS_GPIO_PIN(GPIO_Pin));

  if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
  {
    bitstatus = GPIO_PIN_SET;
  }
  else
  {
    bitstatus = GPIO_PIN_RESET;
  }
  return bitstatus;
}

? ? ? ? 这里可能很多人不太明白,按照GPIOA和PIN0这里进行讲解,GPIOx->IDR & GPIO_Pin表示与,也就是当IDR为0x0000和GPIO_Pin——0为0x0001,GPIOx->IDR & GPIO_Pin则为0,0=(uint32_t)GPIO_PIN_RESET,所以就是输入为低电平则为GPIO_PIN_RESET,逻辑是正确的。

5.2HAL_GPIO_TogglePin:反转电平

? ? ? ? 同样的分析方法。当电平是高电平的时候,将GPIO->BSRR寄存器数据左移16位,也就是对应的GPIO口置0,当电平是低电平的时候,将GPIO->BSRR寄存器数据等于GPIO_Pin,也就是对应为1。

void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  /* Check the parameters */
  assert_param(IS_GPIO_PIN(GPIO_Pin));

  if ((GPIOx->ODR & GPIO_Pin) == GPIO_Pin)
  {
    GPIOx->BSRR = (uint32_t)GPIO_Pin << GPIO_NUMBER;
  }
  else
  {
    GPIOx->BSRR = GPIO_Pin;
  }
}

????????

文章来源:https://blog.csdn.net/a1981613393/article/details/132779435
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。