登录
|
注册会员
开启辅助访问
设为首页
收藏本站
扫一扫关注官方微信
论坛
BBS
M币充值
M currency prepaid phone
M币获取
附件中心
搜索
search
全新论坛MCU智学网上线,欢迎访问新论坛!稀缺资源、技术干货、参考设计、原厂资料尽在MCU智学网
MCU资讯论坛
»
论坛
›
单片机论坛
›
单片机应用于方案
›
CC2430的睡眠功能及唤醒方法
更新自动建库工具PCB Footprint Expert 2023.13 Pro / Library Expert 破解版
CC2430的睡眠功能及唤醒方法
[复制链接]
4871
1
ad***
管理员
发表在
电源技术
2014-4-2 09:32:31
|
查看全部
|
阅读模式
本文包含原理图、PCB、源代码、封装库、中英文PDF等资源
您需要
登录
才可以下载或查看,没有帐号?
注册会员
x
一、承上启下
这一篇,我们来讨论一下CC
24
30的睡眠功能及唤醒方法。在实际运用中的
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
#define
LED
_ON 0
#define LED_OFF 1
#define led1 P1_0
#define led2 P1_1
#define led3 P1_2
#define led4 P1_3
子函数
/*系统时钟初始化
-------------------------------------------------------*/
void xtal_init(void)
{
SLEEP &
amp
;= ~0x
04
; //都上电
while(!(SLEEP & 0
x40
)); //
晶体振荡器
开启且稳定
CLKCON &= ~0x47; //选择32MHz 晶体振荡器
SLEEP |= 0
x04
;
}
/*LED初始化
-------------------------------------------------------*/
void led_init(void)
{
P1
SEL
= 0
x00
; //P1为普通 I/O 口
P1
DIR
|= 0x0F; //P1.0 P1.1 P1.2 P1.3 输出
led1 = LED_OFF; //关闭所有LED
led2 = LED_OFF;
led3 = LED_OFF;
led4 = LED_OFF;
}
/*外部中断初始化
-------------------------------------------------------*/
void io_init(void)
{
P0
INP
&= ~0
X02
; //P0.1有上拉、下拉
EA = 1; //总中断允许
IEN1 |= 0
X20
; // P0IE = 1,P0中断使能
PICTL |= 0X
09
; //P0.1允许中断,下降沿触发
P0IFG &= ~0x02; //P0.1中断标志清0
}
/*睡眠定时器中断初始化
-------------------------------------------------------*/
void sleepTimer_init(void)
{
ST
IF=0; //睡眠定时器中断标志清0
STIE=1; //开睡眠定时器中断
EA=1; //开总中断
}
/*设置睡眠定时器的定时间隔
-------------------------------------------------------*/
void setSleepTimer(unsigned int
sec
)
{
unsigned long sleepTimer = 0;
sleepTimer |=
ST0
; //取得目前的睡眠定时器的计数值
sleepTimer |= (unsigned long)
ST1
&
lt
;< 8;
sleepTimer |= (unsigned long)
ST2
<<
16
;
sleepTimer += ((unsigned long)sec * (unsigned long)32768); //加上所需要的定时时长
ST2 = (unsigned char)(sleepTimer >> 16); //设置睡眠定时器的比较值
ST1 = (unsigned char)(sleepTimer >> 8);
ST0 = (unsigned char)sleepTimer;
}
/*选择电源模式
-------------------------------------------------------*/
void PowerMode(unsigned char mode)
{
if(mode<4)
{
SLEEP &= 0xfc; //将SLEEP.MODE清0
SLEEP |= mode; //选择电源模式
PCON |= 0
x01
; //启用此电源模式
}
}
/*延时函数
-------------------------------------------------------*/
void Delay(unsigned int n)
{
unsigned int i,j;
for(i=0;i
for(j=0;j<1000;j++);
}
主函数
/*主函数
-------------------------------------------------------*/
void main(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);
}
中断服务程序
/*外部中断服务程序
-------------------------------------------------------*/
#pragma vector = P0INT_VECTOR
__interrupt void P0_ISR(void)
{
EA = 0; //关中断
Delay(50);
if((P0IFG & 0x02 ) >0 ) //按键中断
{
P0IFG &= ~0x02; //P0.1中断标志清0
}
P0IF = 0; //P0中断标志清0
EA = 1; //开中断
}
/*睡眠定时器中断服务程序
-------------------------------------------------------*/
#pragma vector= ST_VECTOR
__interrupt void sleepTimer_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)首先,定义一个unsigned long型变量(32位)sleepTimer,用于接收睡眠定时器的当前计数值:
unsigned long sleepTimer = 0;
sleepTimer |= ST0; //取得目前的睡眠定时器的计数值
sleepTimer |= (unsigned long)ST1 << 8;
sleepTimer |= (unsigned long)ST2 << 16;
(2)然后加上所需要的定时间隔:
sleepTimer += ((unsigned long)sec * (unsigned long)32768); //加上所需要的定时时长
此处需要稍微解释一下:
为什么1s就代表着32768?因为定时器是工作在32.768kHz之下,所以定时器每加1,需耗时1/32768 s;加32768,就需要1s;
(3)最后将sleepTimer的值作为定时器的比较值:
ST2 = (unsigned char)(sleepTimer >> 16); //设置睡眠定时器的比较值
ST1 = (unsigned char)(sleepTimer >> 8);
ST0 = (unsigned char)sleepTimer;
这样,就可成功设置定时器的定时周期啦~
(注:至于源码的其他部分,相信结合着详细的注释,大家可以轻松看懂,在此不作赘述)
(4)实验结果
运行程序,观察LED1,现象为:LED1闪烁(即亮->灭1次),1s后再次闪烁,2s后再次闪烁,然后保持熄灭状态,然后按下S1,LED1亮。
实验现象和预期完全吻合,Over~
三、结语
吁~ 抽出2天的课余时间,终于搞定了这篇日志。真的发现写博,特别是写一篇“读者友好”的博文,的确是一项体力活:严谨性、美观性、逻辑性...都是要考虑的事儿。
每次贴代码都嫌太长,但又不太愿意使用博客园自带的折叠工具。因此在本篇博文中,笔者试探性的加入了一些JQuery元素,实现了代码的平滑折叠,还是有小小的成就感嘀,呵呵(JQuery菜鸟,高手勿笑~)。但当局者迷,我并不知这样做是否真正增强了文章的可读性,欢迎读者朋友作出评论 :)
这一个月,笔者真正决定在博客园扎下根来,于是花费了大量的课余时间在博文的写作上。初次写博,虽然评论很少,但大部分日志都有500以上的点击率,也算是对我的小小的鼓励!在博客园发表关于
单片机
的内容,的确需要勇气,不过我会坚持写下去的~
从开始到现在的九篇博文,重点是CC2430芯片上的基本硬件
模块
的运用。到此为止,我们基本上把CC2430上的大部分外设都过了一遍,但是还有比如
Flash
存取、随机数发生器、
AE
S协处理器、射频通信等,还没涉及到。不过Zigbee之旅并未结束,笔者打算在下一个主题(Z-Stack 协议的实现)中,再来有选择性的把这些遗漏之处补齐。
下一篇博文,笔者打算以一个稍带综合性与扩展性的小实验--“温度监测系统”来结束Zigbee的首次旅行,讲解一下如何去综合运用前面学到的知识点。
其实根本没有资格称“讲解”,作为一个初学者,笔者只希望在写博的过程中与读者互勉,共同进步!
举报
回复
1 个评论
f***
新手上路
发表于 2014-9-27 14:41:01
|
显示全部楼层
{:soso_e179:}
举报
回复
支持
反对
返回列表
*
滑块验证:
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
注册会员
本版积分规则
发表回复
回帖后跳转到最后一页
回复
转播
评分
分享
打开支付宝扫一扫,最高立得1212元红包
搜索
本版
帖子
用户
热搜:
传感器
51串口程序
电子管放大器
夾式電表
夾式電流
Mentor论坛
打印机
版块推荐
百宝箱
My 布拉格
无边框Z9
Z9Max
Z9mini
nubia动态
问题 & 建议
资源分享
爱拍
同城会
牛仔生活
查看论坛所有版块>>
每日签到
论坛任务
摄影技巧
跳蚤市场
互助问答
论坛导读
申请内测
红包中心
每日摇一摇
活动中心
网站地图
官方旗舰店
图文热点
工控仪表液晶驱动VK0192 LQFP44/点阵LCD液
产品品牌:永嘉微电/VINKA 产品型号:VK0192 封装形式:LQFP44 概述 VK0192是一
不用电池收音机中锗三极管的替代
图中的检波二极管已找到贴片器件,图中的锗三极管能否使用贴片替换?
小封装液晶驱动VK1088B QFN32L点阵LCD液晶
产品品牌:永嘉微电/VINKA 产品型号:VK1088B 封装形式:QFN32L 概述 VK1088B是
LCD液晶驱动/点阵段码屏驱动芯片VK1072D SS
产品品牌:永嘉微电/VINKA 产品型号:VK1072D 封装形式:SSOP28 概述 VK1072D
VK1072C SOP28/3线串行接口LCD液晶显示驱动
产品品牌:永嘉微电/VINKA 产品型号:VK1072C 封装形式:SOP28 概述 VK1072C是
更多
精华推荐
51单片机的智能反汇编工具
工控仪表液晶驱动VK0192 LQFP44/点阵LCD液
不用电池收音机中锗三极管的替代
小封装液晶驱动VK1088B QFN32L点阵LCD液晶
LCD液晶驱动/点阵段码屏驱动芯片VK1072D SS
VK1072C SOP28/3线串行接口LCD液晶显示驱动
AP8100 外围简单的 BOOST 升压恒压控制驱动
AP510X 单路低压差线性恒流芯片 LED手电筒
更多
社区学堂
工控仪表液晶驱动VK0192 LQFP44/点阵LC
不用电池收音机中锗三极管的替代
工控仪表液晶驱动VK0192 LQFP44/点阵LCD液
产品品牌:永嘉微电/VINKA 产品型号:VK0192 封装形式:LQFP44 概述 VK0192是一
不用电池收音机中锗三极管的替代
图中的检波二极管已找到贴片器件,图中的锗三极管能否使用贴片替换?
小封装液晶驱动VK1088B QFN32L点阵LCD液晶
产品品牌:永嘉微电/VINKA 产品型号:VK1088B 封装形式:QFN32L 概述 VK1088B是
更多
客服中心
QQ:187196467
服务时间:周一至周日 8:30-20:30
在线客服
客服微博
产品咨询
售后中心
关注我们
关于我们
关于我们
友情链接
联系我们
帮助中心
网友中心
购买须知
支付方式
服务支持
资源下载
售后服务
定制流程
关注我们
官方微博
官方空间
官方微信
QQ:187196467
周一到周日 8:30-22:00 (全年无休)
7 x 24小时在线客服
手机版
Powered by
MCUZX!
X3.4 © 2008-2015
MCU资讯论坛
版权所有
京ICP备18035221号-2
客服QQ: 187196467
技术支持:
MCU资讯论坛
|
网站地图
快速回复
返回顶部
返回列表