你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

查看: 14728|回复: 28

[STM32L476] 【NUCLEO-L476RG开发】LPUART唤醒停止模式STOP Mode 2

  [复制链接]

33

主题

1243

回帖

0

蝴蝶豆

论坛元老

最后登录
2019-3-9
发表于 2015-11-8 14:49:20 | 显示全部楼层 |阅读模式
本帖最后由 风子 于 2015-11-8 16:16 编辑

LPUART 即 LOW POWER UART,是STM32L4系列专为低功耗设计的低功耗外设之一,既然玩低功耗的板子,当然不能少了捣鼓低功耗功能,这次就玩玩LPUART。
同时,在上一篇帖子【NUCLEO-L476RG LL库开发】STM32【LL库】开发使用指南中初步介绍了 STM32 LL库以及它的独立使用方法,这个帖子顺便演示一下可能是更通用(实用)的使用方法:LL库和HAL库混合使用。毕竟HAL库使用CUBEMX,非常方便,而独立使用LL库还需要自己建立工程,况且LL库本来就是和HAL库集成在一起的,相互配合,优势互补,最大限度的兼顾用户编程使用方便和MCU性能功耗,我想这才是ST设计这个库的初衷。不过这不是这个帖子的重点,不讲,只在代码中演示。
实验目的是测试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反过来连接,如图

QQ截图20151108134437.png

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

QQ截图20151108134929.png

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

QQ截图20151108135045.png

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

QQ截图20151108135103.png

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

QQ截图20151108135124.png

打开LPUART的中断。
配置好后就可以直接生成工程了,我使用的是MDK5.16a,生成MDKv5工程。
2.2,重定向printf到串口LPUART1
printf函数非常方便,所以用它来输出调试信息,打开上一步生成的工程,在合适的地方加入代码:

  1. #ifdef  __GNUC__
  2. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
  3. #else
  4. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
  5. #endif
  6. PUTCHAR_PROTOTYPE
  7. {
  8. HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);
  9. return ch;
  10. }
复制代码
  1. //main中
  2.         printf("This is a test!\n");
复制代码

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

QQ截图20151108141120.png

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

  1. void HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef  *RCC_ClkInitStruct, uint32_t *pFLatency)
复制代码

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

QQ截图20151108141959.png

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

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

  1.   LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
  2.   LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_MSI);
复制代码

3.2开中断,在HAL_UART_MspInit中加入代码:

  1.   /* USER CODE BEGIN LPUART1_MspInit 1 */
  2. LL_LPUART_SetWKUPType(LPUART1, LL_LPUART_WAKEUP_ON_RXNE);//设置唤醒方式为RXNE
  3. LL_LPUART_EnableIT_RXNE(LPUART1);//打开RXNE中断
  4. LL_LPUART_EnableIT_WKUP(LPUART1);//打开wakeup中断

  5. /* USER CODE END LPUART1_MspInit 1 */
复制代码

3.3检查LPUART的一些状态位,这个我就直接复制了例程中的一个函数,稍加修改

  1. __STATIC_INLINE void PrepareLPUARTToStopMode(void)
  2. {
  3.   /* Empty RX Fifo before entering Stop Mode 2 (Otherwise, characters already present in FIFO
  4.      will lead to immediate wake up */
  5.   while (LL_LPUART_IsActiveFlag_RXNE(LPUART1))
  6.   {
  7.     /* Read Received character. RXNE flag is cleared by reading of RDR register */
  8.     ubReceivedChar=LL_LPUART_ReceiveData8(LPUART1);
  9.   }

  10.   /* Clear OVERRUN flag */
  11.   LL_LPUART_ClearFlag_ORE(LPUART1);

  12.   /* Make sure that no LPUART transfer is on-going */
  13.   while(LL_LPUART_IsActiveFlag_BUSY(LPUART1) == 1)
  14.   {
  15.   }
  16.   /* Make sure that LPUART is ready to receive */   
  17.   while(LL_LPUART_IsActiveFlag_REACK(LPUART1) == 0)
  18.   {
  19.   }

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

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

  26.   /* Enable Wake Up From Stop */
  27.   LL_LPUART_EnableInStopMode(LPUART1);
  28. }
复制代码

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

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

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

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

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

  1. PrepareLPUARTToStopMode();

  2.   HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
复制代码

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


剩下的更新在一楼,完整工程见附件:

STM32L476_HAL LL_LPUART.rar (2.88 MB, 下载次数: 619)

评分

参与人数 1ST金币 +49 收起 理由
沐紫 + 49 赞一个!

查看全部评分

<
回复

使用道具 举报

33

主题

1243

回帖

0

蝴蝶豆

论坛元老

最后登录
2019-3-9
 楼主| 发表于 2015-11-8 14:49:41 | 显示全部楼层
本帖最后由 风子 于 2015-11-8 15:31 编辑

继续更新:
为方便观察,进入停止模式之前先让LED闪烁3秒钟,同时输出一些信息。接着写中断函数


  1. void LPUART1_IRQHandler(void)
  2. {
  3.   /* USER CODE BEGIN LPUART1_IRQn 0 */
  4.   if(LL_LPUART_IsActiveFlag_WKUP(LPUART1) && LL_LPUART_IsEnabledIT_WKUP(LPUART1))
  5.   {
  6.     /* Configure LPUART1 transfer interrupts : */
  7.     /* Disable the UART Wake UP from stop mode Interrupt */
  8.     LL_LPUART_DisableIT_WKUP(LPUART1);

  9.     /* WUF flag clearing */
  10.     LL_LPUART_ClearFlag_WKUP(LPUART1);
  11.         
  12.     ubReceivedChar=LL_LPUART_ReceiveData8(LPUART1);
  13.   }

  14.   /* USER CODE END LPUART1_IRQn 0 */
  15.   HAL_UART_IRQHandler(&hlpuart1);
  16.   /* USER CODE BEGIN LPUART1_IRQn 1 */

  17.   /* USER CODE END LPUART1_IRQn 1 */
  18. }
复制代码

当有中断发生,先检查中断源是不是WKUP中断,并且是否使能该中断,如果不是,则忽略掉。



      检查确定是WKUP中断,则关闭WKUP中断,清除相应标志位,避免重复进中断,最后将接收到的数据读出来存放,以便后用。
中断结束,MCU已经被唤醒,会回到进入停止模式的地方继续执行后面的代码,后面也不用做什么事,就是把收到的字符发送回串口助手,这样我们就可以知道MCU已经成功被唤醒了,当然,唤醒后直接把LED打开,观察更方便代码也更简单。同时发送系统时钟的信息和进入停止模式之前的信息做个比较,








QQ截图20151108151534.png

可以清楚的看到,我们发送到MCU的字符'a'成功发送回来,进入停止模式前系统时钟是PLL,而唤醒之后变成了MSI,如果要继续使用PLL,需要重新配置使能,如果不影响其他地方,可以简单的再调用一次cube生成的时钟配置函数:


  1. printf("System clock reconfiguration\n\r");
  2.         SystemClock_Config();
  3.   displayclkinfo();
复制代码
QQ截图20151108153625.png

最后,把唤醒后的时钟改为HSI,测试一下效果:


  1. LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI);
复制代码
QQ截图20151108153258.png

此时唤醒后系统时钟就是HSI。


回复 支持 反对

使用道具 举报

33

主题

1243

回帖

0

蝴蝶豆

论坛元老

最后登录
2019-3-9
 楼主| 发表于 2015-11-8 14:50:00 | 显示全部楼层
再占板凳
回复 支持 反对

使用道具 举报

1

主题

233

回帖

0

蝴蝶豆

中级会员

最后登录
2019-1-4
发表于 2015-11-8 15:36:28 | 显示全部楼层
还行吧。挺好的。我都不知道该如何表达了
回复 支持 反对

使用道具 举报

33

主题

1243

回帖

0

蝴蝶豆

论坛元老

最后登录
2019-3-9
 楼主| 发表于 2015-11-8 15:39:07 | 显示全部楼层
aabird 发表于 2015-11-8 15:36
还行吧。挺好的。我都不知道该如何表达了

呵呵
回复 支持 反对

使用道具 举报

41

主题

2476

回帖

282

蝴蝶豆

论坛元老

最后登录
2020-12-8
发表于 2015-11-8 17:35:06 | 显示全部楼层
很详细,谢谢分享
回复 支持 反对

使用道具 举报

47

主题

3404

回帖

30

蝴蝶豆

版主

最后登录
2020-12-7
发表于 2015-11-8 19:05:46 | 显示全部楼层
多谢分享。。。
回复 支持 反对

使用道具 举报

3

主题

102

回帖

0

蝴蝶豆

中级会员

最后登录
1970-1-1
发表于 2015-11-8 20:30:57 | 显示全部楼层
帮顶              
回复 支持 反对

使用道具 举报

4

主题

379

回帖

0

蝴蝶豆

金牌会员

最后登录
2019-11-19
发表于 2015-11-8 22:57:18 | 显示全部楼层
写的很详细
回复 支持 反对

使用道具 举报

33

主题

1243

回帖

0

蝴蝶豆

论坛元老

最后登录
2019-3-9
 楼主| 发表于 2015-11-9 08:58:30 | 显示全部楼层

谢谢支持
回复 支持 反对

使用道具 举报

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版