ZigBee——在CC2530的ZStack中添加定时任务

  • Post author:
  • Post category:其他


在使用CC2530芯片进行ZigBee协议的开发时,我们往往使用TI公司提供的带有ZigBee协议栈的ZStack工程,接下来以其中的SampleApp为例,向其中添加自己需要的定时任务并设置周期和处理流程。

首先,我们以SampleApp中的默认定时任务

SAMPLEAPP_SEND_PERIODIC_MSG_EVT

作为参考,通过IAR软件找到其在SampleApp.h头文件中被定义,并在SampleApp.c中多次被使用,由于该文件就是用户程序运行的主要区域,因此着重分析其在这两个文件中的分布及起到的作用。


以下是对该任务的分析:

// Send Message Timeout

#define SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT 1000  // Every 1 seconds

// Application Events (OSAL) – These are bit weighted definitions.(**注意二进制表达**)

#define SAMPLEAPP_SEND_PERIODIC_MSG_EVT 0x0001

在SampleApp.c中的SampleApp_ProcessEvent函数中,第一次用到了该任务。此函数用于处理系统所产生的一些事件和消息。在系统事件ZDO_STATE_CHANGE(网络状态)的处理支路中,使用osal_start_timerEx函数开启了此定时器,具体代码如下:

osal_start_timerEx(SampleApp_TaskID,

SAMPLEAPP_SEND_PERIODIC_MSG_EVT,

SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT);

代码中使用了SampleApp的TaskID,表明该定时器所产生的消息将交由SampleApp中专门负责处理消息的回调函数SampleApp_ProcessEvent进行处理,产生消息时将会传入SAMPLEAPP_SEND_PERIODIC_MSG_EVT的事件信息,并将该定时器超时时间设置为SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT所定义的值。

随后,在SampleApp_ProcessEvent函数中的events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT支路对此任务设置的消息进行处理,从处理的方式可以看到进行了位与运算,即判断events中该事件ID所在的位是否与设定值一致,若一致则进行处理,因此消息ID必须放置在二进制的“bit”中。

在事件处理结束后,通过return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT)返回了处理的结果,即清除了该事件所在的位,并保留其它位留待后续处理。


接下来我们添加两个自定义的定时任务:

#define SAMPLEAPP_SEND_INFO_MSG_EVT  0x0002

#define SAMPLEAPP_LED_RUN_EVT                0x0004

#define SAMPLEAPP_SEND_INFO_MSG_TIMEOUT   10000 // Every 10 seconds

#define SAMPLEAPP_LED_RUN_TIMEOUT                 500     // Every 0.5 seconds

分别用于状态信息的发送和LED运行状态的指示。

首先,在SampleApp.h中添加上述宏定义,随后,在SampleApp.c中的SampleApp_Init函数中添加以下初始化定时器的相关函数:

osal_start_timerEx(SampleApp_TaskID,

SAMPLEAPP_SEND_INFO_MSG_EVT,

SAMPLEAPP_SEND_INFO_MSG_TIMEOUT);

osal_start_timerEx(SampleApp_TaskID,

SAMPLEAPP_LED_RUN_EVT,

SAMPLEAPP_LED_RUN_TIMEOUT);

最后,参考已有的定时器用法,在SampleApp_ProcessEvent函数中添加对应的事件处理流程:

if (events & SAMPLEAPP_SEND_INFO_MSG_EVT)
  {
    // Setup to send message again in normal info
    osal_start_timerEx(SampleApp_TaskID, SAMPLEAPP_SEND_INFO_MSG_EVT,
        (SAMPLEAPP_SEND_INFO_MSG_TIMEOUT));
    
    //do something

    // return unprocessed events 返回未处理的事件
    return (events ^ SAMPLEAPP_SEND_INFO_MSG_EVT);
  }
  if (events & SAMPLEAPP_LED_RUN_EVT)
  {
    // Setup to led event again
    osal_start_timerEx(SampleApp_TaskID, SAMPLEAPP_LED_RUN_EVT,
        (SAMPLEAPP_LED_RUN_TIMEOUT));

    //do something

    // return unprocessed events 返回未处理的事件
    return (events ^ SAMPLEAPP_LED_RUN_EVT);
  }

值得注意的是,由于OSAL中采用按位设置标志位的方式进行事件的处理,因此设置事件时就需要留意事件ID的选取,必须设置为2的整数次幂,如0x01、0x02、0x04、0x08等,不可设置为0x03或其它非2的整数次幂的值,否则将会导致多个事件同时命中。相对地,我们也可以利用这一特性,通过设置一个全为“1”的事件ID来响应发生的所有事件或使所有事件的处理流程对此做出响应。

总之,OSAL系统为我们所编写的用户程序提供了一个完善而稳定的运行环境,对于它的使用,TI官方所给的示例及注释已十分完备,通过阅读代码,对用户程序进行修改也能够帮助我们对ZigBee和CC2530的使用有更加深入的理解。



版权声明:本文为weixin_43593122原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。