在德州仪器的站点: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化学工业出版社

zigbee 学习笔记的更多相关文章

  1. [XBee] ZigBee学习笔记

    转自:http://blog.csdn.net/wanghanjiett/article/details/6931867 几个重要概念: node(节点): 在zigbee堆栈中最多有三种节点:Coo ...

  2. 转 zigbee学习笔记---Channel、PANID、发射功率及其它参数

    现对z-stack里几个网络参数的设置以及如何获取总结一下.信道配置:Zigbee在3个频段定义了27个物理信道:868MHz频段中定义了1个20Kb/s信道,915MHz频段中定义了10个40Kb/ ...

  3. 物联网学习笔记三:物联网网关协议比较:MQTT 和 Modbus

    物联网学习笔记三:物联网网关协议比较:MQTT 和 Modbus 物联网 (IoT) 不只是新技术,还是与旧技术的集成,其关键在于通信.可用的通信方法各不相同,但是,各种不同的协议在将海量“事物”连接 ...

  4. JavaEE精英进阶课学习笔记《博学谷》

    JavaEE精英进阶课学习笔记<博学谷> 第1章 亿可控系统分析与设计 学习目标 了解物联网应用领域及发展现状 能够说出亿可控的核心功能 能够画出亿可控的系统架构图 能够完成亿可控环境的准 ...

  5. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  6. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  7. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  8. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  9. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

随机推荐

  1. JS判断客户端是否是iOS或者Android手机移动端

    var u = navigator.userAgent; var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > - ...

  2. Request对象与Response对象

    1.Request对象 Request对象是来获取请求消息的,是由服务器(Tomcat)创建的. Request对象继承体系结构: ServletRequest        --    接口     ...

  3. Django web框架之权限管理一

    1. 需求分析: 准备:创建独立app, rbac #权限管理模块/组件 app01 #应用 分配权限,URL 2. 数据库设计 2.1 设计思路 第一版: 权限表: ID url title is_ ...

  4. jenkins上展示html报告【转载】

    转至博客:上海-悠悠 前言 在jenkins上展示html的报告,需要添加一个HTML Publisher plugin插件,把生成的html报告放到指定文件夹,这样就能用jenkins去读出指定文件 ...

  5. Decode Ways——动态规划

    A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' - ...

  6. 小米路由器3-R3 刷固件

    1.刷机前的路由器升级准备 1-1.首先进入路由器原声后台:miwifi.com 1-2.在右上角,点击系统升级.在系统版本下边选择手动升级,选择资源包里的:“miwifi_r3_all_55ac7_ ...

  7. LoadRunner脚本回放日志中的Warning信息

    关注LoadRunner脚本回放日志中的Warning信息   最近在与大家的讨论中发现了LoadRunner的很多问题,出于解决问题的出发点,我也就相关自己不理解的问题在Google中搜索了一番,并 ...

  8. ELK系列--logstash无法启动

    1.logstash无法启动,提示bind address   原因:   1)配置目录下存在多个配置文件,而logstash会加载所有conf格式的文件   解决方案:删除不必要的,保留一个conf ...

  9. android ListView 在初始化时多次调用getView()原因分析

    今天在做一个功能:在初始化ListView时,把第一行背景置为黄色,同时保存第一行对象,用于在点击其他行时将该行重新置为白色. if(position==0){ convertView.setBack ...

  10. 2. 创建一个简单的Maven项目

    ☞ 创建项目 选定一个目录,如E:\workspace\maven,新建的项目将放在这个目录. 运行CMD,切换到该目录. 执行mvn archetype:generate直到输出"Choo ...