前言:
Zigbee 的特点就是远距离低功耗的无线传输设备,节点模块闲时可以进入睡眠模式,在需要传输数据时候进行唤醒,能进一步节省电量。本实验将讲述CC2530 在睡眠模式下的 2 种唤醒方法:外部中断唤醒和定时器唤醒。
实验功能:
将睡眠模式下的 CC2530 通过按键中断和定时器方式唤醒。通过 LED 状态展示。
关于Zigbee睡眠唤醒的三个重要问题(知识点),我补充在前
问题1:Zigbee CC2530全功能模式、 PM1、 PM2、 PM3四种模式每个模式分别具体对应什么情况?
Zigbee CC2530是一种集成了Zigbee通信协议的芯片,它可以在不同的工作模式下运行。以下是对CC2530的四种模式的具体情况的描述:
需要注意的是,CC2530的不同工作模式可以通过相应的控制指令或设置来切换。具体的实现方法可能会依赖于所使用的开发工具或环境。
问题2:Zigbee数字核心模块是指什么
Zigbee数字核心模块是指一种集成了Zigbee通信协议的芯片或模块,它是用于实现Zigbee无线通信功能的关键部件。这种模块通常包括一个具有Zigbee协议栈的微控制器、无线收发器、射频(RF)前端、天线等组件。
Zigbee数字核心模块提供了一种简化的方式来实现Zigbee网络中的各种角色,如协调器、路由器和终端设备。它具有以下功能:
Zigbee数字核心模块通常被广泛应用于物联网(IoT)领域,用于构建低功耗、短距离、自组织的无线传感器网络。它可以用于智能家居、工业自动化、智能医疗、能源管理等各种应用场景。
问题3:当ZIgbee执行到main函数的while(1)中,假如此时进入了PM2模式,while(1)循环中的程序是继续执行、默认跳过还是停止在某行代码等待唤醒后继续执行
当Zigbee执行到main函数的while(1)循环中并进入了PM2模式时,具体的行为取决于所使用的开发工具和相应的设置。
一种常见的做法是将微控制器设置为在PM2模式下自动进入睡眠状态,并且唤醒条件被设置为外部中断或定时器中断等。在这种情况下,当进入PM2模式时,程序会停止执行,并且微控制器进入低功耗睡眠状态,直到满足唤醒条件。
一旦满足唤醒条件,微控制器将被唤醒并继续执行while(1)循环中的程序。它会从暂停的位置继续执行,而不是跳过或重新启动。
需要注意的是,具体的实现方式可能因芯片型号、开发工具和应用程序的要求而有所不同。因此,了解所使用的具体开发环境和相关文档中的相关配置和设置是非常重要的。
实验讲解:
睡眠定时器用于设置系统进入和退出低功耗睡眠模式之间的周期。还用于当系统进入低功耗模式后,维持 MAC 定时器(T2)的定时。其特性如下:长达 24 位定时计数器,运行在 32.768KHZ 的工作频率。 24 位的比较器具有中断和 DMA 触发功能在 PM2 低功耗模式下运行
系统电源管理(工作方式如下):
1. 全 功 能 模 式 , 高 频 晶 振 ( 16M 或 者 32M ) 和 低 频 晶 振 ( 32.768KRCOSC/XOSC )全部工作, 数字处理模块正常工作。
2. PM1 : 高频晶振(16M 或者 32M )关闭,低频晶振(32.768K RCOSC/XOSC )工作,数字核心模块正常工作。
3. PM2 :低频晶振(32.768K RCOSC/XOSC )工作, 数字核心模块关闭,系统通过 RESET,外部中断或者睡眠计数器溢出唤醒。
4. PM3 : 晶振全部关闭,数字处理核心模块关闭,系统只能通过 RESET 或外部中断唤醒。此模式下功耗最低。
我们先来看看 WeBee 底板的 LED 部分原理图:
1.实验1:中断唤醒
CC2530 需要配置的主要寄存器如下: PCON , SLEEPCMD。 功能如下表所示: (详细参考 CC2530 datasheet.pdf)
该寄存器有以下配置方法:
SLEEPCMD |= i; // 设置系统睡眠模式, i=0,1,2,3
PCON = 0x01; // 进入睡眠模式 ,通过中断打断
PCON = 0x00; // 系统唤醒 ,通过中断打断
完整程序:
/*描述:LED2闪烁5次后进入睡眠状态,通
过按下按键S1产生外部中断进行唤
醒,重新进入工作模式。
**************************************/
#include
#define uint unsigned int
#define uchar unsigned char
//定义控制LED灯和按键的端口
#define LED2 P1_1 //定义LED2为P11口控制
#define KEY1 P0_0
//函数声明
void Delayms(uint); //延时函数
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定义为输出
P1INP |= 0X02; //打开下拉
LED2 = 0; //LED2灯熄灭
P0INP &= ~0X01; //设置P0口输入电路模式为上拉/ 下拉
P0IEN |= 0X01; //P00设置为中断方式
PICTL |= 0x01; //下降沿触发
}
/****************************************************************
系统工作模式选择函数
* 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,等待按键S1中断唤醒
}
Delayms(500);
}
}
/*****************************************
中断处理函数-系统唤醒
*****************************************/
#pragma vector = P0INT_VECTOR
__interrupt void P0_ISR(void)
{
if(P0IFG>0)
{
P0IFG = 0; //清标志位
}
P0IF = 0;
SysPowerMode(4); //正常工作模式
}
实验1现象
2.实验2:定时器唤醒
CC2530 睡眠定时器除了实验 1 之外还需要配置的寄存器如下: ST0 , ST1 ,ST2。 也就是文初提及到的 24bit 定时器。如下表所示: (详细参考 CC2530datasheet.pdf)
配置唤醒时间寄存器有以下配置方法:
UINT32 sleepTimer = 0;
sleepTimer |= ST0;
sleepTimer |= (UINT32)ST1
sleepTimer |= (UINT32)ST2
sleepTimer += ((UINT32)sec * (UINT32)32768) //低速晶振;
ST2 = (UINT8)(sleepTimer >> 16);
ST1 = (UINT8)(sleepTimer >> 8);
ST0 = (UINT8) sleepTimer;
配置完毕后 sleepTimer 与 ST2<<16|ST1<<8|ST0相差 sec 秒时间(低速晶振)
完整程序
/*描述:通过设置定时器在特定时间内进行
唤醒,重新进入工作模式,每次唤
醒LED2闪烁3下。
**************************************/
#include
#define uint unsigned int
#define uchar unsigned char
#define UINT8 unsigned char
#define UINT16 unsigned int
#define UINT32 unsigned long
//定义控制LED灯的端口
#define LED2 P1_1 //定义LED2为P1.1口控制
//函数声明
void Delayms(uint); //延时函数
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_0、P1_1定义为输出
P1INP |= 0X02; //打开下拉
LED2 = 0; //LED2灯熄灭
}
/****************************************************************
系统工作模式选择函数
* 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);
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); //进入正常工作模式
}
实验2现象