睡眠及唤醒.docx
- 文档编号:9756552
- 上传时间:2023-02-06
- 格式:DOCX
- 页数:11
- 大小:250.77KB
睡眠及唤醒.docx
《睡眠及唤醒.docx》由会员分享,可在线阅读,更多相关《睡眠及唤醒.docx(11页珍藏版)》请在冰豆网上搜索。
睡眠及唤醒
一、承上启下
这一篇,我们来讨论一下CC2430的睡眠功能及唤醒方法。
在实际运用中的CC2430节点一般是靠电池来供电,因此对其功耗的控制显得至关重要。
下面是摘自CC2430中文手册对CC2430的4种功耗模式的介绍:
从上表中可看出,CC2430共有4种电源模式:
PM0(完全清醒),PM1(有点瞌睡)、PM2(半醒半睡)、PM3(睡的很死)。
越靠后,被关闭的功能越多,功耗也越来越低。
它们之间的转化关系如下:
把PM1、PM2唤醒到PM0,有三种方式:
复位、外部中断、睡眠定时器中断;但把PM3唤醒到PM0,只有两种方式:
复位、外部中断(这是因为在PM3下,所有振荡器均停止工作,睡眠定时器当然也熄火啦~)
下面我们通过一个小实验,来介绍如何进入睡眠模式,以及如何唤醒到PM0状态。
二、系统睡眠及中断唤醒实验
(1)实验简介
系统初始化,处于PM0
→进入PM1
→1s后被睡眠定时器唤醒为PM0
→进入PM2
→ 2s后被睡眠定时器唤醒为PM0
→进入PM3
→等待按键S1按下,触发外部中断,被唤醒为PM0
(2)程序流程图
(注:
上图中的圆角框表示系统的运行状况)
(3)实验源码及剖析(下面的框框是可以点的~)
头文件及宏定义
/*
实验说明:
中断唤醒睡眠实验,分别介绍三种睡眠模式下的唤醒
*/
#include
#defineLED_ON0
#defineLED_OFF1
#defineled1P1_0
#defineled2P1_1
#defineled3P1_2
#defineled4P1_3
子函数
/*系统时钟初始化
-------------------------------------------------------*/
voidxtal_init(void)
{
SLEEP&=~0x04;//都上电
while(!
(SLEEP&0x40));//晶体振荡器开启且稳定
CLKCON&=~0x47;//选择32MHz晶体振荡器
SLEEP|=0x04;
}
/*LED初始化
-------------------------------------------------------*/
voidled_init(void)
{
P1SEL=0x00;//P1为普通I/O口
P1DIR|=0x0F;//P1.0P1.1P1.2P1.3输出
led1=LED_OFF;//关闭所有LED
led2=LED_OFF;
led3=LED_OFF;
led4=LED_OFF;
}
/*外部中断初始化
-------------------------------------------------------*/
voidio_init(void)
{
P0INP&=~0X02;//P0.1有上拉、下拉
EA=1;//总中断允许
IEN1|=0X20;//P0IE=1,P0中断使能
PICTL|=0X09;//P0.1允许中断,下降沿触发
P0IFG&=~0x02;//P0.1中断标志清0
}
/*睡眠定时器中断初始化
-------------------------------------------------------*/
voidsleepTimer_init(void)
{
STIF=0;//睡眠定时器中断标志清0
STIE=1;//开睡眠定时器中断
EA=1;//开总中断
}
/*设置睡眠定时器的定时间隔
-------------------------------------------------------*/
voidsetSleepTimer(unsignedintsec)
{
unsignedlongsleepTimer=0;
sleepTimer|=ST0;//取得目前的睡眠定时器的计数值
sleepTimer|=(unsignedlong)ST1<<8;
sleepTimer|=(unsignedlong)ST2<<16;
sleepTimer+=((unsignedlong)sec*(unsignedlong)32768);//加上所需要的定时时长
ST2=(unsignedchar)(sleepTimer>>16);//设置睡眠定时器的比较值
ST1=(unsignedchar)(sleepTimer>>8);
ST0=(unsignedchar)sleepTimer;
}
/*选择电源模式
-------------------------------------------------------*/
voidPowerMode(unsignedcharmode)
{
if(mode<4)
{
SLEEP&=0xfc;//将SLEEP.MODE清0
SLEEP|=mode;//选择电源模式
PCON|=0x01;//启用此电源模式
}
}
/*延时函数
-------------------------------------------------------*/
voidDelay(unsignedintn)
{
unsignedinti,j;
for(i=0;i for(j=0;j<1000;j++); } 主函数 /*主函数 -------------------------------------------------------*/ voidmain(void) { xtal_init(); led_init(); //PM0状态,亮灯并延时 led1=LED_ON;//亮LED1,表示统在PM0模式工作 Delay(10); //PM1状态,灭灯 setSleepTimer (1);//设置睡眠定时器的定时间隔为1s sleepTimer_init();//开睡眠定时器中断 led1=LED_OFF; PowerMode (1);//设置电源模式为PM1 //1s后,由PM1进入PM0,亮灯并延时 led1=LED_ON; Delay(50); //PM2,灭灯 setSleepTimer (2);//设置睡眠定时器的定时间隔为2s led1=LED_OFF; PowerMode (2);//设置电源模式为PM2 //2s后,由PM2进入PM0,亮灯并延时 led1=0; Delay(50); //PM3,灭灯 io_init();//初始化外部中断 led1=LED_OFF; PowerMode(3);//设置电源模式为PM3 //当外部中断发生时,由PM3进入PM0,亮灯 led1=LED_ON; while (1); } 中断服务程序 /*外部中断服务程序 -------------------------------------------------------*/ #pragmavector=P0INT_VECTOR __interruptvoidP0_ISR(void) { EA=0;//关中断 Delay(50); if((P0IFG&0x02)>0)//按键中断 { P0IFG&=~0x02;//P0.1中断标志清0 } P0IF=0;//P0中断标志清0 EA=1;//开中断 } /*睡眠定时器中断服务程序 -------------------------------------------------------*/ #pragmavector=ST_VECTOR __interruptvoidsleepTimer_IRQ(void) { EA=0;//关中断 STIF=0;//睡眠定时器中断标志清0 EA=1;//开中断 } 关于如何使用睡眠定时器来唤醒系统,可以总结为如下流程: 开睡眠定时器中断→设置睡眠定时器的定时间隔→设置电源模式 (注: “设置睡眠定时器的定时间隔”这一步一定要在“设置电源模式”之前,因为进入睡眠后系统就不会继续执行程序了) 接下来,我们重点关注一下设置睡眠定时器定时间隔的子函数: setSleepTimer 首先对睡眠定时器简单的介绍一下: 它是运行于32.768kHz的24位定时器,当系统运行在除了PM3之外的所有的电源模式下,睡眠定时器都会不间断运行。 睡眠定时器使用的寄存器有: ST0,ST1,ST2。 下面是摘自CC2430中文手册对其功能的详细介绍: 可以看出,它们的功能包括两方面: 读,写。 读: 用于读取当前定时器的计数值,读的顺序必须遵循: 读ST0→读ST1→读ST2 写: 用于设置定时器的比较值(当定时器的计数值=比较值时,产生中断),写的顺序必须遵循: 写ST2→写ST1→写ST0 OK,接下来我们结合源码来讲解: (1)首先,定义一个unsignedlong型变量(32位)sleepTimer,用于接收睡眠定时器的当前计数值: unsignedlongsleepTimer=0; sleepTimer|=ST0;//取得目前的睡眠定时器的计数值 sleepTimer|=(unsignedlong)ST1<<8; sleepTimer|=(unsignedlong)ST2<<16; (2)然后加上所需要的定时间隔: sleepTimer+=((unsignedlong)sec*(unsignedlong)32768);//加上所需要的定时时长 此处需要稍微解释一下: 为什么1s就代表着32768? 因为定时器是工作在32.768kHz之下,所以定时器每加1,需耗时1/32768s;加32768,就需要1s; (3)最后将sleepTimer的值作为定时器的比较值: ST2=(unsignedchar)(sleepTimer>>16);//设置睡眠定时器的比较值 ST1=(unsignedchar)(sleepTimer>>8); ST0=(unsignedchar)sleepTimer; 这样,就可成功设置定时器的定时周期啦~ (注: 至于源码的其他部分,相信结合着详细的注释,大家可以轻松看懂,在此不作赘述) (4)实验结果 运行程序,观察LED1,现象为: LED1闪烁(即亮->灭1次),1s后再次闪烁,2s后再次闪烁,然后保持熄灭状态,然后按下S1,LED1亮。 实验现象和预期完全吻合,Over~ 三、结语 吁~抽出2天的课余时间,终于搞定了这篇日志。 真的发现写博,特别是写一篇“读者友好”的博文,的确是一项体力活: 严谨性、美观性、逻辑性...都是要考虑的事儿。 每次贴代码都嫌太长,但又不太愿意使用博客园自带的折叠工具。 因此在本篇博文中,笔者试探性的加入了一些JQuery元素,实现了代码的平滑折叠,还是有小小的成就感嘀,呵呵(JQuery菜鸟,高手勿笑~)。 但当局者迷,我并不知这样做是否真正增强了文章的可读性,欢迎读者朋友作出评论: ) 这一个月,笔者真正决定在博客园扎下根来,于是花费了大量的课余时间在博文的写作上。 初次写博,虽然评论很少,但大部分日志都有500以上的点击率,也算是对我的小小的鼓励! 在博客园发表关于单片机的内容,的确需要勇气,不过我会坚持写下去的~ 从开始到现在的九篇博文,重点是CC2430芯片上的基本硬件模块的运用。 到此为止,我们基本上把CC2430上的大部分外设都过了一遍,但是还有比如Flash存取、随机数发生器、AES协处理器、射频通信等,还没涉及到。 不过Zigbee之旅并未结束,笔者打算在下一个主题(Z-Stack协议的实现)中,再来有选择性的把这些遗漏之处补齐。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 睡眠 唤醒