关于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口进行上下拉的默认配置,但同样配置为输入时,也会默认为输入下拉模式。
不知道大家有没有注意到这种情况 我刚才也遇到了一样的情况,我控制一个LED灯,会被默认配置为低电平。但是Cube生成的代码设置初始电平却在初始化结构体之前,相当于没用。 我刚才遇到通用的问题。设置初始电平为高完全不起作用,Cube默认把设置初始电平放在初始化结构体之前,而初始化结构体又默认把拉为低电平。
页:
[1]