打印
[STM32U0]

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

[复制链接]
2881|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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转接。
 __HAL_RCC_GPIOA_CLK_ENABLE();
    /**LPUART1 GPIO Configuration
    PA3     ------> LPUART1_RX
    PA2     ------> LPUART1_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

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

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


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

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

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


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

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

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

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

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

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


使用特权

评论回复
沙发
Stahan| | 2024-5-31 10:31 | 只看该作者
这个通信距离是多远啊?

使用特权

评论回复
板凳
丙丁先生| | 2024-6-2 12:56 | 只看该作者
为什么在进入Stop2模式之前需要调用HAL_SuspendTick(),而在唤醒后不需要重新启动Tick中断?

使用特权

评论回复
地板
丙丁先生| | 2024-6-2 12:57 | 只看该作者
低功耗模式的应用场景和优势是什么?

使用特权

评论回复
5
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的代码路径

使用特权

评论回复
6
xuanhuanzi| | 2024-6-9 18:33 | 只看该作者
唤醒的原理是什么,是有串口发来消息就唤醒吗?

使用特权

评论回复
7
laocuo1142| | 2024-6-12 08:06 | 只看该作者
听说这个U系列功耗超级低,0.XuA级别,功能和L系列有区别吗?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

53

帖子

0

粉丝