STM32G031F6停机模式编程后功耗异常,如何无需断电恢复低功耗?
STM32G031F6 Stop模式编程后功耗异常问题
问题描述
使用STM32G031F6微控制器配置Stop模式,代码如下:
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; PWR->CR1 = (PWR->CR1 & ~PWR_CR1_LPMS) | PWR_CR1_LPMS_0; SCB->SCR |= (uint32_t)SCB_SCR_SLEEPDEEP_Msk; DBG->CR |= DBG_CR_DBG_STOP; __WFI(); SCB->SCR &= (uint32_t)~SCB_SCR_SLEEPDEEP_Msk; SystemCoreClockUpdate(); SysTick_Config((SystemCoreClock / 1000));
遇到的问题:通过ST-Link编程后,Stop模式下功耗为300uA(正常应为4uA);但完全切断电源并重新连接后,功耗恢复至4uA。需要实现编程后无需断电,Stop模式功耗就能达到4uA。
解决方法
1. 关闭调试模块在低功耗模式下的运行权限
代码中设置的DBG->CR |= DBG_CR_DBG_STOP;会让调试模块在Stop模式下保持激活,直接拉高功耗。如果不需要在Stop模式下调试,需禁用该功能:
// 禁止调试模块在Sleep/Stop/Standby模式下运行 DBG->CR &= ~(DBG_CR_DBG_SLEEP | DBG_CR_DBG_STOP | DBG_CR_DBG_STANDBY);
2. 进入Stop模式前关闭所有未使用的外设时钟
ST-Link编程后,部分外设时钟可能处于默认激活状态,断电后才会复位。进入低功耗前需手动关闭所有不需要的外设时钟:
// 关闭AHB总线外设时钟(根据实际使用保留必要的) RCC->AHBENR &= ~(RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN); // 关闭APB1总线外设时钟 RCC->APBENR1 &= ~(RCC_APBENR1_USART2EN | RCC_APBENR1_I2C1EN); // 关闭APB2总线外设时钟 RCC->APBENR2 &= ~(RCC_APBENR2_USART1EN | RCC_APBENR2_SPI1EN);
3. 将未使用的GPIO配置为模拟输入
未使用的GPIO若处于浮空或推挽输出状态,会产生额外功耗。将它们配置为模拟输入是最低功耗的方式:
GPIO_InitTypeDef GPIO_InitStruct = {0}; // 配置GPIOA所有未使用引脚为模拟输入 GPIO_InitStruct.Pin = GPIO_PIN_All; // 若有引脚需保留功能,替换为对应Pin掩码 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 同理配置GPIOB、GPIOC等其他GPIO端口
4. 完全关闭SysTick时钟
原代码仅关闭了SysTick中断,还需关闭SysTick时钟以消除其功耗:
// 关闭SysTick时钟和中断 SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);
5. 确保电源控制寄存器配置正确
检查PWR_CR1的其他位,确保没有额外的电源域被激活。例如,可将欠压检测配置为低功耗模式:
// 配置欠压检测为低功耗模式 PWR->CR1 |= PWR_CR1_ULP;
优化后的完整Stop模式进入代码示例
// 1. 关闭SysTick时钟和中断 SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk); // 2. 关闭所有未使用的外设时钟 RCC->AHBENR &= ~(RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN); RCC->APBENR1 &= ~(RCC_APBENR1_USART2EN | RCC_APBENR1_I2C1EN); RCC->APBENR2 &= ~(RCC_APBENR2_USART1EN | RCC_APBENR2_SPI1EN); // 3. 配置未使用GPIO为模拟输入 GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_All; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // 4. 禁用调试模块在低功耗模式下运行 DBG->CR &= ~(DBG_CR_DBG_SLEEP | DBG_CR_DBG_STOP | DBG_CR_DBG_STANDBY); // 5. 配置Stop模式 PWR->CR1 = (PWR->CR1 & ~PWR_CR1_LPMS) | PWR_CR1_LPMS_0; // 进入Stop 0模式 SCB->SCR |= (uint32_t)SCB_SCR_SLEEPDEEP_Msk; // 6. 进入低功耗模式 __WFI(); // 唤醒后的恢复操作 SCB->SCR &= (uint32_t)~SCB_SCR_SLEEPDEEP_Msk; SystemCoreClockUpdate(); SysTick_Config((SystemCoreClock / 1000));
内容的提问来源于stack exchange,提问作者Mohammad
相关产品推荐
相关产品推荐

