代码由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默认把设置初始电平放在初始化结构体之前,而初始化结构体又默认把拉为低电平。 |