SimonLuk 发表于 2018-3-1 18:30:42

STM32L4R5 Nucleo低功耗例程测试验证

本帖最后由 ahuaahua 于 2018-3-1 18:38 编辑

有幸在年初的答题中,获得Nucleo STM32L4R5ZI板一块。正所谓吃别人的嘴软,免费拿人家的……必须要发个评测弘扬一下ST大法好~~~但是板子寄到手时已接近春节,年后回来放浪至今才有时间拿出来玩,不知道还能不能参加评测奖励?
L4 Plus主打图形、低功耗,以及高主频、大Flash、和帅气的Ram,还有加密等等一系列特性(具体见手册),由于时间关系,本次先对最重要的低功耗特性进行验证。
1、原理验证            根据Nucleo 144的原理图,MCU主要由两个地方提供电源:VDD和VDD_MCU。其中,VDD提供给IO、模拟、USB等部分。VDD_MCU则提供给VBAT,并通过SB167选择提供给模拟部分。详见下图:1.1VDD来源:经过JP6选择电源后,由U6降压为3.3V,经VDD提供给MCU。VDD前的JP5(IDD),即为板子提供的电流测试点。详见下图:1.2VDD_MCU来源:            由下图可知,VDD_MCU由VDD产生,产生的方式根据Nucleo板子是否带有SMPS功能(就是外部的开关电源)决定。本次到手的板子,是不带这个功能的,保持原样即可。如果有同学收到带“-P”版本的板子,需要注意这个问题,必要时修改对应的连接。


1.3由以上原理分析可知:            只要在JP5跳线帽上测试电流,就可以大概知道MCU的功耗情况。为什么要说大概?因为还有一个器件也使用VDD_MCU,它就是U14:            追求极致的同学们可以详细查SN74LVC2T45的资料,在此我就不累赘了。



2测试方法

2.1必须再歌颂一次ST大法好在STM32CubeL4库里,已经有对应的低功耗Example例程,直接编译下载到板子上即可测试。            在用户的目录下,STM32Cube\Repository\STM32Cube_FW_L4_V1.11.0\Projects\NUCLEO-L4R5ZI\Examples\PWR\PWR_ModesSelection里,可以找到一个关于这个工程的readme.txt的文件:- PWR/PWR_ModesSelection/Inc/stm32l4xx_conf.h         HAL Configuration file
- PWR/PWR_ModesSelection/Inc/stm32l4xx_it.h         Header for stm32l4xx_it.c
- PWR/PWR_ModesSelection/Inc/main.h                   Header file for main.c
- PWR/PWR_ModesSelection/Src/system_stm32l4xx.c       STM32L4xx system clock configuration file
- PWR/PWR_ModesSelection/Src/stm32l4xx_it.c         Interrupt handlers
- PWR/PWR_ModesSelection/Src/main.c                   Main program
- PWR/PWR_ModesSelection/Src/lprun_test.c             Low Power RUN mode test
- PWR/PWR_ModesSelection/Src/lpsleep_test.c         Low Power SLEEP mode test
- PWR/PWR_ModesSelection/Src/run_range1_test.c      RUN mode in range 1 test
- PWR/PWR_ModesSelection/Src/run_range2_test.c      RUN mode in range 2 test
- PWR/PWR_ModesSelection/Src/shutdown_test.c          SHUTDOWN mode test
- PWR/PWR_ModesSelection/Src/sleep_range1_test.c      SLEEP mode in range 1 test
- PWR/PWR_ModesSelection/Src/sleep_range2_test.c      SLEEP mode in range 2 test
- PWR/PWR_ModesSelection/Src/standby_rtc_sram2_test.c STANDBY mode with RTC and SRAM2 preserved test
- PWR/PWR_ModesSelection/Src/standby_rtc_test.c       STANDBY mode with RTC test
- PWR/PWR_ModesSelection/Src/standby_test.c         STANDBY mode test
- PWR/PWR_ModesSelection/Src/stop1_mroff_rtc_test.c   STOP1 mode with RTC but Regulator OFF test
- PWR/PWR_ModesSelection/Src/stop1_mroff_test.c       STOP1 mode with Regulator OFFtest
- PWR/PWR_ModesSelection/Src/stop2_rtc_test.c         STOP2 mode with RTC test
- PWR/PWR_ModesSelection/Src/stop2_test.c             STOP2 mode test

2.2简单抽其中几个,看看这些模式究竟做了什么:void test_lprun_2mhz(void)
{
printf("\n\r Executing test (LPRUN 2MHz - with FLASH ART ON) \n\r");
printf(" Please measure current then use Reset button to select another test \n\r");

/* Set all GPIO in analog state to reduce power consumption */
GPIO_AnalogState_Config();

/* Set the System clock to 2 MHz (MSI) */
SystemClock_2MHz();

/* Suspend Tick increment to prevent wakeup by Systick interrupt.         */
/* Otherwise the Systick interrupt will wake up the device within 1ms   */
/* (HAL time base).                                                       */
HAL_SuspendTick();

#ifdef USE_STM32L4XX_NUCLEO
/* Disable USART2 clock */
__HAL_RCC_USART2_CLK_DISABLE();
#elif USE_STM32L4XX_NUCLEO_144
/* Disable LPUART1 clock */
__HAL_RCC_LPUART1_CLK_DISABLE();
#endif

/* Enable Power Clock */
__HAL_RCC_PWR_CLK_ENABLE();

/* Enter LP RUN mode */
HAL_PWREx_EnableLowPowerRunMode();

/* Disable Power Clock */
__HAL_RCC_PWR_CLK_DISABLE();

while1Aligned64();

}
很简单的几步:1、把IO口都设为模拟;2、更改时钟;3、停掉Systick和串口;4、打开电源时钟;5、使能一下LP RUN;6、关闭电源时钟;7、死循环。
void test_run_range1_80mhz(void)
{
printf("\n\r Executing test (RUN Range 1, 80MHz - with FLASH ART ON) \n\r");
printf(" Please measure current then use Reset button to select another test \n\r");

/* Set all GPIO in analog state to reduce power consumption */
GPIO_AnalogState_Config();

#ifdef USE_STM32L4XX_NUCLEO
/* Disable USART2 clock */
__HAL_RCC_USART2_CLK_DISABLE();
#elif USE_STM32L4XX_NUCLEO_144
/* Disable LPUART1 clock */
__HAL_RCC_LPUART1_CLK_DISABLE();
#endif

/* Set System clock to 80 MHz (MSI) */
SystemClock_80MHz();

/* Suspend Tick increment to prevent wakeup by Systick interrupt.         */
/* Otherwise the Systick interrupt will wake up the device within 1ms   */
/* (HAL time base).                                                       */
HAL_SuspendTick();

while1Aligned64();

}
更为简单的几步:1、把IO口都设为模拟;2、关掉串口;3、更改时钟;4、停掉Systick;5、死循环。
void test_stop2(void)
{
printf("\n\r Executing test (STOP2) \n\r");
printf(" Please measure current then use Reset button to select another test \n\r");

/* Set all GPIO in analog state to reduce power consumption */
GPIO_AnalogState_Config();

/* Enable Power Clock */
__HAL_RCC_PWR_CLK_ENABLE();

/* Enter STOP 2 mode */
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);

}还可以更简单的几步:1、把IO口都设为模拟;2、关掉电源时钟;3,发一个WFI指令。



2.4 这里需要补充啰嗦几句:2.4.1、把IO设为模拟,这只是在测试中,排除外部干扰,使测试数据“单纯”一些的使用方法。实际产品一般不会这么用,因为这样会降低产品的抗干扰能力,比如EMI。2.4.2、这里的测试,都没有使用外部HSE时钟,全部使用MSI(RC振荡产生)。在实际产品中,不使用外部晶振的情况比较少,而外部晶振所需要的电流,对测试的影响还是较大的。2.4.3、由于Nucleo板的设置,VBAT是直连VDD_MCU和VDD的,所以测试并不能完全反映MCU在VDD断开,且VBAT在电池供电下的情况。


3、测试            既然方法都知道了,撸起袖子动手干吧。由于财力有限(求土豪赞助,求高大上的老板收留),拿出手的只有一个比对过、精度相对较好的4位半万用表,结果如下:
No.Desc.Curr. (mA)
0SHUTDOWN0.0000-0.0001
1STANDBY0.0001-0.0002
2STANDBY+ RTC0.0007
3STANDBY+ RTC + SRAM20.0012
4STOP20.0027
5STOP2   + RTC0.0033
6STOP1   + MR OFF0.0727
7STOP1   + MR OFF + RTC0.0731
8LPSLEEP2MHz - FLASH OFF0.171
9LPRUN   2MHz - with FLASH ART ON0.517
10SLEEPRange 2, 24MHz - with FLASH ART ON0.852
11SLEEPRange 1, 80MHz - with FLASH ART ON2.803
12RUN   Range 2, 24MHz - with FLASH ART ON2.920
13RUN   Range 1, 80MHz - with FLASH ART ON11.249


3.1测试结果的看法:3.1.1、在STANDBY状态中,反正都停下来了,能不用SRAM就别用,功耗增加近1倍,尽量用备份域保存数据。3.1.2、STOP1和STOP2的功耗区别是明显的。3.1.3、如果要RUN,且没什么性能要求,LP RUN是很好的选择。但是要注意外设的处理。3.1.4、仪表所限,电流较低的几个测试已接近仪表的极限和误差,仅作参考。


3.2题不是白答的,板子不是白拿的,测试不是白做的。清楚记得,L4R5是可以跑120MHz的,这个测试只是跑到了80MHz(也就是前任L4的速度,不知是故意为之,还是忘了修改),还没显示出这个测试中MCU,最高主频的状态。
重要的事情要说第三遍了:ST大法真的好!修改时钟这种事,小手一抖,简单得不得了!

3.2.1打开最新的CubeMX,选择NucleoL4R5ZI板子,Do NOT初始化默认外设设置(因为会打开很多功能),直接进去,看时钟配置:3.2.2选择时钟源为MSI,PLLCLK,在HCLK输入120,然后就自动算出PLLM1的N为60,R为2。然后生成代码。


3.2.3 为了偷懒,直接修改测试13。对比一下生成的代码以及测试13的代码:

CubeMX生成的代码:RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = 0;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
RCC_OscInitStruct.PLL.PLLN = 60;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;

测试13的代码:RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; //这个宏的值是0
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 40;
RCC_OscInitStruct.PLL.PLLR = 2;

由此可见,直接把测试13的RCC_OscInitStruct.PLL.PLLN,改成60即可。
修改代码后,再跑一次测试,结果是:

No.Desc.Curr. (mA)
14RUN   Range 1, 120MHz - with FLASH ART ON16.61

好了,测试到此就结束了。按照测试的结果计算,3.3V的电源下,MCU在全速的时候功率约为55mW,还是相当不错滴。

最后,尽管是ST大法好,还是要吐槽一下:CubeMX的功率估算,L4R5的数据还没更新(只能到80MHz)。作为当前主推的产品,请注意细节~
感谢观看,请丢给我小红花。



zero99 发表于 2018-3-2 09:32:52

不错的文章,学习下 :o:o,已汇总到
https://www.stmcu.org.cn/module/forum/thread-614299-1-1.html

接下来也会汇总到3月的技术原创中~

sky_han 发表于 2019-4-1 17:38:05

使用内部MSI測試功耗,参考意义不大,因为实际项目会使用外部晶振,外部晶振开启会增加0.4ma功耗
页: [1]
查看完整版本: STM32L4R5 Nucleo低功耗例程测试验证