在项目中发现正常初始化的IO口PB2,在进入低功耗模式时,会有90微安左右的漏电流。原因是在初始化AD采集IO口PB1时,传入的结构体参数不全,改变了PB2的状态。
MCU为STM32L151,使用的库函数版本如下:
库函数中初始化IO口函数为:
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));
assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
assert_param(IS_GPIO_PUPD(GPIO_InitStruct->GPIO_PuPd));
/* -------------------------Configure the port pins---------------- */
/*-- GPIO Mode Configuration --*/
for (pinpos = 0x00; pinpos < 0x10; pinpos++)
{
pos = ((uint32_t)0x01) << pinpos;
/* Get the port pins position */
currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
if (currentpin == pos)
{
GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (pinpos * 2));
GPIOx->MODER |= (((uint32_t)GPIO_InitStruct->GPIO_Mode) << (pinpos * 2));
if ((GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT) || (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_AF))
{
/* Check Speed mode parameters */
assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
/* Speed mode configuration */
GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (pinpos * 2));
GPIOx->OSPEEDR |= ((uint32_t)(GPIO_InitStruct->GPIO_Speed) << (pinpos * 2));
/*Check Output mode parameters */
assert_param(IS_GPIO_OTYPE(GPIO_InitStruct->GPIO_OType));
/* Output mode configuration */
GPIOx->OTYPER &= ~((GPIO_OTYPER_OT_0) << ((uint16_t)pinpos)) ;
GPIOx->OTYPER |= (uint16_t)(((uint16_t)GPIO_InitStruct->GPIO_OType) << ((uint16_t)pinpos));
}
/* Pull-up Pull down resistor configuration */
GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)pinpos * 2));
GPIOx->PUPDR |= (((uint32_t)GPIO_InitStruct->GPIO_PuPd) << (pinpos * 2));
}
}
}
初始化AD采集IO口如下:
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = ADC_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(ADC_PORT, &GPIO_InitStructure);
AD采集IO口为PB1,被影响的IO口为PB2。初始化PB1时如果不加GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL这句话,便会影响PB2,因为此时GPIO_Init()函数中传入的结构体参数为:
可以看到此时GPIO_Speed和GPIO_PuPd两个参数的值并不是有效值,而是GPIO_InitStructure结构体中未经初始化的局部变量值。
/* Pull-up Pull down resistor configuration */
GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)pinpos * 2));
GPIOx->PUPDR |= (((uint32_t)GPIO_InitStruct->GPIO_PuPd) << (pinpos * 2));
在执行这两句后,PB2被改成了下拉,而实际上PB2设置的是无上拉下拉,而且是在初始化PB1之前设置的。
参考手册中对于上拉下拉寄存器的描述如下:
由于传入的参数GPIO_PuPd是0x08,也就是1000,此时执行GPIOx->PUPDR |= (((uint32_t)GPIO_InitStruct->GPIO_PuPd) << (pinpos * 2))这句话时,左移两位后,PB2控制位对应的10,PB1控制位对应的是00,也就是将PB2设置为下拉,PB1设置为无上拉下拉,因此改变了PB2的状态。