// 发送数据函数
status = AF_DataRequest(&dstAddr, &sapi_epDesc, commandId, len, pData, &handle, txOptions, radius); // 不成功重发
if (status != afStatus_SUCCESS) {
SAPI_SendCback( SAPICB_DATA_CNF, status, handle ); } }
传感器要定期的触发事件,发送数据。相关函数代码如下:
/******************************************************************************
* @fn my_StartReporting
*
* @brief Starts the process to periodically report sensor readings *
* @param *
* @return none
*/
void myApp_StartReporting( void ) {
osal_start_timerEx(sapi_TaskID,MY_REPORT_TEMP_EVT,myTempReportPeriod );
osal_start_timerEx(sapi_TaskID,MY_REPORT_BATT_EVT,myBatteryCheckPeriod );
HalLedSet( HAL_LED_1, HAL_LED_MODE_ON ); }
以上就是我在本次实验中的主要代码工作。其开发工作主要是在APP层中。当然想要明白其原理,还要对ZigBee协议栈有进一步的了解。
4.3 ZigBee协议和ZStack分析
4.3.1 ZigBee协议和ZStack简介
ZigBee协议是由ZigBee联盟(一个由众多IT企业组成的)制定和管理的一种短距离低速率的无线网络协议。此协议得到了广泛的支持,只要符合此协议的设备都能够互相联网。Zigbee的基础是IEEE 802.15.但IEEE仅处理低级MAC层和物理层协议,因此Zigbee联盟扩展了IEEE,对其网络层协议和API进行了标准化。ZIgBee协议现在比较流行的版本是ZigBee2007。ZigBee协议非常复杂,ZigBee 2007的协议规范,翻译为中文就有800页,这还不包括IEEE规范部分。协议规范对功能做出了要求,有必须的,和可以具备的,在这里不再详细区分。本实验符合的标准时ZigBee2007。其协议的框图如图7所示:
图7:ZigBee协议结构框图
ZStack是由TI公司开发的一个符合ZigBee协议的协议栈。它是一款可以免费获取,半开源的商业协议栈。它是我们用来开发基于CC2530芯片的ZigBee设备所必要的软件环境。为了开发ZigBee设备,ZStack也引入了OSAL等内容。
本段的以下内容将会结合ZStack,对ZigBee协议进行较为详细的分析。需要指出的是由于ZStack是一款半开源产品。许多关键代码TI公司并没有给出。在这些部分我将根据ZigBee协议给出算法分析和部分实现。当然可以预见的是,这些算法的思路和代码的质量肯定没有TI公司的好。
4.3.2 OSAL原理分析和实现
在ZigBee2007中引入了实时操作系统,在ZStack中就是由OSAL(Operating System (OS) Abstraction Layer)实现的。OSAL可以符合ZigBee协议且满足实际开发的要求。下面我就以OSAL为例来进行分析。
说明:从图5所表示的ZigBee协议中并没有直接表现出有操作系统层。但是如果要按照ZigBee协议去开发一个协议栈,就必须要引入类似操作系统的功能,以实现任务之间的切换、同步和互斥。可以说引入操作系统是实现ZigBee协议的必要手段。而TI公司给出的方案就是引入OSAL(Operating System (OS) Abstraction Layer)。
(1) 运行机理简介
OSAL是一个事件驱动的,轮询方式查询的操作系统。在上节中我们已经知道了系统首先运行main(),完成各种初始化工作后就调用了osal_start_system()。在这个函数中有个无限循环,不停地查看事件表(tasksEvents[idx]),如果有事件发生就调用相应的事件处理函数(函数指针储存在tasksArr[idx])。
(2) OSAL层文件和重要函数简介
OSAL层文件如图6所示:
图6:OSAL层文件目录
OSAL.c文件是OSAL的核心,算是OSAL的内核了吧。主要是实现初始化,任务管理,消息机制等功能。
OSAL的灵魂函数void osal_start_system( void )上节已经介绍过。这里再详细的分析下。(发现TI公司的原版注释已经相当明了了,我就不再画蛇添足加注释了)
/*********************************************************************
* @fn osal_start_system *
* @brief
*
* This function is the main loop function of the task system. It * will look through all task events and call the task_event_processor()
* function for the task with the event. If there are no events (for
* all tasks), this function puts the processor into Sleep. * This Function doesn't return. *
* @param void *
* @return none */
void osal_start_system( void ) {
#if !defined ( ZBIT ) && !defined ( UBIT ) for(;;) // Forever Loop #endif {
uint8 idx = 0;
osalTimeUpdate();
Hal_ProcessPoll(); // This replaces MT_SerialPoll() and osal_check_timer().
do {
if (tasksEvents[idx]) // Task is highest priority that is ready.
{
break; }
} while (++idx < tasksCnt);
if (idx < tasksCnt) {
uint16 events;
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState); events = tasksEvents[idx];
tasksEvents[idx] = 0; // Clear the Events for this task. HAL_EXIT_CRITICAL_SECTION(intState);
events = (tasksArr[idx])( idx, events );
HAL_ENTER_CRITICAL_SECTION(intState); tasksEvents[idx] |= events; // Add back unprocessed events to the current task.
HAL_EXIT_CRITICAL_SECTION(intState); }
#if defined( POWER_SAVING )
else // Complete pass through all task events with no activity? {
osal_pwrmgr_powerconserve(); // Put the processor/system into sleep
} #endif } }
下面给出了些主要的API函数的定义。 消息头的结构体定义如下:
typedef struct {
void *next; uint16 len;
uint8 dest_id; } osal_msg_hdr_t;
事件头的结构体定义如下:
typedef struct {
uint8 event; uint8 status; } osal_event_hdr_t;
/*********************************************************************
* FUNCTIONS */
消息管理函数如下:
/*** Message Management ***/
/*
* Task Message Allocation */
extern uint8 * osal_msg_allocate(uint16 len );