yy1025 发表于 2020-5-1 16:27:32

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

代码由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口进行上下拉的默认配置,但同样配置为输入时,也会默认为输入下拉模式。

yy1025 发表于 2020-5-1 16:28:45

不知道大家有没有注意到这种情况

ryanchen1 发表于 2020-8-29 16:48:25

我刚才也遇到了一样的情况,我控制一个LED灯,会被默认配置为低电平。但是Cube生成的代码设置初始电平却在初始化结构体之前,相当于没用。

ryanchen1 发表于 2020-8-29 16:50:16

我刚才遇到通用的问题。设置初始电平为高完全不起作用,Cube默认把设置初始电平放在初始化结构体之前,而初始化结构体又默认把拉为低电平。
页: [1]
查看完整版本: 关于STM32F103使用LL库GPIO配置时出现的BUG分析