LPUART在Stop模式下必须通过硬件唤醒事件(如起始位检测)触发唤醒,不能依赖普通接收中断;WUS[1:0]需显式配置为0b10等有效值,且APB1时钟、RX引脚模式、SysTick及唤醒后时钟恢复顺序均须严格满足硬件约束。

LPUART在Stop模式下无法靠普通接收中断唤醒,必须用硬件级唤醒事件。HAL_UART_Receive_IT这类标准UART收发接口对LPUART完全无效——它不走NVIC中断线,而是触发系统级唤醒信号,进入Stop前就得把唤醒逻辑“焊死”在寄存器里。
WUS寄存器必须显式配置,不能依赖CubeMX默认值
LPUART_CR3.WUS[1:0] 决定唤醒条件,CubeMX生成的代码常把它设为 0b00(地址匹配),但若没同时启用Mute模式(LPUART_CR1.MME=1)或没写入LPUART_CR2.ADD,唤醒就永远不触发。实际工程中更常用的是 0b10(起始位检测),它不依赖数据内容,接线一有电平跳变就能拉醒MCU。
- 用 HAL 库时,必须手动改写
LPUART->CR3 |= LPUART_CR3_WUS_1;(即 WUS=0b10) - 如果选 0b11(RXNE非空),得确保
LPUART->CR1.RE = 1且 MME=0,否则接收器被静默,数据进不来 - 0b01 是保留值,写进去会导致唤醒行为不可预测,某些H7芯片会直接锁死LPUART
进入STOP前必须关掉所有无关外设时钟,尤其LPUART的APB时钟不能关
很多人卡在“能休眠但唤不醒”,查半天发现是 RCC->APB1ENR1.LPUART1EN 被误清零了。LPUART在Stop模式下仍需APB1总线供电和时钟门控通路,否则寄存器失能,唤醒逻辑根本跑不起来。
- 调用
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI)前,只保留RCC_APB1ENR1_LPUART1EN和RCC_APB1ENR1_PWREN - GPIO时钟可以关,但PA9/PA10引脚必须保持模拟输入(
GPIO_MODE_ANALOG)或浮空输入(GPIO_MODE_INPUT),上拉/下拉会抬高静态电流 - 别忘了关掉SysTick——
HAL_SuspendTick()不是可选项,是硬性要求;否则唤醒后Tick中断可能在时钟未稳时就炸出来
唤醒后第一件事不是读数据,而是等内核时钟恢复稳定
LPUART靠LSE(32.768kHz)运行,但CPU醒来要切回HSI或HSE,这个切换过程有几十微秒延迟。如果唤醒中断服务程序(HAL_LPUART_IRQHandler)里立刻调用 HAL_LPUART_Receive(),大概率读到空或乱码——因为RDR寄存器虽有数据,但APB时钟还没同步好。
立即学习“C++免费学习笔记(深入)”;
- 推荐做法:在
HAL_PWR_WAKEUP_CB_ID1回调里只做最简操作,比如置标志位、清中断标志LPUART_ICR_WUCF,然后退出 - 主循环检测到唤醒标志后,再调用
HAL_RCC_OscConfig()切换时钟,等HAL_RCC_GetOscConfig()返回稳定状态,最后才去读LPUART->RDR - 实测发现,H7系列从STOP2唤醒到HSI就绪平均耗时42μs,这期间任何外设访问都可能触发BusFault
最容易被忽略的是LPUART RX引脚的物理层可靠性:PCB上没加TVS或走线过长,会导致起始位下降沿畸变,WUS=0b10识别失败;而软件侧又没做唤醒失败重试机制,整机就卡在“半睡半醒”状态,电流停在几百微安不动——既不算真休眠,也干不了活。


















