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