你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

关于STM32F103使用LL库GPIO配置时出现的BUG分析

[复制链接]
yey1996 提问时间:2020-5-1 16:27 /
代码由STM32CubeMx 5.6.1生成
库版本:STM32Cube_FW_F1_V1.8.0

一、问题复现:
1、当需要配置IO口推挽输出高电平时,实际输出依然是低电平:
voidMX_GPIO_Init(void)
{
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOE);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOF);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);

  /**/
  LL_GPIO_SetOutputPin(GPIOE, LL_GPIO_PIN_5);

  /**/
  GPIO_InitStruct.Pin = LL_GPIO_PIN_5;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
  GPIO_InitStruct.Speed =LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType =LL_GPIO_OUTPUT_PUSHPULL;
  LL_GPIO_Init(GPIOE, &GPIO_InitStruct);
}

二、问题分析
1、通过展开 LL_GPIO_Init函数:
ErrorStatusLL_GPIO_Init(GPIO_TypeDef *GPIOx, LL_GPIO_InitTypeDef *GPIO_InitStruct)
{
  uint32_t pinmask;
  uint32_t pinpos;
  uint32_t currentpin;

  /* Check the parameters */
  assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
assert_param(IS_LL_GPIO_PIN(GPIO_InitStruct->Pin));

  /* ------------------------- Configure theport pins ---------------- */
  /* Initialize pinpos on first pin set */

  pinmask = ((GPIO_InitStruct->Pin) <<GPIO_PIN_MASK_POS) >> GPIO_PIN_NB;
  pinpos = POSITION_VAL(pinmask);

  /* Configure the port pins */
  while ((pinmask  >> pinpos) != 0u)
  {
    /* skip if bit is not set */
    if ((pinmask & (1u << pinpos)) !=0u)
    {
      /* Get current io position */
      if (pinpos < GPIO_PIN_MASK_POS)
      {
        currentpin = (0x00000101uL <<pinpos);
      }
      else
      {
        currentpin = ((0x00010001u <<(pinpos - GPIO_PIN_MASK_POS)) | 0x04000000u);
      }

      /* Check Pin Mode and Pin Pull parameters*/
     assert_param(IS_LL_GPIO_MODE(GPIO_InitStruct->Mode));
     assert_param(IS_LL_GPIO_PULL(GPIO_InitStruct->Pull));

      /* Pin Mode configuration */
      LL_GPIO_SetPinMode(GPIOx, currentpin,GPIO_InitStruct->Mode);

      /* Pull-up Pull-down resistorconfiguration*/
      LL_GPIO_SetPinPull(GPIOx,currentpin, GPIO_InitStruct->Pull);

      if ((GPIO_InitStruct->Mode ==LL_GPIO_MODE_OUTPUT) || (GPIO_InitStruct->Mode == LL_GPIO_MODE_ALTERNATE))
      {
        /* Check speed and Output modeparameters */
       assert_param(IS_LL_GPIO_SPEED(GPIO_InitStruct->Speed));
       assert_param(IS_LL_GPIO_OUTPUT_TYPE(GPIO_InitStruct->OutputType));

        /* Speed mode configuration */
        LL_GPIO_SetPinSpeed(GPIOx, currentpin,GPIO_InitStruct->Speed);

        /* Output mode configuration*/
        LL_GPIO_SetPinOutputType(GPIOx,currentpin, GPIO_InitStruct->OutputType);
      }
    }
    pinpos++;
  }
  return (SUCCESS);
}
其中有对IO的上下拉配置操作:
LL_GPIO_SetPinPull(GPIOx,currentpin, GPIO_InitStruct->Pull);
__STATIC_INLINE voidLL_GPIO_SetPinPull(GPIO_TypeDef *GPIOx, uint32_t Pin, uint32_t Pull)
{
  MODIFY_REG(GPIOx->ODR, (Pin >>GPIO_PIN_MASK_POS), Pull << (POSITION_VAL(Pin >>GPIO_PIN_MASK_POS)));

}
而STM32F103对上下拉的配置是通过对ODR寄存器的操作,且当IO口配置为输出,不对上下拉进行操作时,即GPIO_InitStruct->Pull默认为0。
导致当LL_GPIO_Init函数中对LL_GPIO_SetPinPull(GPIOx,currentpin, GPIO_InitStruct->Pull);设置时,又一次将ODR对应的位设置为了0,导致IO口输出低电平,从而无法默认输出配置的高电平。

三、解决方案:
1、当使用LL库时,在配置GPIO输出或输入时,最好对上拉/下拉进行配置,否则IO口默认配置为下拉模式;
2、可使用HAL库替代LL库,HAL库在配置IO口为输出模式时,不会对IO口进行上下拉的默认配置,但同样配置为输入时,也会默认为输入下拉模式。


收藏 评论3 发布时间:2020-5-1 16:27

举报

3个回答
yey1996 回答时间:2020-5-1 16:28:45
不知道大家有没有注意到这种情况
ryan chen 回答时间:2020-8-29 16:48:25
我刚才也遇到了一样的情况,我控制一个LED灯,会被默认配置为低电平。但是Cube生成的代码设置初始电平却在初始化结构体之前,相当于没用。
ryan chen 回答时间:2020-8-29 16:50:16
我刚才遇到通用的问题。设置初始电平为高完全不起作用,Cube默认把设置初始电平放在初始化结构体之前,而初始化结构体又默认把拉为低电平。
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版