所有课程见此链接:
4.8睡眠唤醒实验
1.学习CC2530的低功耗控制方式;
2.CC2530的中断和定时器唤醒。
对于远距离的无限传输设备,功耗是一个较为关键的技术指标,而基于单片机CC2530单片机的ZigBee系统在低功耗方面有着较为明显的优势,节点模块闲时可以进入睡眠模式,在需要传输数据时候进行唤醒,能进一步节省电量。本节将讲述CC2530 在睡眠模式下的 2 种唤醒方法:外部中断唤醒和定时器唤醒。
ZigBee节点的唤醒有两种方式分别为:定时器唤醒和中断唤醒睡眠,定时器用于设置系统进入和退出低功耗睡眠模式之间的周期,还用于当系统进入低功耗模式后,维持 MAC 定时器(T2)的定时。其特性如下:24位定时计数器运行在 32.768KHZ 的工作频率。24 位的比较器具有中断和 DMA 触发功能在 PM2 低功耗模式下运行。
1.中断唤醒
CC2530 需要配置的主要寄存器如下:PCON ,SLEEPCMD。功能如表4-7所示:
表4-7 CC2530中断方式唤醒休眠相关控制寄存器
系统电源模式控制寄存器PCON(0x87) |
Bit0 |
1 |
将强制系统进入 SLEEPCMD 所指定的电源模式,所有中断信号都可以 清除此置位。 |
0 |
|||
系统电源模式设定SLEEPCMD(0xBE) |
Bit1:Bit0 |
00 |
全功能模式 |
01 |
PM1 |
||
10 |
PM2 |
||
11 |
PM3 |
2.定时器唤醒
定时器唤醒除了要对寄存器PCON、SLEEPCMD进行设置,还需要对定时器计数寄存器ST0、ST1、ST2进行设置,其具体功能描述如表4-8:
表4-8 CC2530定时器方式唤醒休眠相关控制寄存器
ST0(0x95) |
睡眠计数器数据 Bit7 :Bit0 |
ST1(0x96) |
睡眠计数器数据 Bit15:Bit8 |
ST2(0x97) |
睡眠计数器数据 Bit23:Bit16 |
根据表中相关寄存器的功能说明,具体进行如下配置:
SLEEPCMD |= i; // 设置系统睡眠模式,i=0,1,2,3
PCON = 0x01; // 进入睡眠模式 ,通过中断打断
PCON = 0x00; // 系统唤醒 ,通过中断打断
UINT32 sleepTimer = 0;
sleepTimer |= ST0;
sleepTimer |= (UINT32)ST1 << 8;
sleepTimer |= (UINT32)ST2 << 16;
sleepTimer += ((UINT32)sec * (UINT32)32768) //低速晶振;
ST2 = (UINT8)(sleepTimer >> 16);
ST1 = (UINT8)(sleepTimer >> 8);
ST0 = (UINT8) sleepTimer;
具体程序如下所示:
中断唤醒程序
#include <ioCC2530.h>
#define uint unsigned int
#define uchar unsigned char
//定义控制LED灯和按键的端口
#define LED2 P1_1 //定义LED2为P11口控制
#define KEY1 P0_4
//函数声明
void Delayms(uint); //延时函数
void InitLed(void);
void SysPowerMode(uchar sel); //系统工作模式
/****************************
延时函数
*****************************/
void Delayms(uint xms) //i=xms 即延时i毫秒
{
uint i,j;
for(i=xms;i>0;i--)
for(j=587;j>0;j--);
}
/****************************
//初始化程序
*****************************/
void InitLed(void)
{
P1DIR |= 0x02; //P1_1定义为输出
LED2 = 1; //LED2灯熄灭
P0INP &= ~0X10; //设置P0口输入电路模式为上拉/ 下拉
P0IEN |= 0X10; //P01设置为中断方式
PICTL |= 0X10; // 下降沿触发
}
/****************************************************************
系统工作模式选择函数
* para1 0 1 2 3
* mode PM0 PM1 PM2 PM3
****************************************************************/
void SysPowerMode(uchar mode)
{
uchar i,j;
i = mode;
if(mode<4)
{
SLEEPCMD |= i; // 设置系统睡眠模式
for(j=0;j<4;j++);
PCON = 0x01; // 进入睡眠模式 ,通过中断打断
}
else
{
PCON = 0x00; // 系统唤醒 ,通过中断打断
}
}
/***************************
主函数
***************************/
void main(void)
{
uchar count = 0;
InitLed(); //调用初始化函数
IEN1 |= 0X20; // 开P0口总中断
P0IFG |= 0x00; //清中断标志
EA = 1;
while(1)
{
LED2=~LED2;
if(++count>=10)
{
count=0;
SysPowerMode(3); //5次闪烁后进入睡眠状态PM3,等待按键S3中断唤醒
}
Delayms(500);
}
}
/*****************************************
中断处理函数-系统唤醒
*****************************************/
#pragma vector = P0INT_VECTOR
__interrupt void P0_ISR(void)
{
if(P0IFG>0)
{
P0IFG = 0; //清标志位
}
P0IF = 0;
SysPowerMode(4); //正常工作模式
}
定时器唤醒程序
#include <ioCC2530.h>
#define uint unsigned int
#define uchar unsigned char
#define UINT8 unsigned char
#define UINT32 long unsigned int
//定义控制 LED 灯和按键的端口
#define LED2 P1_1 //定义 LED2 为 P11口控制
#define KEY1 P0_4
//函数声明
void Delayms(uint xms); //延时函数
void InitLed(void); //初始化 P1 口
void SysPowerMode(uchar sel); //系统工作模式
/****************************
延时函数
*****************************/
void Delayms(uint xms) //i=xms 即延时 i 毫秒
{
uint i,j;
for(i=xms;i>0;i--)
for(j=587;j>0;j--);
}/****************************
//初始化程序
*****************************/
void InitLed(void)
{
P1DIR |= 0x02; //P1_1 定义为输出
LED2 = 1; //LED2 灯熄灭
P0INP &= ~0X10; //设置 P0 口输入电路模式为上拉/ 下拉
P0IEN |= 0X10; //P01 设置为中断方式
PICTL |= 0X10; // 下降沿触发
}
/***************************************************************
系统工作模式选择函数
* para1 0 1 2 3
* mode PM0 PM1 PM2 PM3
***************************************************************/
void SysPowerMode(uchar mode)
{
uchar I,j;
I = mode;
if(mode<4)
{
SLEEPCMD |= I; // 设置系统睡眠模式
for(j=0;j<4;j++);
PCON = 0x01; // 进入睡眠模式 ,通过中断打断
}
else
{
PCON = 0x00; // 系统唤醒 ,通过中断打断
}
}
/*****************************************
//初始化 Sleep Timer (设定后经过指定时间自行唤醒)
*****************************************/
void Init_SLEEP_TIMER(void)
{
ST2 = 0X00;
ST1 = 0X0F;
ST0 = 0X0F;
EA = 1; //开中断
STIE = 1; //SleepTimerinterrupt enable
STIF = 0; //SleepTimerinterrupt flag 还没处理的
}
/***************************************************************
设置睡眠时间
***************************************************************/
void Set_ST_Period(uint sec)
{
UINT32 sleepTimer = 0;
sleepTimer |= ST0;
sleepTimer |= (UINT32)ST1 << 8;
sleepTimer |= (UINT32)ST2 << 16;
sleepTimer += ((UINT32)sec * (UINT32)32768);//低频晶振 PM2 模式
ST2 = (UINT8)(sleepTimer >> 16);
ST1 = (UINT8)(sleepTimer >> 8);
ST0 = (UINT8) sleepTimer;
}/***************************
//主函数
***************************/
void main(void)
{
uchar i;
InitLed(); //调用初始化函数
Init_SLEEP_TIMER(); //初始化 SLEEPTIMER
while(1)
{
for(i=0;i<6;i++) //闪烁 3 下
{
LED2=~LED2;
Delayms(200);
}
Set_ST_Period(3); //重新进入睡眠模式
SysPowerMode(2); //进入 PM2 低频晶振模式
}
}
//睡眠中断唤醒
#pragma vector = ST_VECTOR
__interrupt void ST_ISR(void)
{
STIF = 0; //清标志位
SysPowerMode(4); //进入正常工作模式
}
在中断唤醒模式下,通过按下按键 S3(KEY1)产生外部中断进行唤醒,D4(LED2)闪烁5次后进入睡眠状态,重新进入工作模式。
在定时器唤醒模式下,通过设置定时器在特定时间内进行唤醒,重新进入工作模式,每次唤醒D4(LED2)闪烁3下。
扩展知识——CC2530的电源管理
系统电源管理(工作方式如下):
1. 全功能模式,高频晶振(16M 或者 32M )和低频晶振(32.768K RCOSC/XOSC )
全部工作,数字处理模块正常工作。
2. PM1:高频晶振(16M 或者 32M )关闭,低频晶振(32.768K RCOSC/XOSC )
工作,数字核心模块正常工作。
3.PM2:低频晶振(32.768K RCOSC/XOSC )工作,数字核心模块关闭,系统通过 RESET,外部中断或者睡眠计数器溢出唤醒。
4. PM3:晶振全部关闭,数字处理核心模块关闭,系统只能通过 RESET 或外部中断唤醒。此模式下功耗最低。