打印
[STM32F4]

LPUART唤醒停止模式STOP Mode 2

[复制链接]
5853|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Micachl|  楼主 | 2016-3-20 21:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
实验目的是测试LPUART的唤醒Stop mode 2功能,要做的工作如下:
1.硬件,nucleo的虚拟串口默认接的是USART2,要使用LPUART,需要重新接线
2.软件,配置好LPUART,并且重定向printf函数,便于输出需要的信息
3.配置进入Stop mode 2的准备工作
4.进入Stop mode 2
5.使用LPUART唤醒MCU
6.输出一些过程中观察需要的调试信息
大概就有这么些内容,这个实验是参考了STM32L4Cube里面的一个例子,由于水平有限,这也只是个人实验笔记,可能有些地方写得不好,大家自己去看官方库里面的例程,位于STM32Cube_FW_L4_V1.1.0\Projects\STM32L476RG-Nucleo\Examples_LL\LPUART\LPUART_WakeUpFromStop2文件夹中。下面是具体操作:
1.板载ST-LINK有虚拟串口功能,并且引出了TX,RX引脚,只需要把他们和LPUART1的RX,TX引脚连起来即可,注意板子上的TX,RX是针对ST-LINK端说的,所以连接时和LPUART的TX,RX反过来连接,如图

注意RX,TX上连了其他USART的时候千万不要同时使用USART2,本来使用其他串口的时候应该断开板子上SB13,SB14,闲麻烦就不断开了,别使用USART2就好。
2.1配置LPUART1,这个使用Cubemx来完成,比较简单


打开LPUART1,配置PC0,PC1为LPUART1_RX,LPUART1_TX,打开RCC 外部低速时钟LSE


系统时钟选HSI经PLL倍频,80M,LPUART时钟选择LSE,这里不能使用PCLK,因为进入stop mode 2后PLL,系统时钟会被关闭,相应外设不能工作,所以此处只能选择HSI或者LSE,如果用HSI,上一步可以不必打开LSE。


LPUART1参数:波特率9600,使用LSE时钟波特率最高只能9600,其他默认。


打开LPUART的中断。
配置好后就可以直接生成工程了,我使用的是MDK5.16a,生成MDKv5工程。
沙发
Micachl|  楼主 | 2016-3-20 21:48 | 只看该作者
2.2,重定向printf到串口LPUART1
printf函数非常方便,所以用它来输出调试信息,打开上一步生成的工程,在合适的地方加入代码:
#ifdef  __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
//main中
        printf("This is a test!\n");

最后一句是放在主函数中,用来测试下printf函数能不能正常输出信息


看起来一切正常,可以下一步了。
2.3先来输出一些信息,供后面比较,输出系统时钟信息:
在前面配置中,我们使用了PLL倍频,得到80M的系统时钟,而在进入stop mode 2后PLL会被关闭,重新唤醒之后只能使用HSI或者MSI作为系统时钟,PLL需要重新使能才能使用,就像系统刚复位的时候一样,所以进入停止模式之前,应该先设置好唤醒之后的系统时钟,这是准备工作之一,
下面的函数用于获取当前系统时钟设置:

void HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef  *RCC_ClkInitStruct, uint32_t *pFLatency)


使用特权

评论回复
板凳
Micachl|  楼主 | 2016-3-20 21:50 | 只看该作者

获得时钟信息后用printf函数输出:




现在的时钟是PLL,和之前的配置相符。
3.进入停止模式2之前准备工作
为了使MCU能正常进入停止模式,且能正常被唤醒,有些工作必须做好,不然就睡死过去醒不来了。

3.1打开PWR时钟,设置系统唤醒后时钟为MSI

  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
  LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_MSI);
3.2开中断,在HAL_UART_MspInit中加入代码:
  /* USER CODE BEGIN LPUART1_MspInit 1 */
LL_LPUART_SetWKUPType(LPUART1, LL_LPUART_WAKEUP_ON_RXNE);//设置唤醒方式为RXNE
LL_LPUART_EnableIT_RXNE(LPUART1);//打开RXNE中断
LL_LPUART_EnableIT_WKUP(LPUART1);//打开wakeup中断

/* USER CODE END LPUART1_MspInit 1 */
3.3检查LPUART的一些状态位,这个我就直接复制了例程中的一个函数,稍加修改
__STATIC_INLINE void PrepareLPUARTToStopMode(void)
{
  /* Empty RX Fifo before entering Stop Mode 2 (Otherwise, characters already present in FIFO
     will lead to immediate wake up */
  while (LL_LPUART_IsActiveFlag_RXNE(LPUART1))
  {
    /* Read Received character. RXNE flag is cleared by reading of RDR register */
    ubReceivedChar=LL_LPUART_ReceiveData8(LPUART1);
  }

  /* Clear OVERRUN flag */
  LL_LPUART_ClearFlag_ORE(LPUART1);

  /* Make sure that no LPUART transfer is on-going */
  while(LL_LPUART_IsActiveFlag_BUSY(LPUART1) == 1)
  {
  }
  /* Make sure that LPUART is ready to receive */   
  while(LL_LPUART_IsActiveFlag_REACK(LPUART1) == 0)
  {
  }

  /* About to enter stop mode: switch off LED */
  LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_5);

  /* Configure LPUART1 transfer interrupts : */
  /* Clear WUF flag and enable the UART Wake Up from stop mode Interrupt */
  LL_LPUART_ClearFlag_WKUP(LPUART1);
  LL_LPUART_EnableIT_WKUP(LPUART1);

  /* Enable Wake Up From Stop */
  LL_LPUART_EnableInStopMode(LPUART1);
}


使用特权

评论回复
地板
Micachl|  楼主 | 2016-3-20 21:51 | 只看该作者

分析一下这个函数都干了些什么(其实代码里有注释):

a.不断读取接收数据,知道RXNE为0,确保已经没有数据发进来

b.清除OVERRUN标志,确保所有当前工作完成,进入可以接收的状态

c.清除WUF标志位,开WKUP中断(上一步自己做了),使能wakeup功能

4.一切准备工作就绪,MCU可以进入停止模式了,

PrepareLPUARTToStopMode();

  HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
不过还有一个问题,还没写中断函数呢,MCU醒来后不知道干什么啊,人早上醒来知道洗脸刷牙,机器可不知道,所以得告诉它,写中断服务函数。

STM32L476_HAL LL_LPUART.rar

2.88 MB

使用特权

评论回复
5
情深浅潋| | 2020-1-2 16:57 | 只看该作者
学习啦

使用特权

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

本版积分规则

43

主题

300

帖子

1

粉丝