zigbee学习笔记3-通信例程之GenericApp

合集下载

ZigBee学习笔记一端口号命令簇

ZigBee学习笔记一端口号命令簇

主要解决的问题如何使用不同的命令号发送不同长度的的数据第一部分一些概念如图所示是一个节点设备上的端口号(endpoint)它是一个8位的字段,描述一个射频端所支持的不同应用。

端口0x00:用于寻址设备配置文件,这是每个ZigBee设备必须使用的端口;端点0xff:用于寻址所有活动端口;端口0xf1~0xfe:保留;端口0x01~0xf0:共支持240个应用,即一个物理信道最多支持240个虚拟链路。

图中还用另一个概念簇簇(cluster)多个属性的汇集形成了簇,簇是属性的集合,每个簇也拥有一个唯一的ID。

譬如,FS_ZStack\SimpleSwitch.cconst cId_t zb_OutCmdList[NUM_OUT_CMD_SWITCH]= //输出簇列表{TOGGLE_LIGHT_CMD_ID //簇ID, 1};FS_Zstack\SimpleController.cconst cId_tzb_InCmdList[NUM_IN_CMD_CONTROLLER] = //输入簇列表{TOGGLE_LIGHT_CMD_ID //簇ID, 1};cId_t=uint16,端口的描述第一步,定义一个结构体用来描述端口endPointDesc_t GenericApp_epDesc; //结构体类型变量第二步初始化端口参数要完整的描述一个端口,分为两部分(1)endPointDesc_t端口描述(2)简单端口描述SimpleDescriptionFormat_t其实2是包含在1里面的只是由于2比较多就单独列出来了。

下面是2的具体内容探明数据包内容1发送出去的数据是什么样子的第一步数据发送使用的是协议栈的发送函数内容包括了,目的地址目的节点上的那个端口簇里面的命令号要发送的数据长度要发送的数据地址发送的数据序列号第二步数据被接收后被解析成什么样子可以通过一个结构体看明白数据被接受过来以后到底是什么样子事件头很重要,它用来判断消息类型簇里面的命令号存储端口号链路质量数据具体位置很重要上面说到的两个很重要的成员在应用层程序里都有体现本想用两个命令号来区分不同的消息,但是好像不行!未完待续!第二部分消息队列从上面的讲解中我们了解了发送的无线数据、接收到的无线数据的样子。

ZigBee编程基础入门

ZigBee编程基础入门

zigbee基本概念及协议术语1. 逻辑设备类型协调器(coordinator),路由器(router),终端设备(end-device)•ZigBee 协调者—coord为协调者节点*–每各ZigBee网络必须有一个.–初始化网络信息.协调器是一种特殊的路由器(待确认)•ZigBee 路由器—router为路由节点*–路由信息•ZigBee 终端节点—rfd为终端节点*–没有路由功能–低价格2 . 2.4GHz射频信道分为16个独立信道。

3. 绑定应用设备之间信息流的控制机制。

有直接绑定(OTA)、间接绑定、直接绑定(通过串口)4. 配置文件profile 应用程序框架5. 端点endpoint 每个ZigBee设备支持多达240个端点6. NWK寻址地址类型:ZigBee设备有一个64位IEEE长地址(MAC地址)通常用一个16位短地址表识网络地址分配由协调器完成相关参数:5 max_depth 网络的最大深度6 Max_children 路由器或协调器节点连接子节点最大个数20 Max_router 路由器或协调器处理的具有路由能力的子节点最大个数它是max_children的子集数据包传送单点unicast 多点multicast 广播broadcast路由:经过路由器的每个数据帧寻找一条最佳传输路径,并将该数据有效地传送到目的节点。

F8wconfig.cfg配置路由看了下面就不用纠结了。

配置文件(profile):Zigbee协议的配置文件是对逻辑组件及其相关接口的描述,是面向某个应用类别的公约、准则.通常没有程序代码与配置文件相关联.属性(attribute):设备之间通信的每一种数据像开关的状态或温度计值等皆可称为属性.每个属性可得到唯一的ID值.簇(cluster):多个属性的汇集形成了簇,每个簇也拥有一个唯一的ID.虽然个体之间传输的通常是属性信息,但所谓的逻辑组件的接口指的却是簇一级的操作,而非属性一级.终端(endpoint):每个支持一个或多个簇的代码功能块称为终端.不同的设备通过它们的终端及所支持的簇来进行通信.Cluster: is a container for one or more attributes. (一个或更多属性的集合)Attribute: a data entity which represents a physical quantity or state.(反映物理特性或状态的一个数据实体)Cluster是逻辑设备之间的事务关系Cluster定性Attribute则是某种事务关系的具体特例Attribute定量Endpoint是一个逻辑设备(个人理解为入口地址)。

ZIGBEE学习笔记

ZIGBEE学习笔记

1、ZigBee协议栈:ZigBee协议是一系列的通信标准,通信双方需要共同按照这一标准进行正常的数据发射和接收。

协议栈是协议的具体实现形式,通俗点来理解就是协议栈是协议和用户之间的一个接口,开发人员通过使用协议栈来遵循和使用这个协议的,进而实现无线数据收发。

2、ZigBee无线网络协议层的架构:ZigBee协议分为两部分---IEEE 802.15.4和ZigBee,IEEE 802.15.4定义了PHY (物理层)和MAC(介质访问层)技术规范;ZigBee联盟定义了NWK(网络层)、APS(应用程序支持子层)、APL(应用层)技术规范。

ZigBee协议栈就是将各个层定义的协议都集合在一起,以函数的形式实现,并给用户提供API(应用层),用户可以直接调用---学习Zigbee就是熟悉API和学习如何使用对应函数。

3、用户实现简单的无线数据通信的一般步骤:---组网:调用协议栈的组网函数、加入网络函数,实现网络的建立与节点的加入。

---发送:发送节点调用协议栈的无线数据发送函数,实现无线数据发送。

---接收:接收节点调用协议栈的无线数据接收函数,实现无线数据接收。

4、Z-STACK协议栈工作原理:Z-stack可以看做是一个小型的操作系统(本质是大型的程序),用于实现底层和网络层的内容,Z-stack将复杂部分屏蔽掉。

用户通过API函数就可以轻易用ZigBee。

5、协调器、路由器、终端:Router----路由器Coodinator----协调器EndDevice----终端设备(1)协调器:(coordinator)每个zigbee网络只允许有一个zigbee的协调器,协调器首先选择一个信道和网络标识(PAN ID),然后开始这个网络.因为协调器是整个网络的开始,他具有网络的最高权限,是整个网络的维护者,还可以保持间接寻址用的表格绑定,同时还可以设计安全中心和执行其他动作,保持网络其他设备的通信。

zigbee总结zigbee和GSC CDMA 学习笔记

zigbee总结zigbee和GSC CDMA 学习笔记

关于ZIGBEE技术Zigbee的由来在蓝牙技术的使用过程中,人们发现蓝牙技术尽管有许多优点,但仍存在许多缺陷。

对工业,家庭自动化控制和遥测遥控领域而言,蓝牙技术显得太复杂,功耗大,距离近,组网规模太小等,而工业自动化对无线通信的需求越来越强烈。

正因此,经过人们长期努力,Zigbee协议在2003年中通过后,于2004正式问世了。

Zigbee是什么Zigbee是一个由可多到65000个无线数传模块组成的一个无线数传网络平台,十分类似现有的移动通信的CDMA网或GSM网,每一个Zigbee网络数传模块类似移动网络的一个基站,在整个网络范围内,它们之间可以进行相互通信;每个网络节点间的距离可以从标准的75米,到扩展后的几百米,甚至几公里;另外整个Zigbee网络还可以与现有的其它的各种网络连接。

例如,你可以通过互联网在北京监控云南某地的一个Zigbee控制网络。

不同的是,Zigbee网络主要是为自动化控制数据传输而建立,而移动通信网主要是为语音通信而建立;每个移动基站价值一般都在百万元人民币以上,而每个Zigbee―基站‖却不到1000元人民币;每个Zigbee 网络节点不仅本身可以与监控对对象,例如传感器连接直接进行数据采集和监控,它还可以自动中转别的网络节点传过来的数据资料; 除此之外,每一个Zigbee网络节点(FFD)还可在自己信号覆盖的范围内,和多个不承担网络信息中转任务的孤立的子节点(RFD)无线连接。

每个Zigbee网络节点(FFD和RFD)可以可支持多到31个的传感器和受控设备,每一个传感器和受控设备终可以有8种不同的接口方式。

可以采集和传输数字量和模拟量。

Zigbee技术的应用领域Zigbee技术的目标就是针对工业,家庭自动化,遥测遥控,汽车自动化、农业自动化和医疗护理等,例如灯光自动化控制,传感器的无线数据采集和监控,油田,电力,矿山和物流管理等应用领域。

另外它还可以对局部区域内移动目标例如城市中的车辆进行定位.通常,符合如下条件之一的应用,就可以考虑采用Zigbee技术做无线传输:1.需要数据采集或监控的网点多;2.要求传输的数据量不大,而要求设备成本低;3.要求数据传输可性高,安全性高;4.设备体积很小,不便放置较大的充电电池或者电源模块;5.电池供电;6.地形复杂,监测点多,需要较大的网络覆盖;7.现有移动网络的覆盖盲区;8.使用现存移动网络进行低数据量传输的遥测遥控系统。

Zigbee学习知识重点

Zigbee学习知识重点

Zigbee学习知识重点第一章Zigbee概述1、Zigbee是一种新兴的短距离、低速率无线网络技术,主要用于近距离无线连接。

2、Zigbee的特点是功耗低、成本低、时延短、网络容量大、可靠安全。

3、常见的Zigbee芯片有CC243X系列、MC1322X系列和CC253X系列。

4、常见的Zigbee协议栈有非开源(msstatePAN)协议栈、开源(freakz)协议栈和半开源(Zstack)协议栈。

5、Zigbee软件开发平台包括IAR、Zigbee Sniffer、物理地址修改软件以及其它辅助软件。

6、Zigbee硬件开发平台采用Altium Designer进行设计。

7、简述Zigbee的定义。

答:Zigbee是一种近距离、低复杂度、低功耗、低成本的双向无线通讯技术。

主要用于距离短、功耗低且传输速率不高的各种电子设备之间,进行数据传输(包括典型的周期性数据、间歇性数据和低反应时间数据)的应用。

(Zigbee的基础是IEEE802.15.4,但是IEEE802.15.4仅处理低级的MAC(媒体接入控制协议)层和物理层协议,Zigbee联盟对网络层协议和应用层进行了标准化。

)8、简述无线传感器网络与Zigbee之间的关系。

答:从协议标准来讲:目前大多数无线传感器网络的物理层和MAC层都采用IEEE802.15.4协议标准。

IEEE802.15.4描述了低速率无线个人局域网的物理层和媒体接入控制协议(MAC 层),属于IEEE802.15.4工作组。

而Zigbee技术是基于IEEE802.15.4标准的无线技术。

从应用上来讲:Zigbee适用于通信数据量不大,数据传输速率相对较低,成本较低的便携或移动设备。

这些设备只需要很少的能量,以接力的方式通过无线电波将数据从一个传感器传到另外一个传感器,并能实现传感器之间的组网,实现无线传感器网络分布式、自组织和低功耗的特点。

9、Zigbee技术特点:低功耗、低成本、大容量、可靠、时延短、灵活的网络拓扑结构。

ZigBee相关笔记

ZigBee相关笔记

常用控制寄存器相关技巧写1操作数据发送AF-DataRequest函数:afStatus_t AF_DataRequest( afAddrType_t * dstAddr,endPointDesc_t *srcEP,uint16 cID,uint16 le n, uint8 *buf,uint8 *transID,uint8 options,uint8 radius)MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID )解释: (afIncomingMSGPacket_t *)是强制类型转换,SampleApp_TaskID包含的事件ID交给osal_msg_receive函数从消息队列上接受消息,并转换成afIncomingMSGPacket_t结构体类型并赋给MSGpkt遇到问题:1、电脑无法识别板子解决方法:电池组供电,单纯靠USB供电不足2、安装完USB转串口驱动后依然无法识别串口解决方法:去掉仿真器直接将板子与PC相连3、IAR编译问题解决办法:4、功放烧毁原因:上电顺序,先上电再装天线会烧毁功放5、自己定义头文件在IAR中编译时出现“Fatal Error[Pe1696]: cannot open source file”解决方法:在IAR提供的头文件中缺少你定义的,可以使用#include "E:\毕业设计\程序\5883L\5883L test\HMC5883.h",用具体的地址来解决这个问题6、IAR编译时出现“Error[Pe029]: expected an expression”解决方法:定义问题,检查定义语句,#defien定义是不需要加”;”,但是typedef定义是必须要加”;”7、在两个.C文件中使用同一个变量解决方法:方案1:在一个文件中定义全局变量“类型 tmp;”,注意是全局变量。

z-stack代码分析--GenericApp实例

z-stack代码分析--GenericApp实例

z-stack代码分析--GenericApp实例//设备绑定并传送信息(hellow world)//1、终端绑定:按Joystick右键,发起绑定请求,等待其他节点应答;如其他节点也按了Joystick右键,同样发出了绑定请求,则本节点收到一个End_Device_Bind_rsp的信息,表示绑定成功并点亮HAL_LED_4。

//2、匹配描述:按Joystick左键,发起匹配描述请求,等待其他节点应答;//终端绑定和匹配描述的区别://匹配描述绑定:Match方式。

即:一个节点可以通过调用afSetMatch函数允许或禁止本节点被Match(协议栈默认允许,可以手工关闭),然后另外一个节点在一定的时间内发起ZDP_MatchDescReq请求,允许被Match的节点会响应这个Req,发起的节点在接收到RSP的时候就会自动处理绑定。

特点:不需要别人帮忙,只要在网络中的节点互相之间就可以实现,但是前提是他们一定要Match,即一方的outcluster至少有一个是另外一方的incluster,这种方式在很多时候用起来比较方便。

注意:如果同时有多个节点(一个节点上的多个端点也一样)处于允许Match状态,那么req的这个节点可能会收到一大票满足Match条件的rsp,那么你发起req的节点要在这个处理上多下功夫了。

//终端绑定:两个节点分别通过按键机制调用ZDP_EndDeviceBindReq函数。

即:在一定时间内两个节点都通过按键(其他方式也可以)触发调用这个函数。

特点:这个函数的调用将会向协调器发出绑定请求,如果在16S(协议栈默认)时间内两个节点都执行了这个函数,协调器就会帮忙实现绑定。

绑定表应该是存在OutCluster那边,即这两个节点应该是一个输出控制命令,一个接收控制命令,绑定表存在输出控制命令这边。

注意:这种方式一定需要协调器,否则不行;但是一旦绑定成功,不再需要协调器,协调器只是帮忙绑定的一个第三方;虽然叫做EndDeviceBind,但是不局限于End Device,路由器也一样用;重复上述操作会解绑定,也就是说这是一个乒乓方式。

zigbee学习笔记

zigbee学习笔记

要试验的:1串口查看数据2用自己的温度传感器看3串口通信,该代码,发送自己想发的数据。

如果修改数据长度看路由代码。

修改路由代码弄串口这边原理。

两头拼。

要解决的问题:1温度采集代码2zigbee传输代码3串口传输数据代码4endpoint与任务的关系。

与按键串口服务关系。

已经解决的问题:1开发的流程2如何添加新任务3osal工作原理,任务调度机制。

难点:几个关键回调函数的理解关键点(总体规划):1、数据采集,这部分的关键是I-WIRE协议的理解。

传感器与51的通信问题。

自己必须先把这部分搞定,现在要解决这个问题,即在TI提供的协议栈的基础上开发自己的应用。

要弄懂温度,湿度,PH值传感器的工作原理,一般采用I-WIRE总线的协议。

2、将数据传输到协调器(控制节点),这部分关键是zigbee通信协议,要充分利用TI的Z-STACK 协议栈来进行二次开发。

主要关注数据的收发模块,数据的格式、特点。

3、数据从协调器传到PC,这部分关键是串口通信协议。

正确的将数据传到上位机。

4、PC控制显示界面,这部分关键是找到关键的API,然后取出自己想要的数据显示。

如果需要存储数据,要操纵数据库,选择数据库。

解决这几个问题这个项目就算完成了。

现在猜想:一、开发一个新的应用应该做什么呢?1获取模板标识符,簇标识符,设备标识符的相关信息,我要进一步了解这两个关键的概念。

2在1基础上我要能注册application,taskID,endpoint,以建立自己应用与操作系统交互。

这是一个关键的点。

二、必须弄懂传感器采集的原理,代码。

三、必须弄懂串口的原理,代码。

关键的概念1、PAN标识符,PAN ID2、模板标识符,profileID3、簇标识符,clusterID 8bit4、节点,ieee地址(扩展地址)网络地址(短地址)64bit/16bit5、端点,endpoint 8bit6、设备标识符,Device Description 16bit7、应用任务ID,taskID8、属性Attribute 16bit9、Taskevents envents 16bit申请到模板标识符后,可以为模板定义设备描述符、簇标识符、服务类型(KVP或MSG)属性(Attribute)。

物联网ZigBee协议栈解析(加入网络)

物联网ZigBee协议栈解析(加入网络)
软件清单
开发平台:AR EW8051 7.51A 驱动软件: CP210x驱动包 例 程:文件包GenericApp
GenericApp
• “..\Samples CC2530\GenericApp\SX2530
不可更改或者移出 任务
代码分析2
不可移出任 务
• OS信息处理。 • 异常任务处理。
查看函数
组装系统
修改通道
• 为了方便大家集中学习,我们已经在每 套学习系统中标明了相关的通道与PanId 请各位严格使用自己的通道与PanId
修改PanId
• 为了方便大家集中学习,我们已经在每 套学习系统中标明了相关的通道与PanId 请各位严格使用自己的通道与PanId
GenericApp 形成或者加入一个网络
本章利用简单应用程序 GenericApp 实现ZigBee相关功能例程的讲解 在指定通道和pan上形成一个网络 设备加入指定特定参数的网络
实验准备
硬件清单
C51FF-PS-F V21仿真器一块 SMBD-V1.2 底板一块 SMBD-V11-1底板两块 RF-2530无线模块三块 Mini USB线2条 AAA电池8只
ZigBee工程
子工程
配置文件
链接配置文件
全局配置文

• ZigBee的大部分配置都放在相关的配置
节点设备文的件中
配置文件
协调器的配置 文件
路由器配置 文件
配置通道
通道选择
通道全 局变量
f8wConfig.cfg中配置PAN ID
• 如果 PAN_ID = 0xFFFF 设备类型是协调者
• 设备将使用物理地址最后两个字节作为PAN_ID
zigbee工程子工程配置文件zigbee的大部分配置都放在相关的配置文件中链接配置文件全局配置文协调器的配置文件节点设备的配置文件路由器配置文件配置通道通道全局变量通道选择f8wconfigcfg中配置panid0xffff设备类型是协调者0xffff设备类型是路由器或者终端节点设备0xffff设备类型是协调者0xffff设备类型是路由器或者终端节点设备设备将只能加入该panid指定的网络genericapp形成或者加入一个网络本章利用简单应用程序genericapp实现zigbee相关功能例程的讲解在指定通道和pan上形成一个网络设备加入指定特定参数的网络实验准备硬件清单c51ffpsfv21仿真器一块smbdv12底板一块smbdv111底板两块rf2530无线模块三块miniusb线2条aaa电池8只软件清单开发平台

zigbee基础知识笔记

zigbee基础知识笔记

1.基础知识 (1)1.1IEEE地址 (1)1.2簇 (2)1.3 Profile ID (4)1.4 网络地址与端点号、节点 (4)1.5 PANID (5)1.6 zigbee设备 (5)2.绑定机制 (7)2.1描述符绑定 (7)2.2设备绑定 (23)1.基础知识1.1IEEE地址IEEE地址是64位,在设备进入网络之前就分配好了的,应该在全球是唯一的,而网络地址是在网络建立后,设备加入网络时,它的父节点给它分配的,在设备通信时,首先由ieee地址找到设备的网络地址,然后根据网络地址实现设备之间的通信,这样可以减少帧头长度,多传有效数据通俗的说IEEE地址相当于你的手机号(11位的那个),短地址就相当于你们公司的小号(3、4)位,一个公司的互打电话就用小号噻。

假设你的手机号138xxxxx666,这个是唯一的,但你的小号,假设是666,在你的公司网中是唯一的,但是在另一个网中,可能别人的小号也是666。

1.2簇簇就是相当于端点房间里面的人,是接收最终的目标。

这东西是2个字节编号,在射频发送的时候,必须要指定接收模块的镞,发送模块不需要指定。

首先每一个端点可以看成是一个1个字节数字编号的开有一扇门的房间,数据最终的目标是进入到无线数据包指定的目标端点房间,而取无线数据这个相关的代码在任务事件处理函数里,TI协议栈有那么多的任务事件处理函数,所以必须要指定在哪个任务事件处理函数来取这个无线数据包里面的有用数据。

端点就相当于一个房间的门牌号!!!SimonApp_epDesc.endPoint = 10;//SimonApp_ENDPOINT; 此端点编号为10SimonApp_epDesc.task_id = &SimonApp_TaskID; 和我们应用层任务挂钩完成了簇信息表的构建,因为簇信息封装在SimonApp_SimpleDesc里面,这里面却只是起到一个信息表的作用!方便数据到来的时候查询相关信息表!const cId_t SimonApp_ClusterList[SimonApp_MAX_CLUSTERS] ={SimonApp_CLUSTERID};const SimpleDescriptionFormat_t SimonApp_SimpleDesc = {SimonApp_ENDPOINT, // int Endpoint;SimonApp_PROFID, // uint16 AppProfId[2];SimonApp_DEVICEID, // uint16 AppDeviceId[2];SimonApp_DEVICE_VERSION, // int AppDevVer:4;SimonApp_FLAGS, // int AppFlags:4;SimonApp_MAX_CLUSTERS, // byte AppNumInClusters;(cId_t *)SimonApp_ClusterList, // byte *pAppInClusterList;SimonApp_MAX_CLUSTERS, // byte AppNumInClusters;(cId_t *)SimonApp_ClusterList // byte *pAppInClusterList;};接收到数据以后,判断是属于哪一个端点、属于哪一个簇1.3 Profile ID这个是由Zigbee组织来分配的应用ID号,比如无线开关用0x0001,智能电表用ox0002,万用遥控器用0x0003等等。

Zigbee应用笔记

Zigbee应用笔记

Zigbee应用笔记本应用笔记是建立在对TI的“ZStack-1.4.2-1.1.0”理解的基础上的,可以帮助利用TI 的Zigbee协议栈开发应用程序。

一创建主函数程序运行入口是主函数:main() 这部分程序代码包含在ZMain文件夹的ZMain.c中。

在mian()中包括初始化和正常运行两个部分。

1初始化初始化期间不接受中断,故首先要屏蔽中断,调用osal_int_disable( INTS_ALL )实现屏蔽中断功能。

完成初始化后调用osal_int_enable( INTS_ALL )使能中断。

初始化主要包括:协议栈寄存器初始化zmain_ram_init()试验板初始化InitBoard( OB_COLD )这包括各个通用I/O口的设置,确保与硬件电路设计的一致,操作系统时钟设置。

这部分在HAL/Target/Config/hal_board_cfg.h中,用户可以根据自己的硬件设计加以修改。

硬件驱动初始化HalDriverInit () 这包括TIMER、ADC、LED、LCD、KEY、AES、DMA、UART,用户可以根据需要,通过设置相应的宏定义(HAL_ *)初始化相应的硬件。

驱动的宏定义设置在hal_board_cfg.h中的driver configeration部分。

非易失性存储器初始化osal_nv_init( NULL )MAC初始化ZMacInit()设置64位地址zmain_ext_addr() 每一个设备都有一个唯一的64位地址。

初始化协议栈全局变量zgInit()。

初始化应用框架(AF)afInit(),初始化时没有应用端口操作系统初始化osal_init_system()这包括寄存器初始化;操作系统时钟初始化;能量管理系统初始化;操作系统初始化osalTaskInit();添加任务osalAddTasks()这包括网络层任务、应用支持子层任务等,用户可在此添加自己的应用任务;任务初始化osalInitTasks()这包括为每个任务分配一个任务ID号(task_ID)以及调用每一个任务的初始化函数。

zigbee串口通信

zigbee串口通信

zigbee串口通信RS232,也称标准串口,是目前最常用的一种串行通讯接口,因其成本低廉,应用广泛而被很多嵌入式系统所采用。

在CC2530开发板上,由于LCD、LED等基本外接显示信息量有限,同时串口也方便了与其他系统进行通讯,所以它无疑成为了开发者最重要的一个调试手段。

本章的重点,就是以Ztack2007中提供的例程--SerialApp为基础,对CC2530的串口部分进行详细的介绍。

例3.基于Ztack2007的串口通讯在之前的“奥特曼Zigbee读书日记(三)和(四)”中,其实已经利用TI提供的基本库,从零开始,一步步地搭建了一个“老王”和“老张”打招呼的例程,但是由于他们俩说的所有话都是程序规定的,所以他们只能简单地说两句话“吃了吗”和“吃了”,然后不停地重复,我们中国人自然没有这么呆啦~~在本实验中,看看中国小伙是如何“远程”泡美国MM的~~~图(1)注:“日记”中的例程的串口通讯部分其实是抛开Ztack的串口程序而重新写的,但实际上Ztack已经做过这部分工作了,在本例程中,我们不对ZStack做任何修改,只是分析下其程序功能与原理。

读者可以在安装ZStack-CC2530-2.3.0-1.4.0后,在C:\\Te某aIntrument\\ZStack-CC2530-2.3.0-1.4.0\\Project\\ztack\\Utilitie\\SerialApp\\CC2530DB目录下,打开SerialApp这个工程进行实验。

[一]程序功能实现两个节点之间的绑定与通讯,同时每个节点可与其“上位机”--所边接的PC串口终端,进行通讯。

示意如下:图(2)[二]操作说明(图3)(图4)如果显示信息如上图所示,则表示网络初始化成功。

此时,按下任意一个节点的摇杆(Joytick)右键进行绑定申请,然后立即按下另外一个节点的Joytick右键进行绑定确认。

此时,两个节点的红色LED灯--LED1,同时点亮,表示绑定成功,可以开始通信。

ZigBee基础知识讲解

ZigBee基础知识讲解

1.2.2应用层消息类型 在ZigBee应用中,应用框架(AF)提供了两种标准服务类型。一种是键值对 (Key Value Pair, KVP)服务类型,一种是报文(Message, MSG)服务类型。 KVP服务用于传输规范所定义的特殊数据。它定义了属性(Attribute)、属性 值(Value)以及用于KVP操作的命令:Set, Get, Event。其中Set用于设置一个属性 值,Get用于获取一个属性的值,Event用于通知一个属性已经发生改变。kVP 消息主要用于传输一些较为简单的变量格式。 由于ZigBee的很多应用领域中的消息较为复杂并不适用于KVP格式,因此 ZigBee协议规范定义了MSG服务类型。MSG服务对数据格式不作要求,适合 任何格式的数据传输。因此可以用于传送数据量大的消息。 KVP命令帧的格式如图1-2-2。
MSG命令帧格式如图1-2-3所示:
1.2.3ZigBee设备配置层 ZigBee设备配置层提供标准的ZigBee配置服务,它定义和处理描述符请求。在 ZigBee设备配置层中定义了称为ZigBee设备对象(ZigBee device object,ZDO)的 特殊软件对象,它在其他服务中提供绑定服务。远程设备可以通过ZigBee设备 对象(ZDO)接口请求任何标准的描述符信息。当接受到这些请求时,ZDO会 调用配置对象以获取相应的描述符值。子目前的ZigBee协议栈版本中,还没有 完全实现设备配置层。ZDO是特殊的应用对象,它在端点(end-point)0上实 现。 1.2.4用户程序 运行在ZigBee协议栈上的应用程序实际上就是厂商自定义的应用对象。这些应用 程序使用ZigBee联盟给出的并且批准的规范(profile)进行开发并且运行在端 点1-240上。
APSDEME提供的管理服务允许一个应用连接到ZigBee系统。他提供吧基于服务的需求相匹 配的两个设备作为一个整体来进行管理的绑定服务,并为绑定服务构建 和保留绑定表,除 这些外,APSDE 还提供以下服务 (1)AIB 管理:APSME具有能从设备的AIB中获得属性或进行属性设置的能力。 (2)安全管理:APSME通过利用密钥能够与其他设备监理可靠的关联。 APS子层主要提供ZigBee端点接口。应用程序将使用该层打开或关闭一个或多个端点并且读 取后或传送数据,而且APS子层为键值对(key value pair,KVP) 和报文(MGS)数据传输提供了原语。APS子层也有绑定表,绑定表提供了端点和网络中两 个节点间的簇ID对之间的逻辑链路。当首次对主设备编程时绑定表为空,主应用程序必须 调用正确的绑定API来创建新的绑定项。 APS子层还有一个“间接发送缓冲器”RAM,来存储间接帧。直到目的接受者请求 这些数据帧为止。根据ZigBee规范,在星形网络中,从设备总会将这些数据帧转发到主设 备中。从设备可能不知道该数据帧的目标接受者,而且数据帧的实际接受者由绑定表决定, 这样,如果主设备一旦接收到数据帧,它就会查找绑定表以确定目标接受者。如果该数据 帧由接受者,就会将该数据帧存储在间接发送帧缓冲器里,直到目标接受者明确请求该数 据帧为止。根据请求的频率,主设备必须将数据帧保存在间接帧缓冲器内。在此需要注意 的是:节点请求数据越长,数据包需要保存在间接发送帧缓冲器里的时间也越长,因此所 需要的间接缓冲空间也就越大。间接帧缓冲器包含一个设计时分配的固定大小的RAM堆, 可通过动态分配间接发送帧缓冲器的RAM来添加新的数据帧,动态存储管理可充分利用间 接发送帧缓冲空间。

SimpleApp和GenericApp实例绑定程序流程

SimpleApp和GenericApp实例绑定程序流程

SimpleApp和GenericApp实例绑定程序流程(2011-03-11 10:41:34)转载▼标签:杂谈使用的协议栈版本及例子信息:ZigBee2006\ZStack-1.4.3-1.2.1个人注释版_5.24\Projects\zstack\Samples\SimpleApp\CC2430DBZigBee2006\ZStack-1.4.3-1.2.1个人注释版_5.24\Projects\zstack\Samples\GenericApp\CC2430DB记录下个人对这两个例程绑定的理解:两个例程:SimpleApp和GenericApp,其中SimpleApp分两个实验:灯开关实验,温度传感器实验建立一个绑定表格有3种方式:(1)ZDO绑定请求:一个试运转的工具能告诉这个设备制作一个绑定报告(2)ZDO终端设备绑定请求:设备能告诉协调器他们想建立绑定表格报告。

该协调器将使协调并在这两个设备上创建绑定表格条目。

(3)设备应用:在设备上的应用能建立或管理一个绑定表格。

SimpleApp例程默认使用方法1,GenericApp可以使用方法1或2.-------------------------------------灯开关实验:Switch.cswitch开关设备: 作为终端节点按K1则作为终端启动;设备类型确定后再按K1则发送绑定请求命令按K2则作为终端启动;设备类型确定后再按K2则发送灯toggle命令按K3,删除所有绑定Controller.ccontroller灯设备: 作为协调器或路由器按K1则作为协调器启动;设备类型确定后再按K1则初始化设备允许绑定模式按K2则作为路由器启动;-------------------------------------温度传感器实验Sensor.csensor传感器设备: 作为终端节点按K1则作为终端启动;按K2则作为终端启动;Collector.c 作为协调器或路由器Collector中心收集设备:按K1作为协调器启动;设备类型确定后再按K1则初始化设备允许绑定模式按K2作为路由器启动;设备类型确定后再按K2则禁止允许绑定模式-------------------------------------GenericApp实验:设备按K2发送终端设备绑定请求(这个说法待定)设备按K4发送描述符匹配请求******************************************************************************************** ********************************************************************************************************************* ********************************************************************************************************************* *************************1、灯开关实验绑定流程1.1、按键处理函数Controller管理器(灯)设备,其zb_HandleKeys()按键处理函数:if ( myAppState == APP_INIT ){…………logicalType = ZG_DEVICETYPE_COORDINATOR;//协调器…………}else{// Initiate a bindingzb_AllowBind( myAllowBindTimeout ); //默认为10S,myAllowBindTimeout=10}}//--------------------------if ( keys & HAL_KEY_SW_2 ){…………logicalType = ZG_DEVICETYPE_ROUTER; //路由器…………}//--------------------------…………}}osal_start_timerEx( sapi_TaskID, MY_REPORT_TEMP_EVT, myTempReportPeriod );}if ( event & MY_REPORT_BATT_EVT ) //电池电量报告{// Read battery value// If battery level low, report battery valuepData[0] = BATTERY_REPORT; //0x02(用来指示这是电池能量数据)pData[1] = myApp_ReadBattery();zb_SendDataRequest( 0xFFFE, SENSOR_REPORT_CMD_ID, 2, pData, 0, AF_ACK_REQUEST, 0 ); osal_start_timerEx( sapi_TaskID, MY_REPORT_BATT_EVT, myBatteryCheckPeriod );}if ( event & MY_FIND_COLLECTOR_EVT ){// Find and bind to a collector devicezb_BindDevice( TRUE, SENSOR_REPORT_CMD_ID, (uint8 *)NULL );}}************************************可以看到最终调用zb_BindDevice( TRUE, SENSOR_REPORT_CMD_ID, (uint8 *)NULL ),是未知扩展地址的绑定,故接下来的流程参见<协议栈simpleApp例程中两种绑定机制>这篇记录.流程:当传感器设备和中心收集设备逻辑类型确定,网络建立完成后,collector中心收集设备按K1进入允许绑定模式.sensor传感器设备自动发送绑定请求(默认未知扩展地址的绑定).2.3、关于sensor传感器设备进入zb_StartConfirm()的流程.事实上这部分个人还是很模糊,好多细节不理解,大概记录下.看下SAPI_Init()函数:************************************void SAPI_Init( byte task_id ){uint8 startOptions;sapi_TaskID = task_id;sapi_bindInProgress = 0xffff;//不允许绑定过程sapi_epDesc.endPoint = zb_SimpleDesc.EndPoint; //0x02sapi_epDesc.task_id = &sapi_TaskID;sapi_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&zb_SimpleDesc;sapi_tencyReq = noLatencyReqs;// Register the endpoint/interface description with the AF 注册终端afRegister( &sapi_epDesc );// Turn off match descriptor response by defaultafSetMatch(sapi_epDesc.simpleDesc->EndPoint, FALSE);//关闭匹配描述符响应// Register callback evetns from the ZDApp //从ZDApp登记返回事件ZDO_RegisterForZDOMsg( sapi_TaskID, NWK_addr_rsp );ZDO_RegisterForZDOMsg( sapi_TaskID, Match_Desc_rsp );#if (defined HAL_KEY) && (HAL_KEY == TRUE)// Register for HAL eventsRegisterForKeys( sapi_TaskID );//登记按键事件if ( HalKeyRead () == HAL_KEY_SW_1){// If SW5 is pressed and held while powerup, force auto-start and nv-restore off and resetstartOptions = ZCD_STARTOPT_CLEAR_STATE | ZCD_STARTOPT_CLEAR_CONFIG; //复位启动状态和配置//ZCD_NV_STARTUP_OPTION作为默认启动项配置,存到&startOptions中//ZCD_NV_STARTUP_OPTION在按键时便赋值为ZCD_STARTOPT_AUTO_START//这里关系到对事件ZB_ENTRY_EVENT的处理,顺利的话就发送一个启动协议栈请求zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );zb_SystemReset(); //复位系统(更新启动项配置后,重启设备)}#endif // HAL_KEY#ifdef LCD_SUPPORTEDPrint8(HAL_LCD_LINE_2 ,20,"Simple",1);#endif// Set an event to start the applicationosal_set_event(task_id, ZB_ENTRY_EVENT); //设置事件,启动应用}************************************SAPI_Init()中初始化startOptions为:startOptions = ZCD_STARTOPT_CLEAR_STATE | ZCD_STARTOPT_CLEAR_CONFIG;//复位启动状态和配置然后通过zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions )把ZCD_NV_STARTUP_OPTION赋给startOptions,而ZCD_NV_STARTUP_OPTION在按键处理函数中都被赋值为ZCD_STARTOPT_AUTO_START.因此这里startOptions最终为ZCD_STARTOPT_AUTO_START.SAPI_Init()最后有句:osal_set_event(task_id, ZB_ENTRY_EVENT);来看SAPI_ProcessEvent()对ZB_ENTRY_EVENT事件的处理:************************************SAPI_ProcessEvent(){if ( events & ZB_ENTRY_EVENT ) // 0x1000{uint8 startOptions;// Give indication to application of device startupzb_HandleOsalEvent( ZB_ENTRY_EVENT );// LED off cancels HOLD_AUTO_START blink set in the stackHalLedSet (HAL_LED_4, HAL_LED_MODE_OFF);//读配置zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );if ( startOptions & ZCD_STARTOPT_AUTO_START ) //自动启动{zb_StartRequest(); //发送协议栈启动请求}else{// blink leds and wait for external input to config and restart//等待外部输入来配置和重启HalLedBlink(HAL_LED_2, 0, 50, 500);#if defined SENSOR //如果是传感器设备logicalType = ZG_DEVICETYPE_ENDDEVICE;zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);// Do more configuration if necessary and then restart device with auto-start bit setzb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );startOptions = ZCD_STARTOPT_AUTO_START;zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );zb_SystemReset();#endif}//-------------------(本小段更新于2010.6.03)// This must be the last event to be processed//应用事件events://而ZB_USER_EVENTS = 0x00FF;以上应用事件和ZB_USER_EVENTS相与都不为0,因此这些//应用事件事实上都是通过ZB_USER_EVENTS进入zb_HandleOsalEvent()进行处理的!if ( events & ( ZB_USER_EVENTS ) ){// User events are passed to the applicationzb_HandleOsalEvent( events );// Do not return here, return 0 later}//-------------------}************************************一、MY_FIND_COLLECTOR_EVT事件是在哪里联系到ZB_ENTRY_EVENT事件,从而通过ZB_ENTRY_EVENT事件调用zb_HandleOsalEvent()进行处理??? (不是通过ZB_ENTRY_EVENT,因为ZB_ENTRY_EVENT=0x1000; MY_FIND_COLLECTOR_EVT=0x0008,两者相与为0不会执行这里if内的程序,而是通过下面的ZB_USER_EVENTS=0x00FF,和MY_FIND_COLLECTOR_EVT相与不为0再执行zb_HandleOsalEvent().事实上本例所有用户应用事件都是通过ZB_USER_EVENTS被处理的!)二、其实我在zb_HandleOsalEvent()并没看到事件ZB_ENTRY_EVENT,位运算也不对,这里怎么回事???(估计就是没什么处理,不同类型节点的zb_HandleOsalEvent定义是不同的,simpleApp例子有些类型节点对这个函数也没有定义,个人觉得主要还是根据用户实际情况进行添加.比如开启后就开始触发一些事件等…)三、如果startOptions为ZCD_STARTOPT_AUTO_START,则调用zb_StartRequest(),则必然会有个zb_StartConfirm(). 在每种类型设备的按键函数中都可以找到:startOptions =ZCD_STARTOPT_AUTO_START;也就是通过外部按键来改变了startOptions.当然这里还有一种情况,如上面函数中#if defined SENSOR,下面也有startOptions = ZCD_STARTOPT_AUTO_START;也就是说如果传感器设备迟迟没有按键按下来确定设备类型重启,这里将自动完成配置,事实上传感器节点无论按K1/2都作为终端启动.设备的每次重启zb_SystemReset(),都将进行全部初始化,包括SAPI_Init().因此大概流程如下:(这里我自己都认为不怎么准确,仅供参考)设备启动,外部按键选择设备类型,startOptions为ZCD_STARTOPT_AUTO_START——SAPI_Init()触发ZB_ENTRY_EVENT事件启动应用——SAPI_ProcessEvent()处理ZB_ENTRY_EVENT事件——startOptions为ZCD_STARTOPT_AUTO_START,发送协议栈启动请求zb_StartRequest()——协议栈启动响应zb_StartConfirm(),如果启动成功,即入网成功则启动软定时器osal_start_timerEx( sapi_TaskID, MY_FIND_COLLECTOR_EVT, myBindRetryDelay )——溢出则触发MY_FIND_COLLECTOR_EVT事件发送绑定请求.******************************************************************************************** ********************************************************************************************************************* ********************************************************************************************************************* *************************3、GenericApp实验3.1、按键函数先来看下按键函数:************************************void GenericApp_HandleKeys( byte shift, byte keys ){…………{…………if ( keys & HAL_KEY_SW_2 ){HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );// Initiate an End Device Bind Request for the mandatory endpointdstAddr.addrMode = Addr16Bit;dstAddr.addr.shortAddr = 0x0000; // CoordinatorZDP_EndDeviceBindReq( &dstAddr, NLME_GetShortAddr(),GenericApp_epDesc.endPoint,GENERICAPP_PROFID,GENERICAPP_MAX_CLUSTERS, (cId_t *)GenericApp_ClusterList,GENERICAPP_MAX_CLUSTERS, (cId_t *)GenericApp_ClusterList,FALSE );}…………if ( keys & HAL_KEY_SW_4 ){HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );// Initiate a Match Description Request (Service Discovery)dstAddr.addrMode = AddrBroadcast; //广播传输dstAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR; //0xFFFFZDP_MatchDescReq( &dstAddr, NWK_BROADCAST_SHORTADDR,GENERICAPP_PROFID,GENERICAPP_MAX_CLUSTERS, (cId_t *)GenericApp_ClusterList,GENERICAPP_MAX_CLUSTERS, (cId_t *)GenericApp_ClusterList,FALSE );}}}************************************可以看到按K2为发送终端设备绑定请求,按K4为发送描述符匹配请求.对于按K2,这里我知道终端设备有效,路由器按K2应该有效,但协调器按K2是个什么现象?目前不知道.而描述符匹配请求,个人觉得三种类型节点都可以发送.但在GenericApp这个例程中我找不到有初始化设备处于允许绑定模式的语句.下面分别记录下个人对GenericApp实验这两种绑定方式的理解.3.2、终端设备绑定请求这应该属于建立绑定表三种方式的第二种:设备能告诉协调器他们想建立绑定表格报告,该协调器将使协调并在这两个设备上创建绑定表格条目.这里我假设两个终端设备向协调器发送终端设备绑定请求,因为无实验平台,暂时只能靠假设来理解. (1)终端设备向协调器发送终端设备绑定请求调用ZDP_EndDeviceBindReq(),目的地址设为0x0000;ZDP_EndDeviceBindReq()调用fillAndSend(),默认clusterID为End_Device_Bind_req,最后通过AF_DataRequest()发送出去.(2)协调器收到终端设备绑定请求End_Device_Bind_req这个信息被传送到ZDO层,来看下ZDP_IncomingData()函数:************************************void ZDP_IncomingData( afIncomingMSGPacket_t *pData ){…………//通过这个函数把ZDO信息发送到注册过ZDO信息的任务中去.//比如sapi中SAPI_Init()注册过两种类型clusterId的ZDO信息:NWK_addr_rsp 和Match_Desc_rsp //因此其它命令,比如请求命令不会发送到sapi应用层中//注意,End_Device_Bind_req这个ZDO信息是注册在ZDAppTaskID任务中的.handled = ZDO_SendMsgCBs( &inMsg );#if defined( MT_ZDO_FUNC )MT_ZdoRsp( &inMsg );#endif//注意,这里只会对请求/设置/通知命令才调用相应处理函数,如果是响应命令则不处理//但是要ZDO信息处理表中包含的命令才有相应的处理函数,有些没有的就不会调用//比如End_Device_Bind_req,这个很重要,它在哪里被处理呢?在ZDApp层任务中,//函数ZDApp_RegisterCBs()把这个请求命令登记到了ZDAppTaskID,具体参见ZDApp_RegisterCBs() while ( zdpMsgProcs[x].clusterID != 0xFFFF ) //一个个查询过去{if ( zdpMsgProcs[x].clusterID == inMsg.clusterID ){zdpMsgProcs[x].pFn( &inMsg ); //调用相应ZDO信息处理函数return; //如x=6,为ZDO_ProcessMatchDescReq();}x++;}…………}************************************因为ZDO信息处理表zdpMsgProcs[ ]没有对应的End_Device_Bind_req簇,因此没有调用ZDO信息处理表中的处理函数,但是前面的ZDO_SendMsgCBs()会把这个终端设备绑定请求发送到登记过这个ZDO信息的任务中去,那哪里登记过End_Device_Bind_req这个ZDO信息呢? 来看个函数:ZDApp_RegisterCBs():************************************void ZDApp_RegisterCBs( void ){#if defined ( ZDO_IEEEADDR_REQUEST ) || defined ( REFLECTOR )ZDO_RegisterForZDOMsg( ZDAppTaskID, IEEE_addr_rsp );#endif#if defined ( ZDO_NWKADDR_REQUEST ) || defined ( REFLECTOR )ZDO_RegisterForZDOMsg( ZDAppTaskID, NWK_addr_rsp );#endif#if defined ( ZDO_COORDINATOR ) //协调器ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_rsp );ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_rsp );ZDO_RegisterForZDOMsg( ZDAppTaskID, End_Device_Bind_req ); //End_Device_Bind_req#endif#if defined ( REFLECTOR )ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_req );ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_req );#endif}************************************这个函数通过ZDO_RegisterForZDOMsg()登记特定ZDO信息到任务ZDAppTaskID中,包括End_Device_Bind_req,看下ZDO_RegisterForZDOMsg()函数的说明:************************************* @fn ZDO_RegisterForZDOMsg** @brief Call this function to register of an incoming over* the air ZDO message - probably a response message* but requests can also be received.* Messages are delivered to the task with ZDO_CB_MSG* as the message ID.** @param taskID - Where you would like the message delivered* @param clusterID - What message?************************************默认的信息类型是ZDO_CB_MSG.回过来看上面的ZDP_IncomingData()中ZDO_SendMsgCBs()是如何传送End_Device_Bind_req到任务ZDAppTaskID中去的.ZDO_SendMsgCBs():************************************uint8 ZDO_SendMsgCBs( zdoIncomingMsg_t *inMsg ){…………while ( pList ){if ( pList->clusterID == inMsg->clusterID ){…………msgPtr->hdr.event = ZDO_CB_MSG; //事件为ZDO_CB_MSGosal_msg_send( pList->taskID, (uint8 *)msgPtr );ret = TRUE;}}pList = (ZDO_MsgCB_t *)pList->next;}return ( ret );}************************************可以看到通过osal_msg_send()来触发任务ZDAppTaskID的ZDO_CB_MSG事件.osal_msg_send()中调用的是osal_set_event( destination_task, SYS_EVENT_MSG ),事件为SYS_EVENT_MSG.任务ZDAppTaskID事件处理函数ZDApp_event_loop()通过判断SYS_EVENT_MSG来调用ZDApp_ProcessOSALMsg()处理SYS_EVENT_MSG事件;ZDApp_ProcessOSALMsg()再通过判断ZDO_CB_MSG来调用ZDApp_ProcessMsgCBs()处理ZDO_CB_MSG事件;ZDApp_ProcessMsgCBs()再通过判断End_Device_Bind_req调用以下程序来处理End_Device_Bind_req 终端设备绑定请求:************************************case End_Device_Bind_req: //终端设备绑定请求!{ZDEndDeviceBind_t bindReq;ZDO_ParseEndDeviceBindReq( inMsg, &bindReq ); //解析终端绑定请求信息ZDO_MatchEndDeviceBind( &bindReq ); //匹配终端绑定// Freeing the cluster lists - if allocated.if ( bindReq.numInClusters )osal_mem_free( bindReq.inClusters );if ( bindReq.numOutClusters )osal_mem_free( bindReq.outClusters );}break;************************************这里ZDO_ParseEndDeviceBindReq()是把接收到的终端绑定请求信息inMsg解析赋给bindReq.重点看下ZDO_MatchEndDeviceBind( &bindReq ):************************************* @fn ZDO_MatchEndDeviceBind()** @brief** Called to match end device binding requests** @param bindReq - binding request information* @param SecurityUse - Security enable/disable** @return none*/void ZDO_MatchEndDeviceBind( ZDEndDeviceBind_t *bindReq ){zAddrType_t dstAddr;uint8 sendRsp = FALSE;uint8 status;//--------------------------// Is this the first request?if ( matchED == NULL ) //如果接收到的是第一个终端绑定请求{// Create match info structurematchED = (ZDMatchEndDeviceBind_t *)osal_mem_alloc( sizeof ( ZDMatchEndDeviceBind_t ) ); if ( matchED ){// Clear the structureosal_memset( (uint8 *)matchED, 0, sizeof ( ZDMatchEndDeviceBind_t ) );// Copy the first request's information 拷贝请求信息if ( !ZDO_CopyMatchInfo( &(matchED->ed1), bindReq ) ) //如果拷贝不成功{status = ZDP_NO_ENTRY;sendRsp = TRUE;}}else //如果匹配信息空间开辟不成功{status = ZDP_NO_ENTRY;sendRsp = TRUE;}if ( !sendRsp ) //内存空间分配及拷贝都成功{// Set into the correct state 状态为等待另一个请求matchED->state = ZDMATCH_WAIT_REQ;// Setup the timeout 等待时间计时APS_SetEndDeviceBindTimeout( AIB_MaxBindingTime, ZDO_EndDeviceBindMatchTimeoutCB ); }}//-----------else //如果接收到的不是第一个终端绑定请求{matchED->state = ZDMATCH_SENDING_BINDS;//状态为绑定中// Copy the 2nd request's information 拷贝第二个请求信息if ( !ZDO_CopyMatchInfo( &(matchED->ed2), bindReq ) ) //如果拷贝不成功{status = ZDP_NO_ENTRY;sendRsp = TRUE;}//-----------// Make a source match for ed1 以ed1为源//对ed1终端绑定请求与ed2进行簇列表的匹配比较,函数返回的是ed1与ed2匹配的簇的数目matchED->ed1numMatched = ZDO_CompareClusterLists(matchED->ed1.numOutClusters, matchED->ed1.outClusters,matchED->ed2.numInClusters, matchED->ed2.inClusters, ZDOBuildBuf );if ( matchED->ed1numMatched ) //有相匹配的簇{// Save the match list 保存匹配簇列表matchED->ed1Matched = osal_mem_alloc( (short)(matchED->ed1numMatched * sizeof ( uint16 )) ); //分配内存空间if ( matchED->ed1Matched ) //如果内存空间分配成功{osal_memcpy( matchED->ed1Matched, ZDOBuildBuf, (matchED->ed1numMatched * sizeof( uint16 )) ); //保存匹配簇}else //如果内存空间分配不成功{// Allocation error, stopstatus = ZDP_NO_ENTRY;sendRsp = TRUE;}}//-----------// Make a source match for ed2 以ed2为源//对ed2终端绑定请求与ed1进行簇列表的匹配比较,函数返回的是ed2与ed1匹配的簇的数目matchED->ed2numMatched = ZDO_CompareClusterLists(matchED->ed2.numOutClusters, matchED->ed2.outClusters,matchED->ed1.numInClusters, matchED->ed1.inClusters, ZDOBuildBuf );if ( matchED->ed2numMatched ){// Save the match listmatchED->ed2Matched = osal_mem_alloc( (short)(matchED->ed2numMatched * sizeof ( uint16 )) ); if ( matchED->ed2Matched ){osal_memcpy( matchED->ed2Matched, ZDOBuildBuf, (matchED->ed2numMatched * sizeof( uint16 )) );}else{// Allocation error, stopstatus = ZDP_NO_ENTRY;sendRsp = TRUE;}}//如果两个请求有相匹配的簇,并且已经保存成功if ( (sendRsp == FALSE) && (matchED->ed1numMatched || matchED->ed2numMatched) ){// Do the first unbind/bind stateZDMatchSendState( ZDMATCH_REASON_START, ZDP_SUCCESS, 0 );//发送响应信息给两个终端请求设设 //备,这里面也调用ZDP_EndDeviceBindRsp()}else //不成功{status = ZDP_NO_MATCH;sendRsp = TRUE;}}//--------------------------if ( sendRsp ) //如果匹配簇保存不成功{// send response to this requester 发送响应信息给两个请求者dstAddr.addrMode = Addr16Bit;dstAddr.addr.shortAddr = bindReq->srcAddr;//ZDP_EndDeviceBindRsp()默认命令ID为End_Device_Bind_rspZDP_EndDeviceBindRsp( bindReq->TransSeq, &dstAddr, status, bindReq->SecurityUse );//status = ZDP_NO_MATCHif ( matchED->state == ZDMATCH_SENDING_BINDS ){// send response to first requesterdstAddr.addrMode = Addr16Bit; //第一个请求终端dstAddr.addr.shortAddr = matchED->ed1.srcAddr;ZDP_EndDeviceBindRsp( matchED->ed1.TransSeq, &dstAddr, status, matchED->ed1.SecurityUse );}// Process ended - release memory used 释放内存空间ZDO_RemoveMatchMemory();}}//-------------------------************************************ZDO_MatchEndDeviceBind()函数,如果检测到接收到的绑定请求是第一个,则分配空间保存并计时等待第二个绑定请求;如果是第二个绑定请求则分别以两个请求为源绑定来与另一个请求匹配簇和Profile_ID,如果Profile_ID相同且有相匹配的簇,则保存(协调器里进行),并通过ZDMatchSendState()函数来发送匹配成功的响应信息End_Device_Bind_rsp给两个请求终端(这个函数里面也调用了ZDP_EndDeviceBindRsp());如果没有匹配或无法保存则发送匹配失败信息End_Device_Bind_rsp给两个请求终端.(这里纯属个人大概的理解)在《Z-Stack 开发指南》中对End_Device_Bind_req的处理流程是这么描述的:------------------------------------当协调器接收到第一个绑定请求时,他会在一定的时限内保留这一请求并等待第二个请求的出现。

ZigBee中的API接口及结构体

ZigBee中的API接口及结构体

typedef struct{osal_event_hdr_t hdr; /* OSAL Message header *///OSAL消息头uint16 groupId; /* Message's group ID - 0 if not set *///消息组IDuint16 clusterId; /* Message's cluster ID *///消息族IDafAddrType_t srcAddr; /* Source Address, if endpoint isSTUBAPS_INTER_PAN_EP,it's an InterPAN message *///源地址类型uint16 macDestAddr; /* MAC header destination short address *///MAC物理地址uint8 endPoint; /* destination endpoint */ //目的端点uint8 wasBroadcast; /* TRUE if network destination was a broadcast address *///广播地址uint8 LinkQuality; /* The link quality of the received data frame */ //接收数据帧的链路质量uint8 correlation; /* The raw correlation value of the received data frame *///接收数据帧的未加工相关值。

int8 rssi; /* The received RF power in units dBm *///接收的射频功率。

uint8 SecurityUse; /* deprecated *///弃用uint32 timestamp; /* receipt timestamp from MAC *///收到时间标记。

ZIGBEE点播、组播、广播模式

ZIGBEE点播、组播、广播模式

zigbee单播、组播、广播单播:按照协议栈示例GenericApp中的用法:单播有两种方式一种是绑定传输,一种是直接指定目标地址的单播传输按照如下步骤:1.设定发送的目标地址GenericApp_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;GenericApp_DstAddr.endPoint = 0;GenericApp_DstAddr.addr.shortAddr = 0;设定发送的目标地址,这里地址模式AddrNotPresent,即按照绑定的方式进行单播,不需要指定目标地址,需要先将两个设备绑定,将两个设备绑定后即可通信还有另外三种传送方式,如下:enum{AddrNotPresent = 0,//按照绑定表进行绑定传输AddrGroup = 1,//组播传输Addr16Bit = 2,//指定目标网络地址进行单播传输Addr64Bit = 3,//指定IEEE地址进行单播传输AddrBroadcast = 15//广播传输};2.注册端点描述符// Fill out the endPoint description.GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;GenericApp_epDesc.task_id = &GenericApp_TaskID;GenericApp_epDesc.simpleDesc= (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc; GenericApp_tencyReq = noLatencyReqs;// Register the endpoint description with the AFafRegister( &GenericApp_epDesc );3.在需要发送数据的地方,执行如下代码:if ( AF_Datarequest( &GenericApp_DstAddr, &GenericApp_epDesc, GENERICAPP_CLUSTERID,(byte)osal_strlen( theMessageData ) + 1,(byte *)&theMessageData,&GenericApp_TransID,AF_DISCV_RoutE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ){// Successfully requested to be sent.}else{// Error occurred in request to send.}注意GENERICAPP_CLUSTERID必须为对方的输入cluster,且两方的简单描述符中的profileID必须一致4.在接收设备任务循环中检测AF_INCOMING_MSG_CMD事件:afIncomingMSGPacket_t结构的数据包进行处理afIncomingMSGPacket_t结构如下:typedef struct{osal_event_hdr_t hdr;uint16 groupId;uint16 clusterId;afAddrType_t srcAddr;byte endPoint;byte wasBroadcast;byte LinkQuality;byte SecurityUse;uint32 timestamp;afMSGCommandFormat_t cmd;} afIncomingMSGPacket_t;其中afMSGCommandFormat_t结构如下:typedef struct{byte TransSeqNumber;uint16 DataLength; // Number of bytes in TransData byte *Data;} afMSGCommandFormat_t; //提取出Data即可组播:按照SampleApp实验,组播的实现需要如下步骤:1.声明一个组对象aps_Group_t SampleApp_Group;2.对aps_Group_t结构体赋值,示例如下:// By default, all devices start out in Group 1SampleApp_Group.ID = 0x0003;osal_memcpy( SampleApp_, "Group 3", 7 );3.设定通信的目标地址,示例如下:// Setup for the flash command's destination address - Group 1SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;4.注册端点描述符,示例如下:// Fill out the endpoint description.SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;SampleApp_epDesc.task_id = &SampleApp_TaskID;SampleApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t*)&SampleApp_SimpleDesc; SampleApp_tencyReq = noLatencyReqs; // Register the endpoint description with the AFafRegister( &SampleApp_epDesc );5.在本任务里将端点加入到组中,示例如下:aps_AddGroup( SAMPLEAPP_ENDPoint, &SampleApp_Group );6.按照组播地址向对方发送数据,示例如下:if ( AF_Datarequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,SAMPLEAPP_PERIODIC_CLUSTERID,1,(uint8*)&SampleAppPeriodicCounter,&SampleApp_TransID,AF_DISCV_RoutE,AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ){ } else{ // Error occurred in request to send. }通信时候,发送设备的输出cluster设定为接收设备的输入cluster,另外profileID设定相同,即可通信7.对数据的处理与单播的实现一样8.若要把一个设备加入到组中的端点从组中移除,调用aps_RemoveGroup即可,示例如下:aps_Group_t *grp;grp = aps_FindGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP );if ( grp ){ // Remove from the groupaps_RemoveGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP );}广播:按照SampleApp,执行如下步骤即可1.声明afAddrType_t 的变量SampleApp_Periodic_DstAddr;2.设定目标地址变量为广播地址,示例如下:SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast; SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;3.进行数据发送,示例如下:if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID,1,(uint8*)&SampleAppPeriodicCounter,&SampleApp_TransID,AF_DISCV_ROUTE,AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ){ } else{ // Error occurred in request to send.}通信时候,发送设备的输出cluster设定为接收设备的输入cluster,另外profileID设定相同,即可通信4.对数据的处理与单播的实现一样。

运行Zigbee例程

运行Zigbee例程

Zigbee入门指导(二)/logiclimit——运行Zigbee例程logiclimit 在Zigbee入门指导(一)中讲解了基于CC2430的Zigbee开发环境的搭建,安装完Ti的协议栈后,里面有多个例程,帮助用户入门及作为自己工程的基本框架。

在Zigbee入门指导(二)中,我们将通过演示执行相关的例程,了解Zigbee应用的启动流程(不是Zigbee网络的启动流程),了解运行一个自定义Zigbee工程所要作的软件方面的改动和工程选项的配置。

所用的开发套件为无线龙的套件。

一、修改HALHAL及所谓的Hardware Abstration Layer,通俗的了解即为开发板的硬件驱动,由于所用的是无线龙的开发板,与Ti的原装开发板有差异,需要对协议栈自带的HAL进行修改。

HAL文件存放在目录<Components/hal>中,里面有<common>、<include>、<target>三个目录,<common>中定义的与外设无关的硬件操作,<include>存放的是头文件,而<target>存放的是目标文件,里面根据目标板的不同分为<CC2430BB>、<CC2430DB>、<CC2430EB>。

所用的无线龙的开发板和CC2430EB最为相似,故修改<CC2430EB>中的内容。

按键操作几乎在每个例程中都会用到,故此处以按键驱动的修改为例,演示HAL的修改。

先了解下Ti和无线龙扩展板的不同之处。

Ti的CC2430EB原理图在Ti文档SWRU133.pdf(位于SWRU133.zip中)。

Page29是按键电路的原理图,如图1图1(左上角是元件图)CC2430EB的按键其实是摇杆,上下左右四个方向和电阻网络相连,通过放大电路送到CC2430的P0.6脚,经AD采样后判断摇杆摆向哪个方向,按键编号为SW1~SW4摇杆也可像普通按键一样按下,产生一个直流电平变化,接到P0.5脚,按键编号为SW5。

长江大学Zigbee应用学习

长江大学Zigbee应用学习

文档的主要目的是引领初学者应用Z-Stack协议栈编写程序,完成自己想要的功能。

一些的基础的知识只做引导,因为大家可以很轻易的从网络和附属的文档中找到。

默认读者已经安装了开发需要的必需的软件,包括IAR FOR MCS-51,Packet Sniffer,Flash Programmer,和Z-Stack,这些软件件及安装方法在销售商附赠的资料中都会有的。

一般需要对某些硬件的驱动做修改,因为Z-Stack的硬件驱动对应的是TI公司的开发套件,有些部分和销售商的不同,附赠的资料中有修改的方法。

如有错误请不吝指教。

1、Zigbee是什么?有什么特点?2、CC2430、CC2530是什么?有什么特点?通过前两个问题,我们应该知道了Zigbee有哪些特点,什么是CC2530,片上有哪些资源,什么是协调器(Coordinator),路由器(Router),终端设备(End Device),他们可以组成的拓扑结构,以及各自在拓扑结构中的位置。

3、Z-Stack是什么?与Zigbee、CC2530、CC2430单片机有什么关系?通过上一个问题,我们知道了Z-Stack就是一堆代码,在上面添加我们要的功能后,CC2530单片机就可以遵循Zigbee协议进行通信。

而且大家也知道了用户需要做的只是APP 文件夹里屈指可数的几个文件的修改而已。

一切都很方便。

4、Z-Stack的结构5、Z-Stack如何执行任务(Z-Stack系统核心)?上一问主要是讲Z-Stack的流程,task ID 和events只是提及,“要执行任务的ID号idx和对应事件(tasksEvents[idx]的值代表)”,那他们从哪里来的,是什么关系6、任务(Task)与事件(Events)的关系7、怎么添加我们的任务?从上面我们知道了Z-Stack是一个轮询的结构,相关的触发方式将ID和Event置数后,轮到该优先级便执行对应的函数。

那这个函数是什么样子的?8、我们任务函数的结构我们想要的功能如何实现——GenericApp_ProcessEvent函数讲解到这里的时候,我们已经了解了系统的轮询过程,任务是如何被添加的,那我们想要的功能:接收信息,发送信息,按键,传感器采集等是如何在程序中实现的?9、发送、接收的函数分别是哪个函数?如何执行的?如何使用?10、协调器、路由器、终端:同一套程序,不同的编译。

2、自己理解zigbee有关的数据的发送和接收

2、自己理解zigbee有关的数据的发送和接收

哎呀研究这个数据的发送和收发研究了2天了。

今天终于把困扰我很久的一个问题给解决了。

问题:终端节点启动会为什么会自动的发送数据呢?解决过程:这个过程可是异常的艰辛。

要解决这个问题。

咱们先聊聊这个整个zigbee协议栈的工作流程。

程序肯定都是从main函数开始的,这个肯定也不例外。

大家查看一下main函数主要就是关闭中断,检查电源电压是否够高,还有就是初始化了,什么物理层,mac层等等。

而我们在这里关注2个函数就好了。

第一个是:osal_init_system();第二个:osal_start_system();第一个osal_init_system()函数就是初始化与系统运行相关的一些东西如:初始化内存分配系统,初始化消息队列,初始化定时器,初始化电源管理系统,初始化第一块堆,最后一个就是我们要讲的一个非常重要的函数:osalInitTasks();初始化任务函数void osalInitTasks( void )//系统任务初始化函数{uint8 taskID = 0;//这个指针指向了所有任务空间的首地址tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);//这个tasksEvents指针总共有多少个数据空间,其实总共有多少任务就有多少个空间。

osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));macTaskInit( taskID++ ); //mac层的任务是0nwk_init( taskID++ ); //网络层的任务是1Hal_Init( taskID++ ); //物理层的任务号是2#if defined( MT_TASK )MT_TaskInit( taskID++ );//串口的任务#endifAPS_Init( taskID++ );#if defined ( ZIGBEE_FRAGMENTATION )APSF_Init( taskID++ );#endifZDApp_Init( taskID++ );#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )ZDNwkMgr_Init( taskID++ );#endifGenericApp_Init( taskID );//应用程序的初始化。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

zigbee学习笔记3-通信例程之GenericApp2011-09-22 11:02刚入手的朋友,对Z-Stack 非常迷糊的时期,如果能够跑通几个例子、看几个演示,那么可以大大提高学习兴趣;另外如果知道某个例子的大致功能及实现,那么在去看具体实现过程目的性就非常明确。

首先来看看TI 究竟有哪些例子:可以看出其例子是非常丰富的。

GenericApp(设备互相绑定传送信息-hellow world),Location(定位),SampleApp(设备发送和接收LED灯信息),SimpleApp(温度和灯开关,和智能家居结合使用的,have Profile),HomeAutomation(智能家居的应用,have Profile),SerialApp(串行传输的应用),Transmit(发送应用),ZLOAD(协议文件夹中只有Source)。

这样看来还是不少的。

其中SampleApp 例子已经在前面的学习中有所涉及,可以说前面的所有学习都是基于这个例子的,所以这里就不测试它了。

Location 是定位的测试例子,这里我的硬件是不够的,所以也不做测试。

其他我都做点测试,能成功的就成功,不能成功的就失败,这个我也没办法。

1、GenericApp这个实验是两个模块相互绑定后可以对传数据,模块绑定之后,两个模块之间相互传输字符串"Hello World"。

实验说明:首先启动一个网络协调器,协调器如果建立网络成功后,会在LCD 上显示该节点为协调者同时显示网络ID号。

然后打开一个终端节点或路由器的电源,此时节点会自动加入网络。

加入网络成功后,节点会显示自己的节点类型、网络地址和父节点的网络地址。

节点加入网络成功后,首先把主机模块的摇杆往右拔一下,然后把要绑定模块的RIGHT按一下,如果两边的LED4 都熄灭或是点亮后马上熄灭,表示绑定成功。

绑定成功后,两个节点就开始相互定时发送数据,并在对方的LCD屏上显示出来,发送的数据为"Hello World"。

此时如果把相互绑定模块中的left 按一下,可以发送Match Description Request命令,对方则显示Match Description Request信息。

(以上无线龙手册提供)2 关键函数分析:我开始没搞清楚,功能是个啥大约浏览了下,这个例子似乎还与设备的所以还决定看看程序来判断这个例子的功能。

绑定有关系,在key control 描述中发现//***************** Key control**************************//SW2: initiates end device binding //--初始化中断设备绑定SW4: initiates a match description request //--初始化一个匹配描述请求2.1 按建处理程序中发现:if ( keys & HAL_KEY_SW_2 ){HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );// Initiate an End Device Bind Request for the mandatory endpointdstAddr.addrMode = Addr16Bit;dstAddr.addr.shortAddr = 0x0000; // CoordinatorZDP_EndDeviceBindReq( &dstAddr, NLME_GetShortAddr(),GenericApp_epDesc.endPoint,GENERICAPP_PROFID,GENERICAPP_MAX_CLUSTERS, (cId_t *)GenericApp_ClusterList,GENERICAPP_MAX_CLUSTERS, (cId_t *)GenericApp_ClusterList, FALSE );}很明显这里按键2(右键)是发送绑定请求的命令。

if ( keys & HAL_KEY_SW_4 ){HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );// Initiate a Match Deion Request (Service Discovery)dstAddr.addrMode = AddrBroadcast;dstAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR;ZDP_MatchDescReq( &dstAddr, NWK_BROADCAST_SHORTADDR, GENERICAPP_PROFID,GENERICAPP_MAX_CLUSTERS, (cId_t *)GenericApp_ClusterList,GENERICAPP_MAX_CLUSTERS, (cId_t *)GenericApp_ClusterList,FALSE );}显然按键4(左)是初始化一个匹配描述符请求,也就是发现服务,或者叫自动寻求匹配设备。

2.2在发送数据发现:void GenericApp_SendTheMessage( void ){char theMessageData[] = "Hello World";if ( AF_DataRequest( &GenericApp_DstAddr, &GenericApp_epDesc,GENERICAPP_CLUSTERID,(byte)osal_strlen( theMessageData ) + 1,(byte *)&theMessageData, &GenericApp_TransID,AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ){// Successfully requested to be sent.}else{// Error occurred in request to send.}}这里发送了"Hello World"字符串。

如果更改这里,是可以在接收端看到变化的。

这里调用了AF_DataRequest 函数,该函数为AF层请求发送数据函数。

afStatus_t AF_DataRequest( afAddrType_t *dstAddr, endPointDesc_t *srcEP,uint16 cID, uint16 len, uint8 *buf, uint8 *transID,uint8 options, uint8 radius )我想最关心的就是几个参数:1、目标地址:&GenericApp_DstAddrtypedef struct{union{uint16 shortAddr;} addr;afAddrMode_t addrMode;byte endPoint;} afAddrType_t;//--里面定义了目标地址模式、地址、EP三个参数2、端点描述符:&GenericApp_epDesctypedef struct{byte endPoint;byte *task_id; // Pointer to location of the Application task ID.SimpleDescriptionFormat_t *simpleDesc;afNetworkLatencyReq_t latencyReq;} endPointDesc_t;3、串ID#define GENERICAPP_CLUSTERID 14、发送数据数据长度:(byte)osal_strlen( theMessageData ) + 1,数据载荷:(byte *)&theMessageData,5、发送ID:&GenericApp_TransID6、选项:AF_DISCV_ROUTE#define AF_DISCV_ROUTE 0x207、发送半径:AF_DEFAULT_RADIUS#define AF_DEFAULT_RADIUS DEF_NWK_RADIUS网络路由深度,初始化为:#define DEF_NWK_RADIUS 102.3 接收处理函数发现:void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) ///接收处理函数{switch ( pkt->clusterId ){case GENERICAPP_CLUSTERID:// "the" message#if defined( LCD_SUPPORTED )// HalLcdWriteScreen( (char*)pkt->cmd.Data, "rcvd" );Print8(HAL_LCD_LINE_2,10," ", 1);Print8(HAL_LCD_LINE_3,10," ", 1);Print8(HAL_LCD_LINE_2,10,(INT8U*)pkt->cmd.Data, 1);Print8(HAL_LCD_LINE_3,16, "WXL Welcome", 1);break;#endif}}接收数据处理函数里居然要通过液晶显示,本人这里的液晶暂时没有移植过来,因为暂时还不具备那个实力,怪不得看不到发送数据的状况!这里本人就自作聪明的把以前SampleApp 例子里面的一句话加过来了:void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) //--修改的哦{switch ( pkt->clusterId ){case GENERICAPP_CLUSTERID:// "the" messageHalLedBlink( HAL_LED_4, 4, 50, (500) );#if defined( LCD_SUPPORTED )HalLcdWriteScreen( (char*)pkt->cmd.Data, "rcvd" );#elif defined( WIN32 )WPRINTSTR( pkt->cmd.Data );#endifbreak;}}麽想到啊,这么一加居然就有反应了!其实这里很简单的了,就是接收到数据后闪烁4 下灯,间隔0.5S。

相关文档
最新文档