[STM32U0] 【STM32U083测评】尝试LPUART的唤醒功能

[复制链接]
4375|6
 楼主| xhackerustc 发表于 2024-5-26 23:46 | 显示全部楼层 |阅读模式
阅读stm32u083的手册得知进入stop2低功耗模式后,uart是不能唤醒MCU的,只有LPUART具有此功能。 故而如果需要利用uart唤醒stop2模式下的mcu,只能使用LPUART。LPUART的时钟源可以是PCLK1, SYSCLK, HSI或LSE。进入stop2模式后,PCLK1和SYSCLK是关闭的,其实HSI时钟也是关闭的,但是手册里这么句话:“ Some peripherals with wake-up capability I2C3 and LPUART) can switch on the HSI16 to receive a frame, and switch off the HSI16 after receiving the frame if it is not a wake-up frame. In this case the HSI16 clock is propagated only to the peripheral requesting it”,所以像LPUART唤醒开启后,一旦有数据硬件上会临时打开HSI16,收完数据后自动关闭HSI16。这个功能非常有用,因为LSE频率32768HZ,LPUART如果用LSE做时钟源波特率上限比较低,如果又需要LPUART唤醒功能,又需要高波特率,HSI16为时钟源是唯一的路径

程序设计要点
选PA2/PA3针脚做LPUART TX/RX
阅读原理图后发现,STLINK的VCP TX/RX是接在PA2/PA3针脚,巧合的是PA2/PA3可以复用为LPUART的TX 与RX功能,这样测试比较方便不用另外接任何uart转接。
  1. __HAL_RCC_GPIOA_CLK_ENABLE();
  2.     /**LPUART1 GPIO Configuration
  3.     PA3     ------> LPUART1_RX
  4.     PA2     ------> LPUART1_TX
  5.     */
  6.     GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
  7.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  8.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  9.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  10.     GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
  11.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

SystemClock_Config里开启HSI
  1. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  2.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;

HAL_UART_MspInit()里为LPUART选HSI为时钟源
  1.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;
  2.     PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_HSI;
  3.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  4.     {
  5.       Error_Handler();
  6.     }


进入stop2模式前,LPUART唤醒的设置
这有固定套路,参阅样例代码比较合适,注释也比较清晰,这里不多费口舌
  1.   /* make sure that no LPUART transfer is on-going */
  2.   while (__HAL_UART_GET_FLAG(&hlpuart1, USART_ISR_BUSY) == SET);
  3.   /* make sure that LPUART is ready to receive
  4.    * (test carried out again later in HAL_UARTEx_StopModeWakeUpSourceConfig) */
  5.   while (__HAL_UART_GET_FLAG(&hlpuart1, USART_ISR_REACK) == RESET);

  6.   /* set the wake-up event:
  7.    * specify wake-up on RXNE flag */
  8.   WakeUpSelection.WakeUpEvent = UART_WAKEUP_ON_READDATA_NONEMPTY;
  9.   if (HAL_UARTEx_StopModeWakeUpSourceConfig(&hlpuart1, WakeUpSelection) != HAL_OK)
  10.   {
  11.     Error_Handler();
  12.   }

  13.   /* Enable the UART Wake UP from STOP mode Interrupt */
  14.   __HAL_UART_ENABLE_IT(&hlpuart1, UART_IT_WUF);


进入stop2模式与唤醒
  1.   /* enable MCU wake-up by LPUART */
  2.   HAL_UARTEx_EnableStopMode(&hlpuart1);
  3.   HAL_SuspendTick();
  4.   /* enter STOP2 mode */
  5.   HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);

  6.   /* ... STOP2 mode ... */

  7. /* at that point, MCU has been awoken: LED4 has been turned back on */
  8.   SystemClock_Config();

  9.   /* Wake Up based on RXNE flag successful */
  10.   HAL_UARTEx_DisableStopMode(&hlpuart1);

这里也是固定代码套路:进入stop模式前,调用HAL_UARTEx_EnableStopMode()使能LPUART唤醒,醒来后配置下时钟,以及调用HAL_UARTEx_DisableStopMode()关闭LPUART唤醒功能。要注意的是HAL_SuspendTick(),笔者测试如果没这行代码,MCU会立即被唤醒,估计是还未进入stop2模式,tick中断来了。

测试结果
进入stop2模式后,minicom下按任意键会成功唤醒MCU,并有期望的信息打印


 楼主| xhackerustc 发表于 2024-6-2 18:08 | 显示全部楼层
丙丁先生 发表于 2024-6-2 12:56
为什么在进入Stop2模式之前需要调用HAL_SuspendTick(),而在唤醒后不需要重新启动Tick中断? ...

进入stop2前要suspend tick的原因在这个帖子里探讨过https://bbs.21ic.com/icview-3378748-1-1.html

休眠回来后SystemClock_Config()里有开启tick的代码路径
xuanhuanzi 发表于 2024-6-9 18:33 | 显示全部楼层
唤醒的原理是什么,是有串口发来消息就唤醒吗?
laocuo1142 发表于 2024-6-12 08:06 | 显示全部楼层
听说这个U系列功耗超级低,0.XuA级别,功能和L系列有区别吗?
Stahan 发表于 2024-6-30 10:31 | 显示全部楼层
这个通信距离是多远啊?
rzjvv 发表于 2024-8-31 17:40 | 显示全部楼层
在 STM32U0 系列的 STOP2 低功耗模式下,许多外设的时钟都会被关闭,以减少功耗。
而服务器人 发表于 2024-9-30 03:14 | 显示全部楼层
LPUART如果用LSE做时钟源波特率上限比较低,如果又需要LPUART唤醒功能,又需要高波特率,HSI16为时钟源是唯一的路径
您需要登录后才可以回帖 登录 | 注册

本版积分规则

42

主题

166

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部