ZigBee——在CC2530的ZStack中添加定时任务
在使用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的使用有更加深入的理解。