STM32L051低功耗STOP模式串口中断唤醒

STM32L051进入STOP模式后,除去通过RTC唤醒,还可通过外部中断唤醒,在stop without rtc模式下电流消耗能达到0.4uA。很多时候,我们需要使用STM32的串口进行唤醒,比如接收到串口命令后MCU唤醒进行相关操作。本文总结下STM32L051的STOP模式,通过外部中断「按键、串口」进行唤醒。

串口唤醒的思路就是在MCU进入STOP前将RX脚设为EXTI模式,并使能对应的中断,唤醒后重新初始化串口、配置时钟。实际上都是使用的外部中断唤醒。

  1. 在进入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();
}
  1. 设置唤醒源中断,这里配置了按键和串口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);

}
  1. 调用库函数进入STOP模式。
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
  1. 退出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);
}
  1. 恢复各外设状态,比如GPIO、串口等初始化。
  2. 在需要进入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);
}

目前测试到消耗电流与数据手册一致。

在这里插入图片描述
附上工程代码,有需要的朋友可以参考。

更多内容,欢迎关注我的公众号。 微信扫一扫下方二维码即可关注:
扫码加入微信公众号:TonyCode

  • 3
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值