STM32低功耗应用

说起低功耗的单片机第一个想起来的肯定是MSP430系列单片机,它以极地的功耗和较强的性能占领了低功耗控制、应用领域。但是我不会MSP430单片机,其实也没什么会不会,学学都能用,只是嫌MSP430的开发环境和调试方式和ARM的不一样,嫌麻烦就没有使用过MSP430,用的比较多的单片机还是STM32系列的单片机,虽然是ARM内核,但是由于不能跑Linux系统,还是将其划归为单片机,无所谓,不是所有的应用场合都需要Linux这么庞大的系统,例如在低功耗的应用领域Linux就不太适合了,这时候单片机就比较合适。STM32很流行,所以总结一下使用STM32进行低功耗应用开发。
低功耗设计一般是使用在在电池供电的系统中,例如一个3.7V 1000mah的电池供电的系统,在不使用低功耗模式的情况下平均工作电流大约在25ma左右(不包括外围电路耗电),大致计算这个系统充满电可以用的时间:
T1 = 1000 / 25 = 40H
可以使用40个小时,这个对于手机待机来说还能接受,但是有时候应用要求系统充一次电或者换一次电池能够使用个把月或者好几年。这时候肯定需要低功耗模式,例如我们将系统的平均工作电流限制在uA级别的话,例如25uA,这样计算系统可以持续工作的时间为:
T2 = 1000 / 25uA = 40000H = 1667天
显然这个是一个十分可观的待机时间。但是一般系统还有其他外围电路耗电以及反复充电之后的电池不能保证一定是有1000mAh的电量。所以低功耗应用不仅和软件有关,和硬件电路设计也有很大的关系。
下面详细说一下STM32进入低功耗模式的基于库函数的程序设计方法。
1、第一步将所有没用的时钟都关闭,关闭JTAG/SWD调试功能,原因很简单,开一个时钟就会多消耗一点电能,使用下面三个函数进行时钟的关断控制:
RCC_AHBPeriphClockCmd
RCC_APB2PeriphClockCmd
RCC_APB1PeriphClockCmd

2、第二步将所有引脚都设置成高阻态,这一步的设置很重要,如果设置成输出状态进入低功耗后引脚可能会和外围电路有电流,如果设置成浮空输入也可能和外界环境有漏电流,这点很明显,将手碰在引脚上就会导致电流浮动,而且浮动还很大。

3、进入低功耗模式。STM32有3种低功耗模式,Sleep、Stop和Stand By模式,具体每种模式可以查看数据手册上的说明。其中Stand By模式是最省电的模式,功耗能够在10uA以下,但是进入Stand By模式之后只能通过WAKE-UP引脚的上升沿、Reset引脚低电平信号、IWatch Dog、RTC事件唤醒,不能使用外部中断唤醒,并且Stand By模式下内存和寄存器的数据都丢失了。其他两种模式的功耗相对Stand By模式较高,但是可以使用很多种唤醒方式唤醒CPU并且内存和寄存器的数据能够保存住。进入Stand By模式低功耗模式的函数为:
PWR_EnterSTANDBYMode();
需要注意的是进图Stand By模式之后JTAG/SWD不能直接下载,需要在执行下载之后进行按键复位才能下载,另外一点很奇怪的现象是下载完程序之后系统功耗并不会降低到理想值,必须断开电源再上电之后系统电流才能到uA级别,注意是断电再上电,复位都不可以,我猜测是由于使用JTAG/SWD下载完程序之后内部的仿真调试模块一直再工作,断电上电后才能保证JTAG/SWD调试模块停止工作。

4、从低功耗模式唤醒,这里只以Stand By模式为例,其他模式的唤醒很简单。Stand By模式下可以使用WAKE-UP引脚唤醒,Stand By引脚与PA0引脚复用,使能WAKE-UP唤醒功能需要设置Power Control的CSR寄存器的第8位,或者调用PWR_WakeUpPinCmd函数传参Enable。除了WAKE-UP引脚外还能使用IWDG唤醒,IWDG的详情参看数据手册,示例程序如下:

IWDG_Enable();
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_256);
IWDG_SetReload(156 * WORK_CYCLE);
IWDG_ReloadCounter();

首先是使能IWDG,第二步向IWDG的KR寄存器中写入IWDG_WriteAccess_Enable(0x5555),第三步设置IWDG的分频系数,第四步设置Reload值,最后重新状态计数寄存器。

经过测试,进入tand By模式之后单片机耗电可以降低到10uA的级别,注意要断电上电一次并且将JTAG/SWD断开进行电流测量,不然会有漏电。如果将所有杜邦线都断开可能再降低一些电流。

上一篇:Struts2 + Spring + Hibernate


下一篇:JS中的try..catch