1、前言
上一节讲了Zigbee的睡眠定时器利用外部按键使系统从休眠态唤醒到工作态,其核心在于:
61 void SysPowerMode(uchar mode)
62 {
63 if(mode > 0 && mode < 4)
64 {
65 SLEEPCMD |= mode; //设置系统睡眠模式
66 PCON = 0x01; //进入睡眠模式 ,通过中断唤醒
67 }
68 else
69 PCON = 0x00; //主动/空闲模 通过中断唤醒系统
70 }
其中参数mode表示电源管理系统中的PM1、PM2、PM3、全功能模式,上节只对这几种模式做简单的介绍,本节将详细介绍电源管理部分,而后分析基于Zigbee休眠定时器实现的周期性休眠唤醒工程。
2、低功耗电源管理概述
一个具有低功耗运行的系统,其实现往往是利用在不同情况下切换为不同电源模式来实现的。各种运行模式指的是主动模式、空闲模式和供电模式1、2 和3(PM1-PM3)。而超低功耗一般通过关闭对模块的供电来减少静态功耗,以及使用门控时钟和关闭振荡器来降低动态功耗。
3、电源管理系统介绍
不同的操作模式或者供电模式使系统低功耗运行成为了可能,如果想追求超低功耗,可以通过关闭对模块的供电来减小静态功耗,或者使用时钟门控,以及关闭晶振来减少动态功耗。
active mode\idle mode\PM1\PM2\PM3被称为operating模式(power模式)。Active mode是正常运行模式,PM3模式拥有最低的功耗,他们的区别见下表:
Active mode: 全功能模式,稳压器的数字内核开启,要么16MHz的RC振荡器要开启、要么32MHz的晶体振荡器要开启、要么两者都开启;要么32kHz的RCOSC开启、要么32kHz的XOSC要开启。
Idle mode: 空闲模式-除了CPU内核停止运行之外,其他和active mode一样
PM1: The voltage regulator to the digital part is on. Neither the 32 MHz XOSC nor the 16 MHz RCOSC is running. Either the 32 kHz RCOSC or the 32 kHz XOSC is running. The system goes to active mode on reset, an external interrupt, or when the Sleep Timer expires.(处于PM1模式系统重新变为active mode要么reset,要么外部中断触发,要么Sleep timer溢出)
PM2: The voltage regulator to the digital core is turned off. Neither the 32 MHz XOSC nor the 16 MHz RCOSC is running. Either the 32 kHz RCOSC or the 32 kHz XOSC is running. The system goes to active mode on reset, an external interrupt, or when the Sleep Timer expires.
PM3: The voltage regulator to the digital core is turned off. None of the oscillators is running. The system goes to active mode on reset or an external interrupt.
POR在PM2/PM3模式下是Active的,但是BOD却是Power Down的,这给电源管理造成了限制。如果在PM2或者PM3模式下供电电压小于1.4V,温度高于70℃,并且然后重新进入主动模式之前,回到合适的运行电压,寄存器和RAM在PM2/PM3 下保存的内容可能会改变。Hence, care should be taken in the design of the system power supply to ensure that this does not occur. 因为如果电压低于大约1.7V 就触发一个BOD 复位,所以电压可以通过进入主动模式进行精确的定期监控。
3.1、主动和空闲模式
Active mode is the fully functional mode of operation where the CPU, peripherals, and RF transceiver are active. The digital voltage regulator(数字稳压器) is turned on.
Active mode is used for normal operation.在active模式通过使能PCON.IDLE位 (SLEEPCMD.MODE = 0x00), CPU内核停止运行进入空闲模式. All other peripherals function normally, and any enabled interrupt wakes up the CPU core (to transition back from idle mode to active mode).
3.2、PM1模式
In PM1, the high-frequency oscillators are powered down (32 MHz XOSC and 16 MHz RCOSC). The voltage regulator and the enabled 32 kHz oscillator are on. When PM1 is entered, a power-down sequence is run.
当等待唤醒事件的预期时间相对较短(小于3ms),就要选用PM1模式,因为 PM1 uses a fast power-down/up sequence.
3.3、PM2模式
PM2 具有较低的功耗。在PM2 下的上电复位时刻,外部中断、所选的32 kHz 振荡器和睡眠定时器外设是活动的。I/O 引脚保留在进入PM2 之前设置的I/O 模式和输出值。所有其它内部电路是掉电的。稳压器也是关闭的。当进入PM2 模式,就运行一个掉电序列。
当使用睡眠定时器作为唤醒事件,并结合外部中断时,一般就会进入PM2 模式。相比较PM1,当睡眠时间超过3ms 时,一般选择PM2。比起使用PM1,使用较少的睡眠时间不会降低系统功耗。
3.4、PM3模式
PM3 用于获得最低功耗的运行模式。在PM3 模式下,稳压器供电的所有内部电路都关闭(基本上是所有的数字模块,除了中断探测和POR 电平传感)。内部稳压器和所有振荡器也都关闭。
复位(POR 或外部)和外部I/O 端口中断是该模式下仅有的运行的功能。I/O 引脚保留进入PM3 之前设置的I/O 模式和输出值。复位条件或使能的外部IO 中断事件将唤醒设备,使它进入主动模式(外部中断从它进入PM3 的地方开始,而复位返回到程序执行的开始)。RAM 和寄存器的内容在这个模式下可以部分保留。PM3 使用和PM2 相同的上电/掉电序列。
当等待外部事件时,使用PM3 获得超低功耗。当睡眠时间超过3ms 时应该使用该模式。
4、电源管理控制
所需的供电模式通过使用SLEEPCMD 控制寄存器的MODE 位和PCON.IDLE 位来选择。设置SFR 寄存器的PCON.IDLE 位,进入SLEEPCMD.MODE 所选的模式。
来自端口引脚或睡眠定时器的使能的中断,或上电复位将从其他供电模式唤醒设备,使它回到主动模式。
当进入PM1、PM2 或PM3,就运行一个掉电序列。当设备从PM1、PM2 或PM3 中出来,它在16 MHz开始,如果当进入供电模式(设置PCON.IDLE)且CLKCONCMD.OSC = 0 时,自动变为32 MHz。如果当进入供电模式设置了PCON.IDLE 且CLKCONCMD.OSC = 1,它继续运行在16 MHz。
为了正确运行,设置PCON.IDLE 位的指令必须遵循某种方式。这一指令后面跟的第一条汇编指令的第一个字节不能放在4 字节边界。而且,缓存不能禁用(见FCTL 寄存器描述的CM)。不遵守这一要求可能导致较高的电流消耗。只要遵守了这一要求,设置了PCON.IDLE 位的指令后面的第一条汇编指令在导致系统醒来的中断的ISR 之前、但是系统醒来之后执行。如果这个指令是一个全局中断禁用,后面可以跟醒来之后、但是在ISR 运行之前执行的代码。
5、工程
code:
1 /****************************************************************************
2 * 文 件 名: main.c
3 * 描 述: 设置定时器让系统在设定的时间被唤醒,每次唤醒LED1闪烁3下提示用户
4 ****************************************************************************/
5 #include <ioCC2530.h>
6
7 typedef unsigned char uchar;
8 typedef unsigned int uint;
9 typedef unsigned long ulong;
10
11 #define LED1 P1_0 //P1.0口控制LED1
12
13
14 /****************************************************************************
15 * 名 称: DelayMS()
16 * 功 能: 以毫秒为单位延时 16M时约为535,系统时钟不修改默认为16M
17 * 入口参数: msec 延时参数,值越大,延时越久
18 * 出口参数: 无
19 ****************************************************************************/
20 void DelayMS(uint msec)
21 {
22 uint i,j;
23
24 for (i=0; i<msec; i++)
25 for (j=0; j<535; j++);
26 }
27
28 /****************************************************************************
29 * 名 称: InitLed()
30 * 功 能: 设置LED灯相应的IO口
31 * 入口参数: 无
32 * 出口参数: 无
33 ****************************************************************************/
34 void InitLed(void)
35 {
36 P1DIR |= 0x01; //P1.0定义为输出口
37 LED1 = 1; //LED1灯上电默认为熄灭
38 }
39
40 /****************************************************************************
41 * 名 称: SysPowerMode()
42 * 功 能: 设置系统工作模式
43 * 入口参数: mode等于0为PM0 1为PM1 2为PM2 3为PM3
44 * 出口参数: 无
45 ****************************************************************************/
46 void SysPowerMode(uchar mode)
47 {
48 if(mode < 4)
49 {
50 SLEEPCMD |= mode; //设置系统睡眠模式
51 PCON = 0x01; //进入睡眠模式 ,通过中断唤醒
52 }
53 else
54 PCON = 0x00; //通过中断唤醒系统
55 }
56
57 /****************************************************************************
58 * 名 称: ST_ISR(void) 中断处理函数
59 * 描 述: #pragma vector = 中断向量,紧接着是中断处理程序
60 ****************************************************************************/
61 #pragma vector = ST_VECTOR
62 __interrupt void ST_ISR(void)
63 {
64 STIF = 0; //清标志位
65 SysPowerMode(4); //进入正常工作模式
66 }
67
68 /****************************************************************************
69 * 名 称: SysPowerMode()
70 * 功 能: 初始化休眠定时器,设定后经过指定时间自行唤醒
71 * 入口参数:
72 * 出口参数: 无
73 ****************************************************************************/
74 void InitSleepTimer(void)
75 {
76 ST2 = 0x00;
77 ST1 = 0x00;
78 ST0 = 0x00;
79 EA = 1; //开中断
80 STIE = 1; //睡眠定时器中断使能 0: 中断禁止 1: 中断使能
81 STIF = 0; //睡眠定时器中断标志 0: 无中断未决 1: 中断未决
82 }
83
84 /****************************************************************************
85 * 名 称: Set_ST_Period()
86 * 功 能: 设置睡眠时间
87 * 入口参数: sec 睡眠时间
88 * 出口参数: 无
89 ****************************************************************************/
90 void Set_ST_Period(uint sec)
91 {
92 ulong sleepTimer = 0;
93
94 sleepTimer |= ST0;
95 sleepTimer |= (ulong)ST1 << 8;
96 sleepTimer |= (ulong)ST2 << 16;
97 sleepTimer += ((ulong)sec * (ulong)32768);
98 ST2 = (uchar)(sleepTimer >> 16);
99 ST1 = (uchar)(sleepTimer >> 8);
100 ST0 = (uchar) sleepTimer;
101 }
102
103
104 /****************************************************************************
105 * 程序入口函数
106 ****************************************************************************/
107 void main(void)
108 {
109 uchar i=0;
110
111 InitLed(); //设置LED灯相应的IO口
112 InitSleepTimer(); //初始化休眠定时器
113
114 while(1)
115 {
116 for (i=0; i<6; i++) //LED1闪烁3次提醒用户将进入睡眠模式
117 {
118 LED1 = ~LED1;
119 DelayMS(500);
120 }
121
122 Set_ST_Period(5); //设置睡眠时间,睡眠5秒后唤醒系统
123 SysPowerMode(2); //重新进入睡眠模式PM2
124 }
125 }
其中SysPowerMode在上一节[ZigBee] 10、ZigBee之睡眠定时器讲了SysPowerMode(uchar mode) 用于设置系统进入几种模式,本节不额外说明。重点看SleepTimer的用法。
先看SleepTimer的初始化函数:在上一节中介绍一次定时器比较发生在定时器的值等于24位比较器的值,寄存器ST2:ST1:ST0可以用来设置比较器的值。 当STLOAD.LDRDY=1写入ST0发起加载新的比较值。当STLOAD.LDRDY=0软件不能开始一个新的加载,直到它为1。因此这里的76\77\78行用来设置比较器的值,然后开总中断,开SleepTimer中断,最后将睡眠中断标志位清0。
74 void InitSleepTimer(void)
75 {
76 ST2 = 0x00;
77 ST1 = 0x00;
78 ST0 = 0x00;
79 EA = 1; //开中断
80 STIE = 1; //睡眠定时器中断使能 0: 中断禁止 1: 中断使能
81 STIF = 0; //睡眠定时器中断标志 0: 无中断未决 1: 中断未决
82 }
而Set_ST_Period比较简单,就是将待设置的时间赋值给ST2、ST1和ST0,注意无论是初始化还是这里,在给STx赋值是都是需要最后给ST0赋值,在读取STx值时都是要最先读取ST0的值(这个为什么在上一节中有详细介绍)
90 void Set_ST_Period(uint sec)
91 {
92 ulong sleepTimer = 0;
93
94 sleepTimer |= ST0;
95 sleepTimer |= (ulong)ST1 << 8;
96 sleepTimer |= (ulong)ST2 << 16;
97 sleepTimer += ((ulong)sec * (ulong)32768);
98 ST2 = (uchar)(sleepTimer >> 16);
99 ST1 = (uchar)(sleepTimer >> 8);
100 ST0 = (uchar) sleepTimer;
101 }
这样整个工程就比较容易理解了:main函数开始初始化LED和睡眠定时器,然后在while大循环里面先LED闪烁3次,然后调用睡眠周期设置设置5s,此时睡眠定时器开始计时,而main函数由于执行到设置系统进入PM2模式而休眠,当5s后触发休眠定时器中断,在中断中设置系统进入active模式。
Zigbee系列文章:
[ZigBee] 3、ZigBee基础实验——GPIO输出控制实验-控制Led亮灭
[ZigBee] 5、ZigBee基础实验——图文与代码详解定时器1(16位定时器)(长文)
[ZigBee] 6、ZigBee基础实验——定时器3和定时器4(8 位定时器)
[ZigBee] 7、ZigBee之UART剖析(ONLY串口发送)
[ZigBee] 8、ZigBee之UART剖析·二(串口收发)
[ZigBee] 9、ZigBee之AD剖析——AD采集CC2530温度串口显示
PS:如果您觉得还不错,点个赞,让更多人受益~
@beautifulzzzz 2016-07-18 continue~
e-mail:beautifulzzzz@qq.com
sina:http://weibo.com/beautifulzzzz?is_all=1