阅读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,并有期望的信息打印
|