STM32L4 使用低功耗串口唤醒休眠状态源码分享

STM32L4 使用低功耗串口唤醒休眠状态源码分享

一、STM32L4系列介绍

STM32L4系列是意法半导体(STMicroelectronics)推出的一个专注于超低功耗高性能平衡的Arm® Cortex®-M4微控制器系列。该系列结合了出色的能效和强大的处理能力,特别适用于对电池寿命和性能都有较高要求的应用场景。

以下是STM32L4系列的关键特点和介绍:

  1. 核心处理器

    • 基于 Arm® Cortex®-M4 内核 ,支持 DSP指令集单精度浮点单元(FPU)
    • 最高运行频率可达 80 MHz ,提供高达 100 DMIPS 的计算性能,能够处理较为复杂的算法和实时控制任务。
  2. 超低功耗特性 (Ultra-Low Power)

    • 多种低功耗模式:支持多种深度睡眠、睡眠、低功耗运行和待机模式。
    • 极低的功耗
      • 运行模式 :功耗低至约 70 µA/MHz(典型值)。
      • 停止模式:低至几 µA 级别(如 L4R5/L4R9 系列典型值约 1.7 µA)。
      • 待机模式 :可低至 0.23 µA(典型值,部分型号支持 RTC)。
      • 关机模式 :最低可至 30 nA(典型值)。
    • 动态电压调节:根据 CPU 频率动态调整核心电压以优化功耗。
    • 超低功耗外设:集成多种专为低功耗优化的外设,如低功耗定时器 (LPTIM)、低功耗 UART (LPUART)、低功耗 ADC (LPADC)。
    • 快速唤醒:从低功耗模式唤醒至运行模式的速度非常快(通常在几 µs 级别),确保系统响应迅速的同时保持低功耗。
    • ULPBench™认证:在业内标准的超低功耗基准测试中表现优异。
  3. 丰富的存储资源

    • Flash 存储器:容量范围广泛,从 64 KB 到 2 MB 不等(具体取决于子系列和型号)。
    • SRAM:通常配置 128 KB 或更高(如 L4R5/L4R9 系列可达 640 KB),部分型号支持核心耦合存储器(CCM RAM)以加速关键代码执行。
    • EEPROM:部分型号集成了真正的片上 EEPROM(如 L4P5/L4Q5 系列)。
  4. 先进的外设集

    • 模拟外设
      • ADC:高精度模数转换器(如 12-bit, 5 Msps),部分支持过采样提升有效分辨率。
      • DAC:数模转换器(如 12-bit)。
      • 比较器
    • 定时器:丰富的定时器资源,包括高级控制定时器(如 TIM1/TIM8)、通用定时器(TIMx)、基本定时器(TIM6/TIM7)以及低功耗定时器(LPTIM)。
    • 通信接口
      • 多个 USART/UART/LPUART。
      • 多个 SPI/I2S(支持高速模式)。
      • 多个 I2C(支持 SMBus/PMBus)。
      • USB 2.0 Full Speed Device/Host/OTG 控制器(部分型号支持无晶振设计)。
      • CAN 2.0B(部分型号)。
      • SDMMC 接口(支持 SD/SDIO/MMC)。
    • 其他
      • 高级加密硬件加速器(AES)。
      • 哈希处理器。
      • 真随机数生成器(TRNG)。
      • 电容触摸感应(TSC)。
      • LCD 驱动器(部分型号支持)。
      • 硬件 CRC 计算单元。
      • DMA 控制器。
  5. 安全性与可靠性

    • 内存保护单元(MPU)。
    • 硬件加密加速(AES、HASH)。
    • 安全启动选项。
    • 防篡改检测(部分型号)。
    • 看门狗定时器(独立窗口看门狗)。
  6. 开发支持

    • 强大的生态系统:STM32CubeMX(初始化代码生成)、STM32CubeIDE(集成开发环境)、STM32CubeProgrammer(编程工具)。
    • 丰富的软件库:HAL库、LL库、中间件(如 FreeRTOS, FatFS, USB 库等)。
    • 多种评估板和开发套件。
  7. 应用领域

    • 便携式医疗设备(血糖仪、血压计、心率监测)。
    • 可穿戴设备(智能手表、健身追踪器)。
    • 工业传感器网络(低功耗无线传感器节点)。
    • 智能家居设备(门锁、传感器、遥控器)。
    • 手持式仪器仪表。
    • 电池供电的物联网(IoT)终端设备。
    • 需要低功耗和一定处理能力的消费电子产品。

总结:

STM32L4系列凭借其Cortex-M4内核的计算能力行业领先的超低功耗特性丰富的外设资源 以及强大的生态系统支持,成为开发需要在性能与功耗之间取得最佳平衡的应用的理想选择。其多样化的子系列和型号可以满足不同应用场景的具体需求。

二、低功耗串口介绍

  1. 概述

    STM32 的低功耗串口(Low-Power Universal Asynchronous Receiver Transmitter, LPUART)是一种专为低功耗应用场景设计的串行通信接口。它旨在满足电池供电设备、物联网节点等需要长时间待机或间歇性工作的设备对低功耗通信的需求。与传统 UART 相比,LPUART 在保持异步串行通信基本功能的同时,显著降低了在低功耗模式下的功耗。

  2. 主要特点

    • 超低功耗: 这是 LPUART 的核心优势。它可以在器件处于低功耗睡眠模式 (如 Stop mode, Standby mode with LPUART wake-up)时保持活动状态,并消耗极低的电流(通常在微安级别)。
    • 独立时钟源: LPUART 通常使用一个独立的低功耗时钟源(如 LSE - Low Speed External 晶振或 LSI - Low Speed Internal RC 振荡器),而不是系统主时钟(HSE/HIS/PLL)。这使得当主时钟域被关闭以节省功耗时,LPUART 仍能正常工作。
    • 自动唤醒: LPUART 支持接收唤醒功能。当器件处于低功耗模式时,LPUART 模块可以侦听总线。一旦检测到有效的起始位(Start Bit),它能自动唤醒整个微控制器系统,使其进入运行模式来处理接收到的数据。处理完毕后,系统可以再次进入低功耗模式。
    • 波特率范围: LPUART 支持的波特率范围通常较低(例如 9600 bps, 19200 bps),这是为了匹配其低速、低功耗时钟源。具体范围需参考芯片数据手册。
    • 异步通信基础功能: LPUART 保留了标准 UART 的基本功能:异步串行通信、可配置的数据位长度(8 位或 9 位)、停止位(1 位或 2 位)、奇偶校验(奇校验、偶校验或无校验)。
  3. 应用场景

    • 电池供电设备: 如无线传感器网络节点、便携式医疗设备、智能表计、远程控制器等,需要在大部分时间休眠,仅在需要通信时唤醒。
    • 需要长待机的设备: 对功耗极其敏感,要求待机电流极低的设备。
    • 低速、间歇性数据传输: 例如接收配置命令、上报传感器数据等不需要高速连续通信的场景。
  4. 工作流程(典型低功耗应用)

    1. 初始化: 配置 LPUART 参数(波特率、数据位、停止位、校验位),启用接收中断或 DMA,并配置唤醒源为 LPUART 接收事件。
    2. 进入低功耗模式: 系统执行 HAL_PWR_EnterStopMode()HAL_PWR_EnterStandbyMode()(需配置唤醒源)。
    3. 侦听与唤醒: LPUART 在低功耗模式下持续侦听总线。当检测到起始位时:
      • 触发唤醒中断。
      • 微控制器退出低功耗模式,恢复主时钟运行。
    4. 处理数据: MCU 执行唤醒中断服务程序(ISR),在 ISR 或主循环中读取 LPUART 接收到的数据并进行处理。
    5. 返回低功耗: 数据处理完成后,系统再次进入低功耗模式,等待下一次通信。
  5. 配置注意事项

    • 时钟源选择: 确保 LPUART 使用的低速时钟源(LSE/LSI)已启用且配置正确。
    • 唤醒配置: 在进入低功耗模式前,必须正确配置唤醒源为 LPUART。
    • 中断/DMA: 通常使用中断方式处理接收数据,以减少 CPU 轮询开销。DMA 在某些型号和模式下也可能可用,但需注意其在低功耗模式下的行为。
    • IO 配置: LPUART 使用的 GPIO 引脚需要正确配置为复用功能模式。
    • 波特率精度: 低速时钟源(尤其是 LSI)的精度相对较低,在高波特率下误差可能较大。需根据数据手册计算实际波特率误差是否满足应用要求。
  6. 总结

    STM32 的 LPUART 是专为超低功耗应用设计的串行通信接口。其核心价值在于能在系统深度睡眠时维持极低的功耗,并通过接收唤醒功能自动唤醒系统处理通信事件。合理利用 LPUART 可以显著延长电池供电设备的续航时间,是开发低功耗嵌入式系统的关键组件之一。

三、综合案例

1、进入STOP2模式休眠

cpp 复制代码
HAL_SuspendTick();
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);

HAL_SuspendTick()函数的作用是暂停系统定时器(SysTick)的计数和中断。具体来说:

  1. 暂停计数

    该函数会停止SysTick计数器的运行,使计数器值不再更新。

  2. 禁用中断

    同时,它会禁用SysTick的中断请求(IRQ),防止系统因定时器中断而唤醒或触发任务调度。

  • 注意事项
    • 配套使用
      调用HAL_SuspendTick()后,必须通过HAL_ResumeTick()恢复定时器,否则系统时间基准会停滞。
    • RTOS影响
      若使用实时操作系统(如FreeRTOS),暂停SysTick会导致任务调度器停止工作,需谨慎使用。

2、退出休眠后操作

因为进入了STOP2休眠模式,所以退出休眠后需要重新初始化系统时钟,外设不需要初始化:

c 复制代码
bool wkup()
{
	if(!enterSleep)
		return false;
	HAL_ResumeTick();
	SystemClock_Config();
	return true;
}

因为进入休眠的时候调用了HAL_SuspendTick();所以退出后需要调用HAL_ResumeTick();恢复SysTick的计数和中断。

3、低功耗定时器配置

c 复制代码
/************************************************* 
* @copyright: 
* @author:Xupeng
* @date:2022-11-03
* @description: 
**************************************************/  
#include <stm32l4xx.h>
#include "lpuart.h"
#include "wkup.h"



UART_HandleTypeDef hlpuart1;
/************************************************* 
* @function:void lpuart_uart_init()        
* @description: 初始化LPUART   
* @calls:          
* @input:                    
* @return:       
* @others:       
*************************************************/ 
int lpuart_uart_init()
{

	hlpuart1.Instance = LPUART1;
	hlpuart1.Init.BaudRate = 9600;
	hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
	hlpuart1.Init.StopBits = UART_STOPBITS_1;
	hlpuart1.Init.Parity = UART_PARITY_NONE;
	hlpuart1.Init.Mode = UART_MODE_TX_RX;
	hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
	hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
	

	if (HAL_UART_Init(&hlpuart1) != HAL_OK)
	{
		Error_Handler();
	}
    __HAL_UART_DISABLE_IT(&hlpuart1, UART_IT_TC);
    __HAL_UART_ENABLE_IT(&hlpuart1, UART_IT_RXNE);        /* 开启接收中断 */
    HAL_NVIC_EnableIRQ(LPUART1_IRQn);                      /* 使能USART1中断 */
    HAL_NVIC_SetPriority(LPUART1_IRQn, 0, 1);              /* 抢占优先级3,子优先级3 */
	
	
	UART_WakeUpTypeDef UART_WakeUpStruct={0};
    //接收数据不为空时唤醒
	UART_WakeUpStruct.WakeUpEvent=UART_WAKEUP_ON_READDATA_NONEMPTY;  
    //配置LPUART为Stop模式的唤醒源
	HAL_UARTEx_StopModeWakeUpSourceConfig(&hlpuart1, UART_WakeUpStruct); 
    //允许LPUART在任何时间请求时钟
	HAL_UARTEx_EnableClockStopMode(&hlpuart1);
    //使能LPUART的Stop模式功能
	HAL_UARTEx_EnableStopMode(&hlpuart1);


	return 0;
}
/************************************************* 
* @function:void lpuart_irq_handler()        
* @description: LPUART中断处理函数   
* @calls:          
* @input:                    
* @return:       
* @others:       
*************************************************/ 
uint16_t recvCnt = 0;
uint8_t recvBuf[100];
uint32_t recvTime = 0;
void LPUART1_IRQHandler(void)
{
	//HAL_UART_IRQHandler(&hlpuart1);
    uint8_t res;

    if ((__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_RXNE) != RESET)) /* 接收到数据 */
    {
		if(wkup())
			printf("lpuart wkup!\r\n");
        HAL_UART_Receive(&hlpuart1, &res, 1, 1000);
		recvBuf[recvCnt] = res;
		recvCnt ++;
		recvTime = rt_tick_get_millisecond() + 100;
    }
	
	if (__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_ORE) != RESET)
	{
		__HAL_UART_CLEAR_OREFLAG(&hlpuart1);
	}
}

/**
* @brief UART MSP Initialization
* This function configures the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
   GPIO_InitTypeDef GPIO_InitStruct = {0};
   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  if(huart->Instance==LPUART1)
  {

    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;
    PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_LSE;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }


    __HAL_RCC_LPUART1_CLK_ENABLE();

    __HAL_RCC_GPIOC_CLK_ENABLE();
    /**LPUART1 GPIO Configuration
    PC0     ------> LPUART1_RX
    PC1     ------> LPUART1_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    /* LPUART1 interrupt Init */
    HAL_NVIC_SetPriority(LPUART1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(LPUART1_IRQn);
  /* USER CODE BEGIN LPUART1_MspInit 1 */

  /* USER CODE END LPUART1_MspInit 1 */
  }
}

4、综合演示

下面伪代码,使用STM32CubeMx生成后安装下面更改。

c 复制代码
int mian()
{
	uint8_t cnt = 0;
	HAL_Init();
	SystemClock_Config();
	lpuart_uart_init();
	while(1)
	{
		cnt++;
		if(cnt >=10)//10秒后进入低功耗
		{
			cnt = 0;
			enterSleep = true;
			HAL_SuspendTick();
			HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
			//此处等待低功耗串口唤醒后执行其他任务
		}
		HAL_Delay(1000);
	}
	return 0;
}

5、注意点

5.1、进入休眠前一定要调用HAL_SuspendTick(),退出后一定要调用HAL_ResumeTick()

5.2、高速内部(HSI)或外部时钟(HSE)、PLL以及APB和AHB总线时钟在STOP2模式下会被关闭

所以低功耗串口时钟源要选择LSELSI

c 复制代码
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;
    PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_LSE;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }

LSE和LSI由于频率比较低,所以串口波特率不要高于9600;

5.3、要想低功耗串口唤醒MCU,下面的配置必不可少

c 复制代码
UART_WakeUpTypeDef UART_WakeUpStruct={0};
   //接收数据不为空时唤醒
UART_WakeUpStruct.WakeUpEvent=UART_WAKEUP_ON_READDATA_NONEMPTY;  
   //配置LPUART为Stop模式的唤醒源
HAL_UARTEx_StopModeWakeUpSourceConfig(&hlpuart1, UART_WakeUpStruct); 
   //允许LPUART在任何时间请求时钟
HAL_UARTEx_EnableClockStopMode(&hlpuart1);
   //使能LPUART的Stop模式功能
HAL_UARTEx_EnableStopMode(&hlpuart1);
  • HAL_UARTEx_StopModeWakeUpSourceConfig
    HAL_UARTEx_StopModeWakeUpSourceConfig() 函数是 STM32 HAL 库中的一个扩展功能,主要用于在低功耗模式下配置串口唤醒源。其核心作用如下:

    • 功能说明
      1. 唤醒源配置 :在微控制器进入停止模式(STOP Mode)时,该函数允许通过 UART(串口)的特定事件(如接收到起始位或地址匹配)将系统从低功耗状态唤醒。

      2. 低功耗优化:适用于需要长期休眠但需通过串口通信触发的场景(如远程传感器),避免频繁轮询造成的能耗浪费。

      3. 参数控制

        • UART_HandleTypeDef *huart :指定配置的串口实例(如 UART1)。
        • UART_WakeUpTypeDef WakeUpSelection :选择唤醒触发方式:
          • UART_WAKEUP_ON_ADDRESS:地址匹配唤醒(适用于多设备通信),匹配指定的地址。
          • UART_WAKEUP_ON_STARTBIT:起始位检测唤醒。
          • UART_WAKEUP_ON_READDATA_NONEMPTYRXFIFO接受到数据唤醒。
    • 注意事项
      • 兼容性:该函数仅适用于支持低功耗唤醒的 STM32 系列(如 STM32L4/L4+)。
      • 中断配置 :需提前使能 UART 中断(如 HAL_UART_Receive_IT()),确保唤醒事件可被捕获。
      • 唤醒后处理:退出停止模式后需重新初始化时钟和外围设备。
  • HAL_UARTEx_EnableClockStopMode
    HAL_UARTEx_EnableClockStopMode 是 STM32 HAL 库中的一个扩展函数,主要用于 使能 UART 在低功耗模式下的时钟保持功能。其作用可归纳为以下几点:

    1. 支持低功耗场景

      当设备进入低功耗模式(如 Stop 模式)时,系统时钟通常会被暂停以降低功耗。此函数允许 UART 模块在低功耗模式下保持时钟活动,确保 UART 能够持续工作或检测唤醒事件(如接收到数据)。

    2. 实现唤醒功能

      在 Stop 模式下,若 UART 时钟保持活动,设备可通过 UART 接收到的起始位(Start Bit)触发唤醒信号,使系统退出低功耗状态。这对于需要远程唤醒的应用场景(如无线传感器网络)至关重要。

    3. 配置时钟门控

      该函数通过设置 UART 外设寄存器(如 CR3)中的标志位(例如 UCESM),控制时钟在 Stop 模式下的行为。例如:

      c 复制代码
      HAL_UARTEx_EnableClockStopMode(&huart1); // 使能 UART1 的时钟保持
    • 注意事项
      • 需在进入低功耗模式之前调用此函数。
      • 对应的禁用函数为 HAL_UARTEx_DisableClockStopMode()
      • 具体行为依赖芯片型号,需参考对应型号的参考手册(如 STM32L4 系列中的 UCESM 位)。
  • HAL_UARTEx_EnableStopMode
    HAL_UARTEx_EnableStopMode 是 STM32 HAL 库中用于配置 UART 在低功耗模式(Stop 模式)下工作的函数。其主要作用如下:

    1. 功能定义

      该函数使 UART 外设在 MCU 进入低功耗 Stop 模式 时,能够保持通信状态并在唤醒后自动恢复。通过配置相关寄存器,确保:

      • 休眠期间 UART 状态被正确保存
      • 唤醒后无需重新初始化即可继续通信
    2. 应用场景

      适用于需要平衡功耗与通信可靠性的场景,例如:

      • 电池供电设备(如物联网传感器)
      • 间歇性数据传输系统
      • 需要快速唤醒响应的应用
    3. 注意事项

      • 需与 HAL_UARTEx_DisableStopMode 配对使用
      • 启用后,UART 在 Stop 模式下的功耗会略微增加
      • 唤醒时间受波特率影响(典型值 1~2 ms)
      • 需确保时钟配置支持低功耗唤醒
相关推荐
不脱发的程序猿18 小时前
SPI、DSPI、QSPI技术对比
单片机·嵌入式硬件·嵌入式
金线银线还是铜线?1 天前
米德方格MF9005/MF9006:低功耗光能利用的PMIC芯片解析
嵌入式硬件·物联网·iot·太阳能
Arciab1 天前
51单片机_数码管显示
单片机·嵌入式硬件·51单片机
qq_401700411 天前
FreeRTOS用事件组替代全局变量实现同步
单片机
zhongvv1 天前
8位应广单片机与32位M0单片机开发差异总结
经验分享·单片机·嵌入式硬件
咸蛋-超人1 天前
聊一聊 - STM32的堆和栈空间怎么分配
stm32·单片机·嵌入式硬件
raindrops.1 天前
STM32之LL库使用(二)
stm32·单片机·嵌入式硬件
日更嵌入式的打工仔1 天前
单片机基础知识:内狗外狗/软狗硬狗
笔记·单片机
v先v关v住v获v取1 天前
12米折叠式高空作业车工作臂设计9张cad+三维图+设计说明书
科技·单片机·51单片机