STM32L051进入STOP模式后,除去通过RTC唤醒,还可通过外部中断唤醒,在stop without rtc模式下电流消耗能达到0.4uA。很多时候,我们需要使用STM32的串口进行唤醒,比如接收到串口命令后MCU唤醒进行相关操作。本文总结下STM32L051的STOP模式,通过外部中断「按键、串口」进行唤醒。
串口唤醒的思路就是在MCU进入STOP前将RX脚设为EXTI模式,并使能对应的中断,唤醒后重新初始化串口、配置时钟。实际上都是使用的外部中断唤醒。
- 在进入STOP模式前对外设进行设置,GPIO要设置成模拟输入状态,取消串口配置恢复默认。
static void system_config_before_stop(void)
{
GPIO_InitTypeDef GPIO_Initure;
HAL_UART_DeInit(&huart1);
/* Enable Ultra low power mode */
HAL_PWREx_EnableUltraLowPower();
/* Enable the fast wake up from Ultra low power mode */
HAL_PWREx_EnableFastWakeUp();
/* Select HSI as system clock source after Wake Up from Stop mode */
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);
/* Enable GPIOs clock */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/* Configure all GPIO port pins in Analog Input mode (floating input trigger OFF) */
GPIO_Initure.Pin = GPIO_PIN_All;
GPIO_Initure.Mode = GPIO_MODE_ANALOG;
GPIO_Initure.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_Initure);
HAL_GPIO_Init(GPIOB, &GPIO_Initure);
HAL_GPIO_Init(GPIOC, &GPIO_Initure);
/* Disable GPIOs clock */
__HAL_RCC_GPIOA_CLK_DISABLE();
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_GPIOC_CLK_DISABLE();
}
- 设置唤醒源中断,这里配置了按键和串口RX相关中断。
static void stop_exit_config(void)
{
GPIO_InitTypeDef GPIO_Initure = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_Initure.Pin = KEY_PIN;
GPIO_Initure.Mode = GPIO_MODE_IT_RISING;
GPIO_Initure.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(KEY_PORT, &GPIO_Initure);
HAL_NVIC_SetPriority(EXTI2_3_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(EXTI2_3_IRQn);
GPIO_Initure.Pin = GPIO_PIN_10;
GPIO_Initure.Mode = GPIO_MODE_IT_FALLING;
GPIO_Initure.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_Initure);
HAL_NVIC_SetPriority(EXTI4_15_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
}
- 调用库函数进入STOP模式。
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
- 退出STOP模式后要恢复时钟。特别注意在进入STOP模式后系统时钟变成了MSI。
static void clock_config_after_stop(void)
{
HAL_StatusTypeDef ret = HAL_OK;
RCC_OscInitTypeDef RCC_OscInitStructure = {0};
RCC_ClkInitTypeDef RCC_ClkInitStructure = {0};
/* Enable Power Control clock */
__HAL_RCC_PWR_CLK_ENABLE();
/* The voltage scaling allows optimizing the power consumption when the device is
clocked below the maximum system frequency, to update the voltage scaling value
regarding system frequency refer to product datasheet. */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/* Get the Oscillators configuration according to the internal RCC registers */
HAL_RCC_GetOscConfig(&RCC_OscInitStructure);
/* After wake-up from STOP reconfigure the system clock: Enable HSI and PLL */
RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStructure.HSEState = RCC_HSE_OFF;
RCC_OscInitStructure.HSIState = RCC_HSI_ON;
RCC_OscInitStructure.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStructure.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStructure.PLL.PLLMUL = RCC_PLLMUL_4;
RCC_OscInitStructure.PLL.PLLDIV = RCC_PLLDIV_2;
ret = HAL_RCC_OscConfig(&RCC_OscInitStructure); //³õʼ»¯
if (ret != HAL_OK) while (1);
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStructure.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_1); //ͬʱÉèÖÃFLASHÑÓʱÖÜÆÚΪ1
if (ret != HAL_OK) while (1);
}
- 恢复各外设状态,比如GPIO、串口等初始化。
- 在需要进入STOP模式的地方直接调用函数。
static void enter_stop_mode(void)
{
//1. 配置stop之前各外设
system_config_before_stop();
//2.设置唤醒中断
stop_exit_config();
//3. 进入stop
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
//3.退出stop后恢复各外设
clock_config_after_stop();
//4.恢复各外设
gpioInit();
uart1Init(115200);
}
目前测试到消耗电流与数据手册一致。