level 5
绝零残冰
楼主
这一篇,我们来讨论一下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)实验源码及剖析(下面的框框是可以点的~)头文件及宏定义[url=]

[/url]
/*
实验说明:中断唤醒睡眠实验,分别介绍三种睡眠模式下的唤醒
*/
#include <ioCC2430.h>
#define LED_ON 0
#define LED_OFF 1
#define led1 P1_0
#define led2 P1_1
#define led3 P1_2
#define led4 P1_3 [url=]

[/url]
子函数[url=]

[/url]
/*系统时钟初始化
-------------------------------------------------------*/
void xtal_init(void)
{
SLEEP &= ~0x04; //都上电
while(!(SLEEP & 0x40)); //晶体振荡器开启且稳定
CLKCON &= ~0x47; //选择32MHz 晶体振荡器
SLEEP |= 0x04;
}
/*LED初始化
-------------------------------------------------------*/
void led_init(void)
{
P1SEL = 0x00; //P1为普通 I/O 口
P1DIR |= 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)
{
P0INP &= ~0X02; //P0.1有上拉、下拉
EA = 1; //总中断允许
IEN1 |= 0X20; // P0IE = 1,P0中断使能
PICTL |= 0X09; //P0.1允许中断,下降沿触发
P0IFG &= ~0x02; //P0.1中断标志清0
}
/*睡眠定时器中断初始化
-------------------------------------------------------*/
void sleepTimer_init(void)
{
STIF=0; //睡眠定时器中断标志清0
STIE=1; //开睡眠定时器中断
EA=1; //开总中断
}
/*设置睡眠定时器的定时间隔
-------------------------------------------------------*/
void setSleepTimer(unsigned int sec)
{
unsigned long sleepTimer = 0;
sleepTimer |= ST0; //取得目前的睡眠定时器的计数值
sleepTimer |= (unsigned long)ST1 << 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 |= 0x01; //启用此电源模式
}
}
/*延时函数
-------------------------------------------------------*/
void Delay(unsigned int n)
{
unsigned int i,j;
for(i=0;i<n;i++)
for(j=0;j<1000;j++);
}
[url=]

[/url]
主函数[url=]

[/url]
/*主函数
-------------------------------------------------------*/
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);
}
[url=]

[/url]
中断服务程序[url=]

[/url]
/*外部中断服务程序
-------------------------------------------------------*/
#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; //开中断
}
[url=]

[/url]
关于如何使用睡眠定时器来唤醒系统,可以总结为如下流程:开睡眠定时器中断 → 设置睡眠定时器的定时间隔 → 设置电源模式
(注:“设置睡眠定时器的定时间隔”这一步
http://www.gbblxy.com/forum.php?mod=viewthread&tid=5263&extra=page%3D1
2015年07月27日 02点07分
1

从上表中可看出,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)实验源码及剖析(下面的框框是可以点的~)头文件及宏定义[url=]
[/url]/*
实验说明:中断唤醒睡眠实验,分别介绍三种睡眠模式下的唤醒
*/
#include <ioCC2430.h>
#define LED_ON 0
#define LED_OFF 1
#define led1 P1_0
#define led2 P1_1
#define led3 P1_2
#define led4 P1_3 [url=]
[/url]子函数[url=]
[/url]/*系统时钟初始化
-------------------------------------------------------*/
void xtal_init(void)
{
SLEEP &= ~0x04; //都上电
while(!(SLEEP & 0x40)); //晶体振荡器开启且稳定
CLKCON &= ~0x47; //选择32MHz 晶体振荡器
SLEEP |= 0x04;
}
/*LED初始化
-------------------------------------------------------*/
void led_init(void)
{
P1SEL = 0x00; //P1为普通 I/O 口
P1DIR |= 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)
{
P0INP &= ~0X02; //P0.1有上拉、下拉
EA = 1; //总中断允许
IEN1 |= 0X20; // P0IE = 1,P0中断使能
PICTL |= 0X09; //P0.1允许中断,下降沿触发
P0IFG &= ~0x02; //P0.1中断标志清0
}
/*睡眠定时器中断初始化
-------------------------------------------------------*/
void sleepTimer_init(void)
{
STIF=0; //睡眠定时器中断标志清0
STIE=1; //开睡眠定时器中断
EA=1; //开总中断
}
/*设置睡眠定时器的定时间隔
-------------------------------------------------------*/
void setSleepTimer(unsigned int sec)
{
unsigned long sleepTimer = 0;
sleepTimer |= ST0; //取得目前的睡眠定时器的计数值
sleepTimer |= (unsigned long)ST1 << 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 |= 0x01; //启用此电源模式
}
}
/*延时函数
-------------------------------------------------------*/
void Delay(unsigned int n)
{
unsigned int i,j;
for(i=0;i<n;i++)
for(j=0;j<1000;j++);
}
[url=]
[/url]主函数[url=]
[/url]/*主函数
-------------------------------------------------------*/
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);
}
[url=]
[/url]中断服务程序[url=]
[/url]/*外部中断服务程序
-------------------------------------------------------*/
#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; //开中断
}
[url=]
[/url]关于如何使用睡眠定时器来唤醒系统,可以总结为如下流程:开睡眠定时器中断 → 设置睡眠定时器的定时间隔 → 设置电源模式
(注:“设置睡眠定时器的定时间隔”这一步
http://www.gbblxy.com/forum.php?mod=viewthread&tid=5263&extra=page%3D1