zigbee笔记:七、zigbee系统电源管理与睡眠唤醒

news2025/5/30 14:40:14

        zigbee的低功耗、近距离无线传输的特点使得其在一众近距离无线传输方案中备受青睐。而zigbee低功耗优势是通过根据不同工况选择运行在不同的运行模式(供电模式)实现的,因此,掌握zigbee的系统电源管理与睡眠唤醒的相关知识,是对zigbee进行优势开发的重中之重。本文将根据开发经验和网络相关资料进行详解解读,也欢迎指正。(声明:本文为总结性文章,内容有大量引用其他博主的内容,末尾有参考链接声明)

一、zigbee的电源管理模式

        zigbee cc2530是一种集成了Zigbee通信协议的芯片,通过不同的运行模式(电源模式)可以实现低功耗的操作。运行模式有主动模式、空闲模式和供电模式 1、2 和 3(PM1-PM3),各自特点如下图:

        (1)主动模式:即完全功能的运行模式,也是复位设备默认运行模式,数字稳压器为开启状态,CPU、外设和 RF 收发器都是活动的,高 频 晶 振 ( 16M 或 者 32M ) 和 低 频 晶 振 ( 32.768KRCOSC/XOSC )全部工作, 数字处理模块正常工作。在该模式下cc2530可以充当Zigbee网络中的协调器(Coordinator)、路由器(Router)或终端设备(End Device)。

        (2)空闲模式:除了 CPU 内核停止运行(即空闲),其他和主动模式一样。在主动模式(SLEEPCMD.MODE = 0x00)通过使能 PCON.IDLE 位,CPU 内核就停止运行,进入空闲模式。所有其他外设将正常工作,且 CPU 内核将被任何使能的中断唤醒(从空闲模式转换到主动模式)。

        (3)PM1模式:低功耗模式1(Power Mode 1)。在PM1模式下,稳压器的数字部分开启。32 MHz XOSC 和 16 MHz RCOSC 都不运行。32 kHz RCOSC 或 32 kHz XOSC运行。复位、外部中断或睡眠定时器过期时系统将转到主动模式。该模式下cc2530的主要功能是接收和处理数据,但其无线电部分处于关闭状态,以降低功耗。这种模式适用于需要在较短时间内接收数据的应用场景。

        (4)PM2模式:低功耗模式2(Power Mode 2)。在PM2模式下,稳压器的数字内核关闭。32 MHz XOSC 和 16 MHz RCOSC 都不运行。32kHz RCOSC 或 32 kHz XOSC运行。复位、外部中断或睡眠定时器过期时系统将转到主动模式。该模式下cc2530,I/O 引脚保留在进入PM2 之前设置的I/O 模式和输出值,无线电部分处于关闭状态,同时大部分的功能也被禁用,以进一步减少功耗。这种模式适用于需要长时间处于待机状态,但偶尔需要唤醒进行一些处理的应用场景。

        (5)PM3模式:休眠模式(Power Mode 3)。在PM3模式下,获得最运行低功耗,稳压器的数字内核关闭,所有的振荡器都不运行,复位或外部中断时系统将转到主动模式。该模式下cc2530,I/O 引脚保留进入PM3 之前设置的I/O 模式和输出值,其他所有功能都被禁用,包括无线电部分。在这种模式下,cc2530需要外部触发来唤醒并重新启动其功能。这种模式适用于需要极低功耗且只偶尔需要进行通信的应用场景。

二、如何切换电源管理

        上一节,我们已经了解zigbee cc2530具有五中工作模式,各自拥有不同的特点,根据运行工况进行选择切换,实现低功耗方案设计。那么如何进行电源模式的切换管理,供电模式通过使用 SLEEPCMD 控制寄存器的 MODE 位和 PCON寄存器的IDLE 位来选择。

1、控制寄存器

首先,我们认识系统电源管理的两个寄存器:

2、切换电源模式与唤醒

        进行电源模式的切换管理很简单,分两步走:

        (1)首先,通过使用SLEEPCMD 控制寄存器的MODE 位选择系统电源模式;

        (2)使能SFR 寄存器的PCON.IDLE 位(设置为1),进入SLEEPCMD.MODE 所选的模式。

SLEEPCMD |= i;         // 设置系统睡眠模式, i=0,1,2,3
PCON = 0x01;         // 进入睡眠模式 ,通过中断打断
PCON = 0x00;         // 系统唤醒 ,通过中断打断

示例函数:

void SysPowerMode(char mode) 
 { 
     if((mode > 0)&&(mode < 4)) 
    {  
         SLEEPCMD |= mode;    //设置系统睡眠模式 
         PCON = 0x01;         //进入睡眠模式 ,通过中断唤醒
     } 
     else 
         PCON = 0x00;         //通过中断唤醒系统 
 }

三、案例讲解

1、中断唤醒

        初始设置系统为PM3电源模式,然后通过外部中断的方式,使得电源模式恢复(唤醒)主动模式。实验现象:LED1闪烁3次后进入睡眠状态,通过按下按键S1产生外部中断进行唤醒,重新进入主动模式,LED1闪烁3次后又进入睡眠状态。

//该代码基于作者的zigbee设备编写
//移植使用注意修改LED和按键的对应节点

#include <iocc2530.h>


#define LED1 P1_0

//  初始化LED1对应P1_0
void initLED1_P1_0()
{
    P1SEL &= ~0x01;
    P1DIR |= 0x01;
    P1_0 = 1;
}

//初始化一个按键KEY1中断
void initInterrupt()
{
    P0SEL &= 0xfd;  //中断口是P0_0
    P0DIR &= 0xfd;
    P0INP &=  0xfd;
    P2INP &=  0xdf;
    EA = 1;
    P0IE = 1;
    P0IEN |= 0x02;
    PICTL |= 0x01;
}

//延时函数
void delayms( unsigned int a )  //@16MHz
{
    unsigned char i, j;
    for( int s = 0; s < a; s++ )
    {
        i = 3;
        j = 148;
        do
        {
            while( --j );
        }
        while( --i );
    }
}
//  设置系统工作模式函数
void SysPowerMode( char mode )
{
    if( ( mode > 0 ) && ( mode < 4 ) )
    {
        SLEEPCMD |= mode;    //设置系统睡眠模式
        PCON = 0x01;         //进入睡眠模式 ,通过中断唤醒
    }
    else
    {
        PCON = 0x00;    //通过中断唤醒系统
    }
}

#pragma vector=P0INT_VECTOR
__interrupt void P0_INT( void )
{
    if( P0IFG & 0x02 )
    {
        SysPowerMode( 4 );
    }
    P0IFG = 0;
    P0IF = 0;
}

void main()
{
    char count = 0;
    initInterrupt();     //初始化一个按键中断
    initLED1_P1_0(); //  初始化一个LED
    while( 1 )
    {
       if( count > 10 )  {
         count = 0;
        }
        LED1 = ~LED1;
        if( ++count >= 6 )
        {
            count = 0;
            SysPowerMode( 3 ); //3次闪烁后进入睡眠状态PM3,等待按键S1中断唤醒
        }
        delayms( 800 );
    }
}


2、睡眠定时中断唤醒

        电源模式恢复(唤醒)为主动模式的另一种方法是定时中断唤醒,需要使用到睡眠定时器。我们先来了解睡眠定时器。这里简单只讲解睡眠定时器的比较模式用法,更详细讲解阅读参考链接(3)。

        2.1 睡眠定时器

         睡眠定时器用于设置系统进入和退出低功耗睡眠模式之间的周期。还用于当系统进入低功耗模式后,维持 MAC 定时器(T2)的定时。其特性如下:

        (1)长达 24 位定时计数器,运行在 32.768KHZ 的工作频率;

        (2)24 位的比较器具有中断和 DMA 触发功能在 PM2 低功耗模式下运行(PM3模式下振荡器全部被关闭,无法使用睡眠定时器唤醒)

        (3)定时器的当前值可以从 SFR 寄存器 ST2:ST1:ST0 中读取

        2.2  睡眠定时器寄存器

           睡眠定时器(T2)工作模式仍然有捕获和比较两种。通过如下寄存器控制。

        2.3 睡眠定时器比较模式

        睡眠定时器在复位之后立即启动,如果没有中断就继续运行。当定时器的值等于 24 位比较器的值,就发生一次定时器比较。通过写入寄存器 ST2:ST1:ST0 来设置比较值。

        寄存器 ST0、ST1、ST2分别对应着定时器的值等于 24 位比较器的低、中、高位,如何写值?定义一个32位的变量,通过移位的方式进行,如下:

//在给STx赋值是都是需要最后给ST0赋值,在读取STx值时都是要最先读取ST0的值

void Set_ST_Period(uint sec) 
{ 
   UINT32 sleepTimer = 0; //定义一个32位的变量
//注意:读取ST2:ST1:ST0的值,建议读取顺序ST0、ST1、ST2
   sleepTimer |= ST0;  //读取ST0的值,写入sleepTimer的[0:7]位
   sleepTimer |= (UINT32)ST1 <<  8; //读取ST1的值,写入sleepTimer的[8:15]位
   sleepTimer |= (UINT32)ST2 << 16; //读取ST2的值,写入sleepTimer的[16:24]位

   sleepTimer += ((UINT32)sec * (UINT32)32768); 
//当 STLOAD.LDRDY 是 1 写入 ST0 后,会发起加载最新的比较值,ST2、ST1 和 ST0 寄存器的最新的值。
//注意:写入ST2:ST1:ST0的值,写入顺序必须为ST2、ST1、ST0
   ST2 = (UINT8)(sleepTimer >> 16); //将sleepTimer的[16:24]位的值,写入ST2
   ST1 = (UINT8)(sleepTimer >> 8); //将sleepTimer的[8:15]位的值,写入ST1
   ST0 = (UINT8) sleepTimer; //将sleepTimer的[0:7]位的值,写入ST0
}

        2.4睡眠定时器唤醒

        通过设置定时器在特定时间内进行唤醒,重新进入工作模式,每次唤醒LED2闪烁3下。


 
#include <ioCC2530.h>
 
#define uint unsigned int
#define uchar unsigned char
 
#define UINT8 unsigned char
#define UINT16 unsigned int
#define UINT32 unsigned long
 
//定义控制LED灯的端口
 
#define LED1 P1_0             //定义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--);
}
/****************************
//初始化LED1对应P1_0
*****************************/
  
void initLED1_P1_0()
{
    P1SEL &= ~0x01;
    P1DIR |= 0x01;
    P1_0 = 1;
}
 
/**************************************************************** 
系统工作模式选择函数            
* 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 = 0X00; 
  ST0 = 0X00; 
  EA = 1;  //总开中断 
  STIE = 1; //睡眠定时器中断使能
  STIF = 0; //睡眠定时器中断标志清零
}
 
/********************************************************************* 
//设置睡眠时间 
*********************************************************************/ 
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;        
  initLED1_P1_0();        //调用初始化LED1函数    
  Init_SLEEP_TIMER();    //初始化SLEEPTIMER
  while(1)
  {
  
      for(i=0;i<6;i++) //闪烁3下
      {
        LED1=~LED1;
        Delayms(200);
      }
      Set_ST_Period(3); //重新进入睡眠模式
      SysPowerMode(2);   //进入PM2低频晶振模式
  
  }
}
//中断唤醒
#pragma vector = ST_VECTOR 
 __interrupt void ST_ISR(void) 
 { 
   STIF = 0;          //清标志位
   SysPowerMode(4);   //进入正常工作模式
 }

        main函数开始初始化LED和睡眠定时器,然后在while大循环里面先LED闪烁3次,然后调用睡眠周期设置设置3s,此时睡眠定时器开始计时,而main函数由于执行到设置系统进入PM2模式而休眠,当5s后触发休眠定时器中断,在中断中设置系统进入active模式。

参考链接:

(1)lesson4(Zigbee补充2)CC2530睡眠唤醒(详解)_cc2530休眠与唤醒-CSDN博客

(2)ZigBee基础实验(九)--定时器二_zigbee看门狗的唤醒定时器唤醒定时器彭20控制-CSDN博客

(3)ZigBee基础实验(八)--定时器一_zigbee定时器实验代码-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1917575.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32的Code、RO-data、RW-data、ZI-data和RAM以及flash的关系

对于刚接触stm32编程的同学来说&#xff0c;通常不知道如何选择合适型号的芯片来开发自己的项目&#xff0c;下面就分析一下多大的片内ram以及flash能符合我们项目的需求。 不知道大家有没有注意到&#xff0c;我们的项目每次编译完成后&#xff0c;都会出现这个Program Size&…

查看尝试登服务器ssh 访问ip地址

不指定时间查看尝试登录服务器的SSH访问IP地址 # CentOS/RHEL系统 zgrep "sshd" /var/log/secure-* | grep "Failed password" | awk {print $(NF-3)} | sort | uniq -c | sort -nr | head -n 10检查过去7天的日志尝试登录服务器的SSH访问IP地址 # CentOS…

浅谈谷歌浏览器axure扩展程序

Axure RP Extension for Chrome 是一款专门为Axure设计的谷歌浏览器扩展程序&#xff0c;它的主要作用是帮助用户在谷歌浏览器中无缝预览和测试由Axure RP创建的交互式原型。当您在Axure RP中构建原型并将其导出为HTML格式时&#xff0c;此扩展程序允许您直接在浏览器中打开这些…

自主升级,平稳过渡!麒麟信安保障长沙市智慧交通发展中心CentOS迁移无忧

长沙市智慧交通发展中心围绕综合交通运输协调体系的构建&#xff0c;实施交通运行的监测、预测和预警&#xff0c;面向公众提供交通信息服务&#xff0c;开展多种运输方式的调度协调&#xff0c;提供交通行政管理和应急处置的信息保障。 该中心目前数据日交换量超2亿条&#x…

threeJS 为模型增加精灵图

前言 之前使用css3DRender创建图片弹框&#xff0c;在旋转模型到背面时&#xff0c;弹框也背对模型&#xff0c;这与UI要求的效果有出入。考虑将css3DRender换成css2Drender,但是可能是模型的问题&#xff0c;将弹框加入到模型的子集&#xff0c;旋转模型时弹框发生比较明显的…

博物馆环境监测系统——文物的绿色守护者

博物馆环境监测系统是现代博物馆不可或缺的一项技术装备。该系统可以实时监测温度、湿度等因素&#xff0c;旨在保持文物所处环境的稳定性&#xff0c;确保馆内的文物得到最佳的保护和展示条件。尤其是在梅雨季节&#xff0c;博物馆环境监测系统在博物馆的工作中发挥着至关重要…

ENSP-防火墙小实验

实验总要求 我的拓扑图&#xff1a; 具体配置 1.交换机 vlan: # sysname Lswl # vlan batch 2 to 3 # 接口&#xff1a; [LSWl]int e 0/0/2 [LSWl-Ethernet0/0/2ldisplay this # interface Ethernet0/0/2port link-type accessport default vlan 2 # return [LsWl-Ethernet0…

nohup java -jar 启动java项目

hi&#xff0c;我是程序员王也&#xff0c;一个资深Java开发工程师&#xff0c;平时十分热衷于技术副业变现和各种搞钱项目的程序员~&#xff0c;如果你也是&#xff0c;可以一起交流交流。 今天我们聊聊linux中运行java jar包的问题~ 理解nohup命令 nohup命令的基本概念 noh…

对于一些未来规划的想法

文章目录 一、关于如何加技能点二、关于大厂、中厂、小厂三、大语言模型、元宇宙、VR、虚拟货币四、关于嵌入式的技术路线五、其他 一、关于如何加技能点 首先进入课题组&#xff0c;务必先把眼前的东西学好&#xff0c;做好当下的事情。 也是关于个人的发展规划的话&#xff…

强强联手促发展,奋楫共进启新篇 | 中创算力与中国移动签订战略合作协议

在数字化浪潮席卷全球的今天&#xff0c;河南中创算力信息科技有限公司与中国移动通信集团河南有限公司郑州分公司携手并进&#xff0c;共同开启了数字化转型的新篇章。 2024年7月10日上午&#xff0c;双方在中国移动郑州分公司隆重举行了战略合作协议的签约仪式。双方将在5G技…

炎热夏季环境下的文物保护:挑战与策略

随着夏季的到来&#xff0c;高温和强烈的日照给文物保护带来了新的挑战。在这个季节&#xff0c;文物不仅面临着物理和化学损害的风险&#xff0c;还可能因为管理不善而遭受人为破坏。因此&#xff0c;探讨如何在夏季炎热天气中做好文物保护工作具有重要意义。 夏季炎热天气对文…

海外电商SAAS平台对接流程

海外电商SAAS平台对接流程通常包括以下几个步骤&#xff0c;需要说明的是对接这些平台存在一定的风险&#xff0c;为了降低这些风险&#xff0c;建议您选择信誉良好的平台&#xff0c;并做好安全防护措施。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xf…

FastAPI 学习之路(三十九)对开发接口进行测试

概况 对于开发好的接口需要进行测试之后才能发布。当我们在开发的时候&#xff0c;没有提前测试&#xff0c;我们也要对我们自己的接口进行测试&#xff0c;那么FastApi自身也带有针对开发的接口进行测试的功能。我们看下FastApi官方给我们提供了什么样的支持。 接口还是基于…

景点门票销售管理系统(数据库课设)

1.课设要求描述 ●实现票价管理&#xff0c;应分老年、小孩、成人、团体等&#xff1b; ●实现营业员管理&#xff1b; 实现门票销售、退票管理&#xff1b; ● 创建存储过程&#xff0c;统计指定日期的门票销售情况&#xff1b; ●创建存储过程&#xff0c;统计指定月份…

PHP智慧社区小区物业管理系统小程序源码

让生活更便捷&#xff0c;社区更和谐✨ &#x1f3e1;【开篇&#xff1a;智慧生活&#xff0c;从社区开始】&#x1f3e1; 在快节奏的现代生活中&#xff0c;寻找一份便捷与舒适成为了我们共同的追求。小区&#xff0c;作为我们日常生活的温馨港湾&#xff0c;其管理水平和服…

小红书的大模型有点「怂」

大模型发展至今&#xff0c;各个公司都根据自己的业务发布了各自的大模型。而小红书作为种草类产品的代表&#xff0c;自研的大模型一直引而不发&#xff0c;还在内测阶段。 AI以及自研大模型的持续火热&#xff0c;让以原创内容为主导的小红书坐不住了。 近期&#xff0c;据多…

Day66 代码随想录打卡|回溯算法篇---分割回文串

题目&#xff08;leecode T131&#xff09;&#xff1a; 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串。返回 s 所有可能的分割方案。 方法&#xff1a;本题是一个分割回文串的问题&#xff0c;是回溯算法的另一类问题。 针对一个字…

oak相机使用oak官网方式标定

目录 一、depthai ROS驱动 一、depthai ROS驱动 &#xff08;1&#xff09;驱动下载地址&#xff1a;2. C 开发快速上手 — DepthAI Docs 0.3.0.0 documentation sudo apt install ./depthai_2.17.1_arm64.deb //运行 Python3 utilities/cam_test.py -mres 400 -cams rgb,m …

【2】kettle使用的小细节——输出数据分发和复制

在进行地铁数据清洗时&#xff0c;遇到3组线路&#xff1a; 出现的问题&#xff1a;程序运行到 增加序列 组件还有396条数据记录&#xff0c;但是在排序记录中只有 132条数据&#xff0c;即对3条线路进行了分发&#xff0c;各发送了132条数据。 断开这三条连接&#xff0c;重新…

对智能的研究正在悄悄地诱发复杂取代科学

随着智能人工智能的发展&#xff0c;传统科学研究方法可能面临新的挑战或者被扩展。人工智能的发展带来了大数据分析、机器学习、深度学习等新的工具和方法&#xff0c;这些方法在处理复杂系统和大规模数据方面表现出色&#xff0c;使得科学研究变得更加多样化和复杂化。对智能…