STM32 GPIO外设系统深度解析学习指南

按照STM32MCUWIKI参考手册的外设介绍—–>CubeF4的软件包中相关的Exmple代码—–>CubeMX设置截图加深理解记忆

资料链接:嵌入式开发_硬软件的环境搭建

我的飞书文档-GPIO篇

如果觉得内容不错,欢迎给我的飞书文档点赞。同时如果有什么意见或者文档修改意见的话,可以在飞书中评论,有时间的话我逐步更新。

外设简介

GPIO代表[General Purpose Input/Output]通用输入/输出。它是集成电路上没有特定功能的引脚类型。虽然大多数引脚都有专用用途,例如向某个组件发送信号,但 GPIO 引脚的功能是可定制的,可以由软件控制。

引脚模式

通用 I/O(GPIO)端口的每个端口位可以通过软件单独配置为以下几种模式:

  • 输入或输出[input or output]
  • 模拟模式[analog]
  • 复用功能[alternate function (AF)]
  • 引脚特性

  • 输入:无上拉,无下拉或上拉或下拉
  • 输出:推挽式或开漏式,具有上拉或下拉功能
  • 复用功能:具有上拉或下拉功能的推挽或开漏。
  • 引脚输出速度

    其主要是指STM32改变引脚状态,由高变为低或由低变为高时的上升沿和下降沿。

    相关寄存器

    功能介绍

    I/O 端口控制寄存器

    每个 GPIO 有 4 个 32 位存储器映射的控制寄存器(GPIOx_MODER、GPIOx_OTYPER、 GPIOx_OSPEEDR、GPIOx_PUPDR),可配置多达 16 个 I/O。 GPIOx_MODER 寄存器用于选择 I/O 方向(输入、输出、AF、模拟)。 GPIOx_OTYPER 和 GPIOx_OSPEEDR 寄存器分别用于选择输出类型(推挽或开漏)和速度 (无论采用哪种 I/O 方向,都会直接将 I/O 速度引脚连接到相应的 GPIOx_OSPEEDR 寄存器位)。无论采用哪种 I/O 方向, GPIOx_PUPDR 寄存器都用于选择上拉/下拉。

    I/O 端口数据寄存器

    每个 GPIO 都具有 2 个 16 位数据寄存器:输入和输出数据寄存器(GPIOx_IDR 和

    GPIOx_ODR)。

    GPIOx_ODR 用于存储待输出数据,可对其进行读/写访问。

    通过 I/O 输入的数据存储到输入数据寄存器 (GPIOx_IDR) 中,它是一个只读寄存器。

    I/O 数据位操作

    置位复位寄存器 (GPIOx_BSRR) 是一个 32 位寄存器,它允许应用程序在输出数据寄存器

    (GPIOx_ODR) 中对各个单独的数据位执行置位和复位操作。置位复位寄存器的大小是

    GPIOx_ODR 的二倍。

    GPIOx_ODR 中的每个数据位对应于 GPIOx_BSRR 中的两个控制位:BSRR(i) 和

    BSRR(i+SIZE)。

    当写入 1 时,BSRR(i) 位会置位对应的 ODR(i) 位。当写入 1 时,BSRR(i+SIZE) 位会清零 ODR(i) 对应的位。

    GPIO 锁定机制

    通过将特定的写序列应用到 GPIOx_LCKR 寄存器,可以冻结 GPIO 控制寄存器。冻结的寄存器包括 GPIOx_MODER、GPIOx_OTYPER、GPIOx_OSPEEDR、GPIOx_PUPDR、

    GPIOx_AFRL 和 GPIOx_AFRH。

    I/O 复用功能输入/输出

    有两个寄存器可用来从每个 I/O 可用的 16 个复用功能输入/输出中进行选择。借助这些寄存器,可根据应用程序的要求将某个复用功能连接到其它某个引脚。

    这意味着可使用 GPIOx_AFRL 和 GPIOx_AFRH 复用功能寄存器在每个 GPIO 上复用多个可

    用的外设功能。这样一来,应用程序可为每个 I/O 选择任何一个可用功能。由于 AF 选择信号由复用功能输入和复用功能输出共用,所以只需为每个 I/O 的复用功能输入/输出选择一个通道即可。

    外部中断线/唤醒线

    所有端口都具有外部中断功能。要使用外部中断线,必须将端口配置为输入模式。具体参考Example

    详细介绍

    1. GPIOx_MODERGPIO 端口模式寄存器)

     

    2. GPIOx_OTYPERGPIO 端口输出类型寄存器)

    3. GPIOx_OSPEEDRGPIO 端口输出速度寄存器)

    4. GPIOx_PUPDRGPIO 端口上拉/下拉寄存器)

    5. GPIOx_IDRGPIO 端口输入数据寄存器)

    6. GPIOx_ODRGPIO 端口输出数据寄存器)

    7. GPIOx_BSRRGPIO 端口置位/复位寄存器)

    8. GPIOx_LCKRGPIO 端口配置锁定寄存器)

    9. GPIOx_AFRLGPIO 复用功能低位寄存器)

    10. GPIOx_AFRHGPIO 复用功能高位寄存器)

    HAL库相关驱动API

    HAL_GPIO_ReadPin

    C
    /**
      * @brief  Reads the specified input port pin.
      * @param  GPIOx where x can be (A..K) to select the GPIO peripheral for STM32F429X device or
      *                      x can be (A..I) to select the GPIO peripheral for STM32F40XX and STM32F427X devices.
      * @param  GPIO_Pin specifies the port bit to read.
      *         This parameter can be GPIO_PIN_x where x can be (0..15).
      * @retval The input port pin value.
      */
    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;
    }

    HAL_GPIO_WritePin

    C
    /**
      * @brief  Sets or clears the selected data port bit.
      *
      * @note   This function uses GPIOx_BSRR register to allow atomic read/modify
      *         accesses. In this way, there is no risk of an IRQ occurring between
      *         the read and the modify access.
      *
      * @param  GPIOx where x can be (A..K) to select the GPIO peripheral for STM32F429X device or
      *                      x can be (A..I) to select the GPIO peripheral for STM32F40XX and STM32F427X devices.
      * @param  GPIO_Pin specifies the port bit to be written.
      *          This parameter can be one of GPIO_PIN_x where x can be (0..15).
      * @param  PinState specifies the value to be written to the selected bit.
      *          This parameter can be one of the GPIO_PinState enum values:
      *            @arg GPIO_PIN_RESET: to clear the port pin
      *            @arg GPIO_PIN_SET: to set the port pin
      * @retval None
      */
    void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
    {
      /* Check the parameters */
      assert_param(IS_GPIO_PIN(GPIO_Pin));
      assert_param(IS_GPIO_PIN_ACTION(PinState));

      if(PinState != GPIO_PIN_RESET)
      {
        GPIOx->BSRR = GPIO_Pin;
      }
      else
      {
        GPIOx->BSRR = (uint32_t)GPIO_Pin << 16U;
      }
    }

    HAL_GPIO_TogglePin

    C
    /**
      * @brief  Toggles the specified GPIO pins.
      * @param  GPIOx Where x can be (A..K) to select the GPIO peripheral for STM32F429X device or
      *                      x can be (A..I) to select the GPIO peripheral for STM32F40XX and STM32F427X devices.
      * @param  GPIO_Pin Specifies the pins to be toggled.
      * @retval None
      */
    void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
    {
      uint32_t odr;

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

      /* get current Output Data Register value */
      odr = GPIOx->ODR;

      /* Set selected pins that were at low level, and reset ones that were high */
      GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin);
    }

    CubeF4软件包Example示例:

    1. GPIO_IOToggle

    int main(void)
    { 
      static GPIO_InitTypeDef  GPIO_InitStruct;
     
       /* -2- Configure PG.6, PG.7, PG10 and PG.12 IOs in output push-pull mode to
             drive external LEDs */
      GPIO_InitStruct.Pin = (GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_10 | GPIO_PIN_12);
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_PULLUP;
      GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
     
      HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
     
      /* -3- Toggle PG.6, PG.7, PG10 and PG.12 IOs in an infinite loop */ 
      while (1)
      {
        HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_6);
        /* Insert delay 100 ms */
        HAL_Delay(100);
        HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_7);
        /* Insert delay 100 ms */
        HAL_Delay(100);
        HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_10);
        /* Insert delay 100 ms */
        HAL_Delay(100);
        HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_12);
        /* Insert delay 100 ms */
        HAL_Delay(100);
      }
    }

    2.GPIO_EXTI

    int main(void)
    {  
      GPIO_InitTypeDef   GPIO_InitStructure;
    
      /* Enable GPIOA clock */
      __HAL_RCC_GPIOA_CLK_ENABLE();
     
      /* Configure PA0 pin as input floating */
      GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;
      GPIO_InitStructure.Pull = GPIO_NOPULL;
      GPIO_InitStructure.Pin = GPIO_PIN_0;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
    
      /* Enable and set EXTI Line0 Interrupt to the lowest priority */
      HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 0);
      HAL_NVIC_EnableIRQ(EXTI0_IRQn);
    }
    
    /**
      * @brief EXTI line detection callbacks
      * @param GPIO_Pin: Specifies the pins connected EXTI line
      * @retval None
      */
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    {
      if(GPIO_Pin == KEY_BUTTON_PIN)
      {
        /* Toggle LED2 */
        BSP_LED_Toggle(LED2);
      }
    } 

    CubeMX相关设置

     GPIO为输出模式的设置

    GPIO为输入模式的设置

    GPIOEXTI模式的设置

    此处的MODE其实是多个模式的组合,对于本文章而言,其实是MODE_INPUT

    C
    #define  GPIO_MODE_IT_RISING                    (MODE_INPUT | EXTI_IT | TRIGGER_RISING)

    作者:Alo723

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32 GPIO外设系统深度解析学习指南

    发表回复