STM32标准库与HAL库中的Mode和Pull设置

Posted 何事误红尘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32标准库与HAL库中的Mode和Pull设置相关的知识,希望对你有一定的参考价值。

目录

概述

最近做SDK的BSP驱动。之前使用STM32CubeMX进行开发,设计GPIO的初始化接口包括了mode、pull两个参数。
现在对接另一款国产芯片,芯片驱动仅支持标准库,在GPIO的初始化结构体中没有pull成员,且mode也不完全相同。那么该如何处理这两个参数呢?

HAL库

先看下STM32L152CCTx的工程,GPIO的初始化函数中对于pull的处理:

void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)


      /* Activate the Pull-up or Pull down resistor for the current IO */
      temp = GPIOx->PUPDR;
      CLEAR_BIT(temp, GPIO_PUPDR_PUPDR0 << (position * 2));
      SET_BIT(temp, (GPIO_Init->Pull) << (position * 2));
      GPIOx->PUPDR = temp;
      

也就是操作PUPDR寄存器,查看手册定义如下:

而支持的mode如下:

#define  GPIO_MODE_INPUT                        (0x00000000U)   /*!< Input Floating Mode                   */
#define  GPIO_MODE_OUTPUT_PP                    (0x00000001U)   /*!< Output Push Pull Mode                 */
#define  GPIO_MODE_OUTPUT_OD                    (0x00000011U)   /*!< Output Open Drain Mode                */
#define  GPIO_MODE_AF_PP                        (0x00000002U)   /*!< Alternate Function Push Pull Mode     */
#define  GPIO_MODE_AF_OD                        (0x00000012U)   /*!< Alternate Function Open Drain Mode    */

#define  GPIO_MODE_ANALOG                       (0x00000003U)   /*!< Analog Mode  */

标准库

现在看下标准库时如何初始化的。标准库直接参考STM32F103的工程,GPIO初始化函数的主要代码如下:

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)


/*---------------------------- GPIO Mode Configuration -----------------------*/
  currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
  if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
   
    /* Check the parameters */
    assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
    /* Output mode */
    currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
  
/*---------------------------- GPIO CRL Configuration ------------------------*/
  /* Configure the eight low port pins */
  if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
  
    tmpreg = GPIOx->CRL;
    for (pinpos = 0x00; pinpos < 0x08; pinpos++)
    
      pos = ((uint32_t)0x01) << pinpos;
      /* Get the port pins position */
      currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
      if (currentpin == pos)
      
        pos = pinpos << 2;
        /* Clear the corresponding low control register bits */
        pinmask = ((uint32_t)0x0F) << pos;
        tmpreg &= ~pinmask;
        /* Write the mode configuration in the corresponding bits */
        tmpreg |= (currentmode << pos);
        /* Reset the corresponding ODR bit */
        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
        
          GPIOx->BRR = (((uint32_t)0x01) << pinpos);
        
        else
        
          /* Set the corresponding ODR bit */
          if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
          
            GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
          
        
      
    
    GPIOx->CRL = tmpreg;
  
  

  1. 获取模式的低四位,得到mode。若为输出,则一并设置 speed;
  2. 根据上拉还是下拉,管脚输出对应电平。

从代码可以看出,只有输入才会有上下拉。而支持的mode如下:

typedef enum
 GPIO_Mode_AIN = 0x0,
  GPIO_Mode_IN_FLOATING = 0x04,
  GPIO_Mode_IPD = 0x28,
  GPIO_Mode_IPU = 0x48,
  GPIO_Mode_Out_OD = 0x14,
  GPIO_Mode_Out_PP = 0x10,
  GPIO_Mode_AF_OD = 0x1C,
  GPIO_Mode_AF_PP = 0x18
GPIOMode_TypeDef;

与HAL库相比,多了GPIO_Mode_IPDGPIO_Mode_IPU。也就是HAL库需要设置为输入模式,再单独设置上拉、下拉、浮空,而标准库直接定义了上拉输入模式、下拉输入模式和浮空输入模式。

另外,每个pin的模式由4bit控制,为什么枚举采用8bit呢?
这一点从代码中也可以看出来,高四位的0x1表示输出。

再看HAL库

查看STM32F103参考手册,也并没有PUPDR寄存器,应该是不同内核的原因。
用STM32CubeMX生成一个STM32F103的HAL库版本,查看下HAL库是如何处理的。生成后直接定位到HAL_GPIO_Init函数:

可以看到同样是对寄存器的4bit进行设置。展开switch,可以看到对Pull的处理,也就是先判断mode。如果为输入,则继续判断pull,最终还是归纳到标准库支持的8个mode:

到这里,SDK该如何处理mode和pull参数也就清晰了。

以上是关于STM32标准库与HAL库中的Mode和Pull设置的主要内容,如果未能解决你的问题,请参考以下文章

STM32标准库与HAL库对照学习教程外设篇--红外避障传感器

STM32标准库与HAL库对照学习教程特别篇--IIC通信原理讲解

STM32实现光照强度传感器(BH1750)(标准库与HAL库实现)

STM32实现光照强度传感器(BH1750)(标准库与HAL库实现)

STM32实现六轴姿态测量陀螺仪模块JY61P(标准库与HAL库实现)

STM32实现六轴姿态测量陀螺仪模块JY61P(标准库与HAL库实现)