在德州仪器的站点:http://www.ti.com.cn/tool/cn/z-stack上下载安装zigbee2007协议栈版,我的是ZStack-CC2530-2.3.0-1.4.0。

以下演示一个简单的用zigbee通信的样例:

完毕这个样例须要两个zigbee的模块,一个用作协调器(Coordinator)(起建立zigbee网络和与上位机通信的作用)一个用作终端设备(Enddevice)(起採集数据。增加建立的zigbee网络),这里须要实现的功能是先由协调器建立网络,终端设备增加网络。然后终端设备发送“QSS”给协调器,协调器进行推断,假设接收到QSS,那么闪烁LED2,否则点亮LED2。

删除在App目录中的几个文件,仅仅剩下OSAL_SampleApp.c。加入三个文件Coordinator.c,Coordinator.h,Enddevice.c。

须要在OSAL_SampleApp.c中加入#include "Coordinator.h"。

编译Coordinator时须要在workspace以下的下拉表中选择CoordinatorEB,然后右键单击Enddevice.c,在弹出的对话框中选择Exclude from build,将终端设备的程序排除在编译范围内,相同在编译Enddevice的程序时也须要将Coordinator.c排除在编译范围内。

ZigBee网络传输数据流程:

1、终端节点发送信标请求;

2、协调器已经建立ZigBee无线网络。在ZigBee无线网络中。协调器的地址必然是0x0000,。

3、终端节点发送增加网络请求;

4、协调器对终端节点的增加网络请求作出应答

5、终端节点接收到协调器的应答后,发送数据请求(Data Request)。请求协调器分配网络地址。

6、协调器对终端节点的数据请求作出应答

7、协调器将分配的网络地址发送给终端节点

之后终端节点就使用分配的网络地址和协调器通信了。

OSAL(Operating System Abstraction Layer)操作系统抽象层

每一个应用程序对象执行在不同的port上。因此port的作用就是区分不同的应用程序对象。能够把一个应用程序对象看成为一个任务,因此,须要一个机制来实现任务的切换、同步和相互排斥。这就是OSAL产生的根源。

它的主要功能有:

任务注冊、初始化和启动;

任务间的同步、相互排斥;

中断处理。

储存器分配和管理。

在Coordinator.c中GenericApp_Init是任务的初始化函数。GenericApp_ProcessEvent负责处理传递给此任务的事件,推断事件类型,然后运行对应的事件处理函数。

OSAL负责调度整个任务的执行,假设有事件发生了,则会调用对应的事件处理函数进行处理。

那么事件和任务的事件处理函数是怎样联系起来的呢?

ZigBee的做法是:建立一个事件表,保存各个任务相应的事件,建立还有一个函数表,保存各个任务事件处理函数的地址,然后将这两张表建立某种相应的关系,当某事发生时则查找函数表找到相应的事件处理函数就可以。

Zigbee协议中三个变量最重要:

Uint8 tasksCnt-保存任务的总数;

Uint16 *tackEvents指向事件表的首地址。

pTaskEventHandlerFn taskArr[]-数组中的每一项都是一个函数指针,指向事件处理函数;

Typedef unsigned short (*pTaskEventHandlerFn )(unsigned char task_id,unsigned short event);

总结一下OSAL的工作原理:

通过tasksEvents指针訪问事件表的每一项,假设有事件发生。则查找函数表找到事件处理函数进行处理,处理完后。继续訪问事件表,查看是否有事件发生。无限循环。

能够说OSAL是基于事件驱动的轮询式操作系统。

OSAL的消息队列:

将事件和数据封装成一个消息,将消息发送到消息队列,然后在事件处理函数中就能够使用osal_msg_receive,从消息队列中得到该消息。OSAL维护了一个消息队列。每一个消息都会被放到这个消息队列中去。当任务接收到事件后,能够从消息队列中获取属于自己的消息,然后调用消息处理函数进行对应的处理就可以。

OSAL加入新任务:

OSAL_SampleApp.c中,能够找到数组tasksArr[]和函数osalInitasks。tasksArr[]数组中存放了全部任务的事件处理函数的地址。osalInitasks是OSAL的任务初始化函数。全部任务的初始化工作都在这里完毕,而且自己主动给每一个任务分配一个ID。

因此要加入一个新任务,仅仅须要编写两个函数:

新任务的初始化函数。

新任务的事件处理函数。

Coordinator.h

/*******************************

这里定义一些关于zigbee的设备描叙符的宏

**************************************/

#ifndef COORDINATOR_H

#define COORDINATOR_H

#include "ZComDef.h"//zigbee common definition

#define GENERICAPP_ENDPOINT         10  //port

#define GENERICAPP_PROFID           0x0F04

#define GENERICAPP_DEVICEID         0x0001

#define GENERICAPP_DEVICE_VERSION   0

#define GENERICAPP_FLAGS            0

#define GENERICAPP_MAX_CLUSTERS     1

#define GENERICAPP_CLUSTERID        1

extern void GenericApp_Init(byte task_id);

extern UINT16 GenericApp_ProcessEvent(byte task_id,UINT16 events);

#endif

/*********************************************************************/

Coordinator.c

/*********************************************************************

* INCLUDES

*/

#include "OSAL.h"

#include "ZGlobals.h"

#include "AF.h"

#include "aps_groups.h"

#include "ZDApp.h"

#include "Coordinator.h"//这是新加的

#include "OnBoard.h"

/* HAL *///硬件抽象层

#include "hal_lcd.h"

#include "hal_led.h"

#include "hal_key.h"

#include "MT_UART.h"

#include "MT_APP.h"

#include "MT.h"

/*********************************************************************

* GLOBAL VARIABLES

*/

// This list should be filled with Application specific Cluster IDs.

const cId_t GENERICAPP_ClusterList[GENERICAPP_MAX_CLUSTERS] =

{

GENERICAPP_CLUSTERID

};

const SimpleDescriptionFormat_t GenericApp_SimpleDesc =

{

GENERICAPP_ENDPOINT,              //  int Endpoint;

GENERICAPP_PROFID,                //  uint16 AppProfId[2];

GENERICAPP_DEVICEID,              //  uint16 AppDeviceId[2];

GENERICAPP_DEVICE_VERSION,        //  int   AppDevVer:4;

GENERICAPP_FLAGS,                 //  int   AppFlags:4;

GENERICAPP_MAX_CLUSTERS,          //  uint8  AppNumInClusters;

(cId_t *)GENERICAPP_ClusterList,  //  uint8 *pAppInClusterList;

0,                                //  uint8  AppNumInClusters;

(cId_t *)NULL                    //  uint8 *pAppInClusterList;

};//简单的设备节点描叙符

endPointDesc_t GenericApp_epDesc;//定义一个节点描叙符

byte GenericApp_TaskID; //任务优先级

byte GenericApp_TransID; //数据发送序列号

typedef struct

{

byte endPoint;

byte *task_id;

SimpleDescriptionFormat_t *simpleDesc;

afNetworkLatencyReq_t latenncyReq;

}ndPointDesc_t;

void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );//消息处理函数

void GenericApp_SendTheMessage( void );//数据发送函数

static void rxCB(uint8 port,uint8 event);

//任务初始化函数

void GenericApp_Init(byte task_id )

{

halUARTCfg_t uartConfig;

GenericApp_TaskID = task_id;//初始化优先级

GenericApp_TransID = 0;//初始化序列号

// Fill out the endpoint description.//初始化设备节点描叙符

GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;

GenericApp_epDesc.task_id = &GenericApp_TaskID;

GenericApp_epDesc.simpleDesc  =

(SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;

GenericApp_epDesc.latencyReq = noLatencyReqs;

// Register the endpoint description with the AF

//注冊设备节点描叙符,仅仅有注冊之后才干够使用OSAL的服务

afRegister( &GenericApp_epDesc );

}

//消息处理函数,完毕对接收数据的处理,固定格式

UINT16 GenericApp_ProcessEvent( uint8 task_id, uint16 events )

{

afIncomingMSGPacket_t *MSGpkt;//定义一个接收消息结构体的指针MSGpkt

if ( events & SYS_EVENT_MSG )

{

MSGpkt=(afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );

while ( MSGpkt )

{

switch ( MSGpkt->hdr.event )//对消息进行推断

{

// Received when a messages is received (OTA) for this endpoint

case AF_INCOMING_MSG_CMD://无线数据

GenericApp_MessageMSGCB( MSGpkt );//对数据进行处理

break;

default:

break;

}

// Release the memory释放内存

osal_msg_deallocate( (uint8 *)MSGpkt );

// Next - if one is available再次从消息队列中接收消息

MSGpkt=(afIncomingMSGPacket_t*)osal_msg_receive( GenericApp_TaskID );

}

// return unprocessed events

return (events ^ SYS_EVENT_MSG);

}

return 0;

}

//数据处理函数

void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )

{

unsigned char buffer[4] = " ";

switch ( pkt->clusterId )

{

case GENERICAPP_CLUSTERID:

osal_memcpy(buffer,pkt->cmd.Data,3);//将接收到的数据复制到buffer区

if((buffer[0] == 'Q') || (buffer[1] == 'S') || (buffer[2] == 'S'))

{

HalLedBlink(HAL_LED_2,0,50,500);//闪灯

}

else

{

HalLedSet(HAL_LED_2,HAL_LED_MODE_ON);//点灯

}

break;

}

}

Enddevice.c

/*********************************************************************

* INCLUDES

*/

#include "OSAL.h"

#include "ZGlobals.h"

#include "AF.h"

#include "aps_groups.h"

#include "ZDApp.h"

#include "Coordinator.h"//新增协调器头文件

#include "OnBoard.h"

/* HAL *///硬件抽象层

#include "hal_lcd.h"

#include "hal_led.h"

#include "hal_key.h"

#include "MT_UART.h"

#include "MT_APP.h"

#include "MT.h"

// This list should be filled with Application specific Cluster IDs.

const cId_t GENERICAPP_ClusterList[GENERICAPP_MAX_CLUSTERS] =

{

GENERICAPP_CLUSTERID

};

const SimpleDescriptionFormat_t GenericApp_SimpleDesc =

{

GENERICAPP_ENDPOINT,              //  int Endpoint;

GENERICAPP_PROFID,                //  uint16 AppProfId[2];

GENERICAPP_DEVICEID,              //  uint16 AppDeviceId[2];

GENERICAPP_DEVICE_VERSION,        //  int   AppDevVer:4;

GENERICAPP_FLAGS,                 //  int   AppFlags:4;

0,

(cId_t *)NULL,                   //  uint8 *pAppInClusterList;

GENERICAPP_MAX_CLUSTERS,          //  uint8  AppNumInClusters;

(cId_t *)GENERICAPP_ClusterList  //  uint8 *pAppInClusterList;

};//简单的设备节点描叙符

endPointDesc_t GenericApp_epDesc;//节点描叙符

byte GenericApp_TaskID; //任务优先级

byte GenericApp_TransID; //数据发送序列号。在协议栈中每发送一个数据包。

//该发送序列号加1,能够用来在数据接收端查看数据包的序列号来计算丢包率

devStates_t GenericApp_NwkState;//记录该设备的状态

void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );//消息处理函数

void GenericApp_SendTheMessage( void );//数据发送函数

void GenericApp_Init(byte task_id )//任务初始化函数

{

GenericApp_TaskID    = task_id;//初始化了任务优先级(任务优先级由协议栈的操作系统OSAL分配)

GenericApp_NwkState  = DEV_INIT;//将设备状态初始化为DEV_INT,表示该节点没有连接到ZigBee网络

GenericApp_TransID   = 0;//将发送数据包的序列号初始化为0,

// Fill out the endpoint description.对节点描叙符进行的初始化

GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;

GenericApp_epDesc.task_id = &GenericApp_TaskID;

GenericApp_epDesc.simpleDesc  =

(SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;

GenericApp_epDesc.latencyReq = noLatencyReqs;

// Register the endpoint description with the AF,注冊节点描叙符

afRegister( &GenericApp_epDesc );

}

//消息处理函数,完毕接收数据的处理

uint16 GenericApp_ProcessEvent( uint8 task_id, uint16 events )

{

afIncomingMSGPacket_t *MSGpkt;//定义一个指向消息结构的指针

if ( events & SYS_EVENT_MSG )

{

MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );

while ( MSGpkt )

{

switch ( MSGpkt->hdr.event )//推断消息类型

{

// Received when a messages is received (OTA) for this endpoint

case ZDO_STATE_CHANGE:

GenericApp_NwkState = (devStates_t)(MSGpkt->hdr.status);//读取设备节点类型

if(GenericApp_NwkState == DEV_END_DEVICE)

{

GenericApp_SendTheMessage();//发送无线数据

}

break;

default:

break;

}

// Release the memory

osal_msg_deallocate( (uint8 *)MSGpkt );

// Next - if one is available

MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );

}

// return unprocessed events

return (events ^ SYS_EVENT_MSG);

}

return 0;

}

//发送消息函数

void GenericApp_SendTheMessage(void )

{

unsigned char theMessageData[4] = "QSS";

afAddrType_t my_DstAddr;//目标地址

my_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;//将发送数据模式设置为单播

my_DstAddr.endPoint = GENERICAPP_ENDPOINT;//初始化port

my_DstAddr.addr.shortAddr = 0x00;//协调器的网络地址是固定的,为0x00

AF_DataRequest(&my_DstAddr,&GenericApp_epDesc,//调用AF_DataRequest函数发送数据

GENERICAPP_CLUSTERID,

3,

theMessageData,

&GenericApp_TransID,

AF_DISCV_ROUTE,

AF_DEFAULT_RADIUS);

HalLedBlink(HAL_LED_2,0,50,500);//闪灯

}

參考书目:

王小强 欧阳骏 黄宁淋编著《Zigbee无线传感器网络设计与实现》2012化学工业出版社

最新文章

  1. web前端基础篇⑨
  2. 使用 VisualCode + iTerm2 提交github的Pull Request
  3. javascript的replace+正则 实现ES6的字符串模版
  4. Mac 下 命令收藏
  5. Linux复制指定目录及子目录下特定类型的文件
  6. 利用二维矩阵求spanning tree
  7. 框架技术--S2SH框架整合(spring部分)No 3--声明式事务
  8. Apache Spark2.0正式发布
  9. FAQ:注册表_键值类型
  10. 找最大重复次数的数和重复次数(C++ Pair)
  11. Java第九周学习总结
  12. WPF 圆角输入框
  13. Docker最全教程——从理论到实战(八)
  14. 手机端上点击input框软键盘出现时把input框不被覆盖,显示在屏幕中间(转)
  15. SQL IN查询优化
  16. Redisson实现分布式锁(一)
  17. webpack 图片没打包成功
  18. JGit与远程仓库链接使用的两种验证方式(ssh和https)
  19. mac os下提高android studio运行速度终极方法
  20. GoLang中 json、map、struct 之间的相互转化

热门文章

  1. eclipse out of memory
  2. Go语言标准包之用io包模拟curl
  3. LoadRunner11破解方法
  4. nginxhttp请求限制丶tcp会话限制和下载速度限制
  5. CentOS7安装和配置vsftpd
  6. php打开错误日志
  7. 使用CSS让元素尺寸缩小时保持宽高比例一致
  8. 动若脱兔:深入浅出angr--初步理解符号执行以及angr架构
  9. 04、Unity_声音管理器
  10. Centos7搭建SVN Server手记