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 isclocked below the maximum system frequency, to update the voltage scaling valueregarding 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 PCLK2clocks dividers */RCC_ClkInitStructure.ClockType = RCC_CLOCKTYPE_SYSCLK;RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_1); //ͬʱÉèÖÃFLASHÑÓʱÖÜÆÚΪ1if (ret != HAL_OK) while (1);}
恢复各外设状态,比如GPIO、串口等初始化。在需要进入STOP模式的地方直接调用函数。
static void enter_stop_mode(void){//1. 配置stop之前各外设system_config_before_stop();//2.设置唤醒中断stop_exit_config();//3. 进入stopHAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);//3.退出stop后恢复各外设clock_config_after_stop();//4.恢复各外设gpioInit();uart1Init(115200);}
目前测试到消耗电流与数据手册一致。
附上工程代码,有需要的朋友可以参考。
更多内容,欢迎关注我的公众号。 微信扫一扫下方二维码即可关注: