Zigbee入门与实践第五章 Zigbee组网实战入门_第1页
Zigbee入门与实践第五章 Zigbee组网实战入门_第2页
Zigbee入门与实践第五章 Zigbee组网实战入门_第3页
Zigbee入门与实践第五章 Zigbee组网实战入门_第4页
Zigbee入门与实践第五章 Zigbee组网实战入门_第5页
已阅读5页,还剩71页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、JIAJIEKEJIZigBee 无线传感器网络入门佳杰科技Dan2012H T T P : / J I E L O V E D A N . T A O B A O . C O M //佳杰科技目录ZigBee 无线传感器网络入门3前言35.1 Zstack 协议栈45.1.1 什么是 ZigBee 协议栈45.1.2 如何使用 ZigBee 协议栈45.1.3 ZigBee 协议栈的安装、编译与下载5一个简单的无线传输组网实验65.2建立一个全新的 Zstack 工程7协调器编程11终端节点编程23测试步骤与效果32ZigBee 数据传输

2、实验剖析32数据发送32数据接收34Zigbee 数据包的捕获35ZigBee 数据包的结构37本实验数据分析3.....10数据收发无线组网实验405.4.1 首先提出要求405.4.2 操作系统编程及分析415.4.3 公共头文件的编程及分析435.4.4 协调器的编程及分析445.4.5 终端的编程及分析515.3.11测试步骤与效果54无线开关灯实验组网实现565.4.1 首先提出设计要求565.4.2 建立一个全新的工程的方法575.4.3 操作系统编程及分析595.4.4 公共头文件的编程及分

3、析615.4.5 协调器的编程及分析625.4.6 终端的编程与分析675.35.4/佳杰科技ZigBee 无线传感器网络入门前言本章教程讲授思路是,从实战出发,提出设计要求,然后开始协调器,终端的编程。一步一步的完成要求,并对代码进行分析。我们将 会对用到的函数加以详细的解释说明,配套开发板可以直接下载完成的组网代码进行结果的测试。ZigBee 无线传感器网络涉及电子、电路、通信、射频等多学科的知识,这对于入门级学习来说,无形中增加了学习难度,很多读者看协议、射频电路学了半年甚至更长的时间,但是连基本的点对点通信都无法实现,更别说根据对

4、ZigBee 协议的理解来实现正常的无线网络部署工作了。基于此原因,本书推荐另一种学习思路,不是将学习重点放在复杂的 ZigBee协议、射频、等知识,而是直接进行 ZigBee 无线网络点对点通信的学习,基本思路是:从发送端发送一个数据,接收端接收到数据后校验收到的数据是否正确,并给出相应的指示。很简单的功能,但是这里涉及以下问题:lllllll数据在协议栈里面是如何流动的;如何调用 ZigBee 协议栈提供的发送函数; 如何使用 ZigBee 协议栈进行数据的接收; 如何理解 ZigBee 协议栈;ZigBee 协议栈是采用分层的思想,各层都具有哪些功能;如何利用 ZigBee 协议栈提供的

5、函数来实现基本的无线传感器网络应用程序开发; 系统硬件对 ZigBee 协议都提供了哪些支持。一个看似简单得不能再简单的实验引起了读者对于 ZigBee 无线传感器网络技术方方面面的思考,也正是由于上述思考,笔者才鼓起勇气带领读者去探究 ZigBee无线网络的技术,触摸那神圣的无线通信世界,感知那“中”的无线传感器网络,读者的 ZigBee 无线传感器网络开发之旅由此开始本章只是带领读者从功能上理解协议栈,并没有给出具体的概念性的知识点, 展示了 ZigBee 无线网络中的数据传输过程,并没有对ZigBee。协议栈进行深入的讨论,在本书第 6 章中会对ZigBee。协议栈的构成及工作原理进行讨

6、论,本章的主要目的是使读者对 ZigBee 协议栈开发有个感性的认识。注意,本章用到的实验,都有完成好了的程序代码在本章文件夹里可以找到。大家可以先下载程序,观察执行效果,然后再开始分析,一步一步看程序代码是如何实现的。本章所涉及的程序都是组网完成,不牵涉路由器,这会在后面提到。在开始实验之前,有几点设计准备在前面提到过,这里 Zstack 安装的路径为D:ZStack-CC2530-2.3.0-1.4.0 安装的版本为 2.3.0-1.4.0,不同版本的协议栈会有所差异。IAR 开发软件采用的是 IAR Assembler for 8051 8.10.3 (0338),版本信

7、息在 IAR 软件中的 Help 栏的 About 栏的 Product info 中查看最顶部的编号。本实验的程序代码在文字提及的地方采用方框包围,提及的分析代码采用编号标注。1分析代码程序代码/佳杰科技5.1Zstack 协议栈进行 zigBee。无线传感器网络的开发,首先面临的问题是什么?是 ZigBee 协议栈,以及由此引发的如下问题:llZigBee 协议栈和zigBee 协议是什么关系;如何使用 ZigBee 协议栈进行应用程序的开发。下面对上述问题进行逐一讲解。5.1.1 什么是 ZigBee 协议栈协议定义的是一系列的通信标

8、准,通信双方需要共同按照这一标准进正常的数据收发;协议找是协议的具体实现形式,通俗的理解为用代码实现的函数库,以便于开发人员调用。ZigBee 的协议分为两部分,IEEE 802.15.4 定义了物理层和 MAC 层技术规范,ZigBee 联盟定义了网络层安全层和应用层技术规范,ZigBee 协议栈就是将各个层定义的协议都集合在一起,以函数的形式实现,并给用户提供一些应用层 API,供用户调用。注意:虽然协议是统一的,但是。的具体实现形式是变化的,即不同厂商提供的协议钱是有区别的,例如:函数名称和参数列表可能有区别,用户在选择协议找以后,需要学习具体的例子,查看厂商提供的 Dert10 演示程

9、序、说明文档(通常,实现协议栈的厂商会提供一些 API 手册供用户查询)来学习各个函数的使用方式,进而快速地使用协议栈进行应用程序的开发工作。使用 ZigBee 协议栈进行开发的基木思路可以概括为如下三点:l用户对于 ZigBee 无线网络的开发就简化为应用层的 C 语言程序开发,用户不需要深入研究复杂的 ZigBee 协议栈;ZigBee 无线传感器网络中数据采集,只需要用户在应用层加入传感器的读取函数即可;如果考虑到节能,可以根据数据采集周期进行定时,定时时间到就唤醒 ZigBee 的终端节点,终端节点唤醒后,自动采集传感器数据,然后将数据发送给路由器或者直接发给协调器。ll如何使用 Zi

10、gBee 协议栈5.1.2既然 ZigBee 协议栈已经实现了 ZigBee 协议,那么用户就可以使用协议栈提供的 API 进行应用程序的开发,在开发过程中完全不必关心 ZigBee 协议的具体实现细节,只需要关心一个核心的问题:应用程序数据从哪里来到哪里去。下面举个例子,当用户应用程序需要进行数据通信时,需要按照如下步骤实现:调用协议栈提供的组网函数、加入网络函数,实现网络的建立与节点的加入;发送设备调用协议栈提供的无线数据发送函数,实现数据的发送;接收端调用协议栈提供的无线数据接收函数,实现数据的正确接收。因此,使用协议栈进行应用程序开发时,开发者不需要关心协议栈是具体怎么实现的(例如:每

11、个函数是怎么实现的.每条函数代码是什么意思等),只需要知道协议栈提供的函数实现什么样的功能,会调用相应的函数来实现自己的应用要求即可。/佳杰科技技巧提示:在 TI 推出的ZigBee 2007 协议栈(又称作 Z-Stack )中数据发送函数如下:.5.6.7.afStatus_tAF DataRequest(afAddrType_ t *dstAddr,endPointDesc t *srcEP uintl6 cID, uintl6 len,uint8 *buf, uint8 *translD, uint8 options,

12、uintB radius)用户调用该函数即可实现数据的无线发送,当然,在此函数中有 8 个,用户需要将每个参数的含义理解以后,才能达到熟练应用该函数进行无线数据通信的目的。AF_DataRequest()函数中最核心的两个参数:ll3. uint16 1en一发送数据的长度;4. uint8 *buf指向存放发送数据的缓冲区的指针。至于调用该函数后,如何初始化硬件进行数据发送等工作,用户不需要关心,ZigBee 协议栈己经将所需要的初始化工作初始化了,这就类似于学习 TCP/IP 编程时,用户只需要调用相应的数据发送、接收函数即可,而不必关心具体的网卡驱动(如 DM9000, CS8900 网

13、卡是如何接收数据的)的具体实现细节。5.1.3 ZigBee 协议栈的安装、编译与下载ZigBee 协议栈具有很多版本,不同厂商提供的 ZigBee 协议栈有一定的区别,本书选用TI 公司推出的 ZigBee 2007 协议栈进行讲解。ZigBee 2007 协议栈ZStack-CC2530-2.3.0-1.4.0(可以在TI 的能使用,下面讲解安装步骤网站下载)需要安装以后才从 TI网站下载ZigBee 2007 协议栈 ZStack-CC2530-2.3.0-1.4.0.exe,双击ZStack-CC2530-2.3.0-1.4.O.exe,即可进行协议栈的安装,默认是安装到 C 盘根目录

14、下。在路径 D:ZStack-CC2530-2.3.0-1.4.0ProjectszstackSamples GenericAppCC2530SB 下找到 GenericApp.eww,如图 4-1 所示,打开该工程即可。打开该工程后,可以看到 GenericApp 工程文件布局,如图 4-2 所示。在图 4-2 所示的文件布局中,左侧有很多文件夹,如 App, HAL, MAC 等,这些文件夹对应了 ZigBee 协议中不同的层,使用ZigBee 协议栈进行应用程序的开发,一般只需要修改 App 目录下的文件即可。/佳杰科技图 4-1 G

15、eneri cApp.eww 工程路径选择不同工程还没有编译前程序部分 分层图 4-2 Generi cApp 工程文件布局提示:关于协议栈的编译与下载,请读者结合 4.2 节的数据传输实验进行学习,通过具体的实例来展示协议栈开发的基本流程是笔者推荐的学习方法。5.2一个简单的无线传输组网实验尽管到此为止,读者对 ZigBee 协议的基本内容都不了解,甚至 ZigB ee 协议栈是什么也/佳杰科技可能存在诸多的疑问与不解,但是笔者也是从这些“困难”中走出来的,也理解此时读者的心情,与其阅读那“深奥”的 ZigBee 协议栈,不如通过一个数据

16、传输实验来对 ZigBee 协议以及ZigBee 协议栈建立一个形象、直观的认识,这将有助于读者对 ZigBee 协议的理解。数据传输实验的基本功能:两个 ZigBee 节点进行点对点通信,ZigBee 节点 2 发送“LED”三个字符,ZigBee 节点 1 收到数据后,对接收到的数据进行判断,如果收到的数据是“LED, 则使开发板上的 LED 灯闪烁。数据传输实验原理图如图 4-3 所示。这就是一个简单的无线传输组网实验。“LED”ZigBee 无线网络ZigBee 节点2 终端节点ZigBee 节点1 协调器图 4-3 数据传输原理图5.3.1 建立一个全新的 Zstack 工程在 Zi

17、gBee 无线传感器网络中有三种设备类型:协调器、路由器和终端节点,设备类型是由 ZigBee 协议栈不同的编译选项来选择的。协调器主要负责网络组建、维护、控制终端节点的加入等。路由器主要负责数据包的路由选择,终端节点负责数据的采集,不具备路由功能。在本实验中,ZigBee 节点 1 配置为一个协调器,负责 ZieBee 网络的组建,ZieBee 节点 2配置为一个终端节点,上电后加入 ZigBee 节点 1 建立的网络,然后发送“LED”给节点 1 。打开 D:ZStack-CC2530-2.3.0-1.4.0ProjectszstackSamples 目录,这里是我们需要建立工程的地方,在

18、该目录下,以及有了3 个文件夹,分别是“GenericApp”“SampleApp”“SimpleApp”。下面介绍如何建立一个新的自己的 Zstack 工程。工程名为 TestA复制 GenericApp,到本目录下。将文件夹改名为 TestA复制粘贴后得到的文件夹/佳杰科技打开 TestASource 路径如下图。修改这 3 个文件名称,如下图所示。打开路径 TestACC2530DB,将里面的文件改为用记事本打开这 3 个文件,替换其中的 GenericApp 为TestA,然后保存。点击全部替换http:/jielovedan.ta

19、/佳杰科技打开目录 TestASource,替换该文件夹里面的 3 个文件中的 GenericApp 为 TestA,在 IAR 中打开工程。如下图所以:到这里,全新的工程就已经建立好了。将 TestA 工程的 TestA.h 和TestA.c 删除,方法是,点击 TestA.h 右键,选择下拉菜单中选择 Remove 即可。删除后如下图所示:点击编译/佳杰科技单机 File,在弹出的下拉菜单中选择 New,然后选择 File,如图所示,将该文件保存为Coordinator.h,然后用相同的方法建立 Coordinator.

20、c 和 Enddevice.c。保存的路径为SamplesTestASource。下面添加刚建立的文件到工程中来,方法是:右键点击 APP,选择 ADD,选择 Add files,选择刚刚建立的 3 个文件,打开即可。/佳杰科技图 4-7 添加完文件的 GenericApp 工程文件布局5.3.2 协调器编程下面开始程序代码的编写OSAL_TestA.c 文件编程1 #include ZComDef.h2 #include hal _dri vers .h3 #include OSAL.h4 #include OSAL_Tasks.h5/头

21、文件的包含/6 #if defined ( MT_TASK )7 #include MT.h8 #include MT_TASK.h9 #endif10 #include nwk.h11 #include APS.h12 #include ZDApp.h13 #if defined ( ZIGBEE_FREQ_AGILITY ) | defined ( ZIGBEE_PANID_CONFLICT )14 #include ZDNwkMgr.h15 #endif16 #if defined ( ZIGBEE_FRAGMENTATION )17 #include aps_fra g.h18 #en

22、dif/佳杰科技19#include Common.h20/任务注册/21 const pTaskEventHandlerFn tasks Arr = 22 macEventLoop,/MAC 任务循环23 nwk_event_loop,/网络层任务函数24 Hal_ProcessEvent,/硬件层函数25 #if defined( MT_TASK )26 MT_ProcessEvent,/串口支持层定义27 #endif28 APS_event_loop,/应用支持层任务函数29 #if defined ( ZIGBEE_FRAGMEN

23、TATION )30 APSF_ProcessEvent,31 #endif32 ZDApp_event_loop,/设备对象层函数33 #if defined ( ZIGBEE_FREQ_AGILITY ) | defined ( ZIGBEE_PANID_CONFLICT )34 ZDNwkMgr_e vent_loop,35 #endif36 GenericApp_ProcessEvent/自己定义的任务处理函数自己添加和任务37;38 const uint8 tasks Cnt = sizeof( tasksArr ) / sizeof( tasks Arr0 );39 uint16

24、*tasks Events ;40 void osalInitTasks( void )/为各个进程添加任务 ID,用作查找任务时用4142 uint8 taskID = 0;43 tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasks Cnt);44 osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasks Cnt);45 macTaskInit( taskID+ );/MAC 层的任务ID 号46 nwk_init( taskID+ );/网络ID 分配47 Hal

25、 _Ini t( taskID+ );/硬件ID 分配48 #if defined( MT_TASK )49 MT_TaskIni t( taskID+ );50 #endif51 APS_Init( taskID+ );52 #if defined ( ZIGBEE_FRAGMENTATION )53 APSF_Ini t( taskID+ );54 #endif55 ZDApp_Ini t( taskID+ );56 #if defined ( ZIGBEE_FREQ_AGILITY ) | defined ( ZIGBEE_PANID_CONFLICT )57 ZDNwkMgr_Ini

26、t( taskID+ );/佳杰科技该文件是操作系统初始化需要的部分,osalInitTasks()任务添加函数主函数文件位置操作系统程序化调用函数osalInitTasks()58 #endif59 Generi cApp_Init( taskID );/为自己的任务添加ID自己分配60/佳杰科技从上面看出,工程编译首先必须要定义 osalInitTasks()函数。那么工程要成功编译,还需要编译什么文件呢?tasksArr任务存放的位置,在操作系统中轮训会用到,所以必须初始化,这样编

27、译就可以通过了,协议栈这样可以完成网络建立,但是我们还没有添加自己的任务。自己的任务添加 tasksArr里面,任务在轮训时候可以查找到该任务,必须要分配一个任务的 ID。osalInitTasks()中添加。编写完成上面的文件后,点击保存,然后编译查看有无错误。第 1-19 行一些头文件的包含,这些格式比较固定,由于操作系统采用的是模块化程序设计,所以在调用其他层函数的时候,需要对其进行申明处理。那么头文件就起到这里这样的作用。第 20-37 行 操作系统的任务表,操作系统的所有任务都在这个表里,举一个例:系统查找到了任务 ID 为 1 的任务的Event 不是 0,那么其中就肯定有事情需要

28、操作系统去完成,那么系统就会根据任务的 ID 好,执行 tasks Arr1也就是执行这个函数nwk_event_loop。相信在这里大家对操作系统的运行有了一点点的了解,后面我们在详细了解。第 0-60 行 系统为任务分配 ID,其实就是把 1 2 3 4 5 6 的数输入到各个函数,然后在各个函数中记录任务的。这个就是查找任务时需要的标号。Common.h 头文件的编写1 #ifndef COMMON_H2 #define COMMON_H3 #include zComDef.h4 #define GENERICAPP_ENDPOINT 105 #define GENERICAPP_PRO

29、FID0x0F04/佳杰科技该文件定义了应用支持层的一些初始化参数。第 1-2 行 头文件的格式第 4. 行定义端第 5. 行定义规范 ID 这个参数没有太严格的要求,只要工程都一样就可以了,不一样也没有发现什么问题。呵呵呵。第 6.第 7.第 8.第 9.行定义器件的ID行定义器件的版本号行定义器件的标准行定义器件的最大族个数 就是定义一个数值,其最长有多少第 10. 行定义族的ID这个 ID 就是存放在数组中的第 11. 行固定格式Coordinator.c 文件的编写#include OSAL.h #include AF.h #inc

30、lude ZDApp.h #include ZDObject.h #include ZDProfile.h #include #include Common.h #include DebugTrace.h#if !defined( WIN32 ) #include OnBoard.h#endif/* HAL */#include hal_lcd.h #include hal_led.h #include hal_key.h #include hal_uart.h #include OSAL_Nv.hconst cId_t GenericApp_ClusterListGENERICAPP_MAX

31、_CLUSTERS =GENERICAPP_CLUSTERID;6 #define GENERICAPP_DEVICEID 0x00017 #define GENERICAPP_DEVICE_VERSION 08 #define GENERICAPP_FLAGS09 #define GENERICAPP_MAX_CLUSTERS110 #define GENERICAPP_CLUSTERID111 #endif/佳杰科技const SimpleDescriptionFormat_t GenericApp_SimpleDesc =GENERI

32、CAPP_ENDPOINT,/int Endpoint;GENERICAPP_PROFID,/uint16 AppProfId2;GENERICAPP_DEVICEID,/uint16 AppDeviceId2; GENERICAPP_DEVICE_VERSION,/intAppDevVer:4; GENERICAPP_FLAGS,/intAppFlags:4; GENERICAPP_MAX_CLUSTERS,/byteAppNumInClusters; (cId_t *)GenericApp_ClusterList,/byte *pAppInClusterList;0,/byteAppNum

33、InClusters; (cId_t *)NULL/byte *pAppInClusterList;endPointDesc_t GenericApp_epDesc; byte GenericApp_TaskID;byte GenericApp_TransID;void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pckt ); void GenericApp_SendTheMessage(void);void GenericApp_Init( byte task_id )GenericApp_TaskID = task_id; Generi

34、cApp_TransID = 0;GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT; GenericApp_epDesc.task_id = &GenericApp_TaskID; GenericApp_epDesc.simpleDesc= (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc; GenericApp_epDesc.latencyReq = noLatencyReqs;afRegister( &GenericApp_epDesc );UINT16 GenericApp_Proces

35、sEvent( byte 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 )/case 26:/佳杰科技12345678#include OSAL.h#include AF.h #include

36、ZDApp.h #include ZDObject.h #include ZDProfile.h #include #include Coorinator.h#include DebugTrace.h910#if !defined( WIN32 )#include OnBoard.hcase AF_INCOMING_MSG_CMD:GenericApp_MessageMSGCB(MSGpkt); break;default:break;osal_msg_deallocate( (uint8 *)MSGpkt );MSGpkt = (afIncomingMSGPacket_t *)osal_ms

37、g_receive( GenericApp_TaskID );return (events SYS_EVENT_MSG);return 0;void GenericApp_MessageMSGCB(afIncomingMSGPacket_t *pkt)unsigned char buf2; osal_memcpy(buffer,pkt-cmd.Data,3); switch ( pkt-clusterId )case GENERICAPP_CLUSTERID:osal_memcpy(buffer,pkt-cmd.Data,3);if(buffer0 = L) | (buffer1 = E) |

38、 (buffer2 = D)HalLedBlink(HAL_LED_2,0,50,500);elseHalLedSet(HAL_LED_2,HAL_LED_MODE_ON);break;/佳杰科技11#endif12131415#include hal_lcd.h#include hal_led.h #include hal_key.h#include hal_uart.h说明:上诉包含的头文件是从 GenericApp.c 文件复制得到的,只需要用#include“Coordinator.h”将 #include “GenericApp.

39、h” 替换即可,如上述代码中加粗字体部分所示。以下代码大部分是从 GenericApp.c 复制得到的,只是为了演示如何实现点对点通信,因此对 GenericApp.c 中的代码进行了裁剪。16const cId_t GemericApp_ClusterListGENERICAPP_MAX_CLUSTERS =17GENERICAPP_CLUSTERID;上述代码中的 GENERICAPP_MAX_CLUSTERS 是在 Coordinator.h 文件中定义的宏,这主要是为了跟协议栈里面数据的定义格式保持一致,下面代码中的常量都是以宏定义的形式实现的。18const SimpleDescri

40、ptionFormat_t GenericApp_SimpleDesc =GENERICAPP_ENDPOINT, GENERICAPP_PROFID, GENERICAPP_DEVICEID, GENERICAPP_DEVICE_VERSION, GENERICAPP_FLAGS, GENERICAPP_MAX_CLUSTERS,(cId_t *)GenericApp_ClusterList, 0,(cId_t *)NULL;192021222324252627上述数据结构可以用来描述一个 ZigBee 设备节点,称为简单设备描述符(此描述符包含了很多信息,读者在此可以按照上述格式使用,后面

41、实验都需要用到该结构体,用多了自然就熟悉了,在此没有必要机械地记忆该结构体)。282930endPointDesc_t GenericApp_epDesc;byte GenericApp_TaskID; byte GenericApp_TransID;上述代码定义了三个变量,一个是节点描述符 GenericApp_epDesc,一个是任务优先级GenericAppes_TaskID,最后一个是数据发送序列号 GenericApp_TransID。注意:上述代码中 endFointDesc_t 结构体(注意,在 ZigBee 协议中新定义的类型一般以“t 结尾)的定义较为复杂,下面是该结构体的定

42、义:typedef structbyte endPoint;/佳杰科技byte *task_id;SimpleDescriptionFormat_t *simpleDesc; afNetworkLatencyreq_t latencyReq; endPointDesc_t;31 void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );32 void GenericApp_SendT heMessage( void );上述代码声明了两个函数,一个是消息处理函数 GenericA

43、pp_MessageMSGCB ,另一个是数据发送函数 GenericApp_SendTheMessage。33void GenericApp_Init( byte task_id)genericApp_TaskID genericApp_TransID genericApp_epDesc.endPoint genericApp_epDesc.task_idgenericApp_epDesc.simpleDesc3435363738= task_id;= 0;= GENERICAPP_ENDPOINT;= &GenericApp_TaskID;= (SimpleDescriptionForma

44、t_t*)&GenericApp_SimpleDesc;= noLatencyReqs;3940genericApp_epDesc.latencyReqafRegister( &GenericApp_epDesc);上述代码是该任务的任务初始化函数,上述格式较为固定,读者可以以此作为自己应用程序开发的参考。第 34 行,初始化了任务优先级(任务优先级有协议栈的操作系统 OSAL 分配)。第 35 行,将发送数据包的序号初始化为 0,在 ZigBee 协议栈中,每发送一个数据包, 该发送序号自动加 1(协议栈里面的数据发送函数会自动完成该功能),因此在接收端可以查看接收数据包的序号来计算丢包率。

45、第 36-39 行,对节点描述符进行的初始化,上述初始化格式较为固定,一般不需要修改。第 40 行,使用 afRegister 函数将节点描述符进行注册,只有注册以后,才可以使用 OSAL提供的系统服务。41UINT16 GenericApp_ProcessEvent( byte task_id, UINT16 events )afIncomingMSGPacket_t *MSGpkt; if ( events & SYS_EVENT_MSG )MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(GenericApp_TaskID); whil

46、e (MSGPkt )switch ( MSGpkt-hdr.event )case AF_INCOMING_MSG_CMD GenericApp_MessageMSGCB( MSGpkt ); break;default:break;42434445464748495051/佳杰科技5253osal_msg_deallocate( (uint8 *)MSGpkt );MSGpkt = ( afIncomingMSGPacket_treturn (events SYS_EVENT_MSG);return 0;*)osal_msg_recei

47、ve( GenericApp_taskID);5455上述代码是消息处理函数,该函数大部分是固定的,读者不需要修改,是需要熟悉这种代码格式即可,唯一需要读者修改的代码是第 48 行,读者可以修改该函数的实现形式,但是其功能基本都是完成对数据的处理。注意:读者不必被上述各种新的数据类型迷惑,如果读者经过一段时间的学习对上述数据类型熟悉了,就会很容易看懂上述代码的功能,在此只需要熟悉上述代码的格式即可,除了第 48 行,其他都是固定的,不需要修改。下面从总体上讲解一下上述代码的功能(如果读者没有接触过 ZigBee 协议栈时,最基本的接收消息函数、消息结构是什么都不清楚,读者可以略过这些讲解,这里

48、主要考虑到有部分读者对 ZigBee 协议栈有一定的了解)。第 42 行,定义了一个指向接收消息结构体的指针 MSGpkt。第 44 行,使用 osal_msg_receive 函数从消息队列上接收消息,该消息中包含了接收到的无线数据包(准确地说是包含了指向接收到的无线数据包的指针)。第 47 行,对接收到的消息进行判断,如果是接收到了无线数据,则调用第 48 行的函数对数据进行相应的处理。第 52 行,接收到的消息处理完后,就需要释放消息所占据的存储空间,因为在ZigBee协议栈中,接收到的消息存放在堆上的,所以需要调用 osal_msg_deallocate 函数将其占据的堆内存释放,否则

49、容易引起“内存”。第 53 行,处理完一个消息后,再从消息队列里接收消息,然后对其进行相应的处理,直到所以消息都处理完为止。56void GenericApp_messageMSGCB( afIncomingMSGPacket_t *pkt)unsigned char buffer4 = ;switch ( pkt-clusterId )case GENERICAPP_CLUSTERID:osal_memcpy(buffer,pkt-cmd.Data,3);if(buffer0 = L) | (buffer1 = E) | (buffer2 = D)HalLedBlink(HAL_LED_2,

50、0,50,500);elseHalLedSet(HAL_LED_2,HAL_LED_MODE_ON);break;575859606162636465/佳杰科技上述代码中,字体加粗部分的格式是固定的,实现的基本功能如下: 第 60 行,将收到的数据拷贝到缓冲区 buffer 中。第 61 行,判断接收到的数据是不是“LED”三个字符,如果是这三个字符,则执行第 62行,使 LED2 闪烁,如果接收到的不是这三个字符,则点亮 LED2 即可。注意:上述代码使用到了 ZigBee 协议栈提供的函数 HalLedBlink(功能是: 使某个LSD

51、 闪烁)和 HafLedSet(功能是:设置某个 LED 的状态,如点亮、熄灭、状态翻转等),直接使用即可,这里需要提醒读者,使用协议栈进行应用程序开发时,如果协议栈已经提供了相应的函数,则只需要尽快掌握该函数的功能及使用方法即可,不需要另外实现该函数,其实,很多函数只要使用过一次以后,很快就会记住的。到此协调器的编程已经基本结束 1 下面回忆一下上述代码所做的基本工作。l删除了协议栈中的 GenericApp.h”和 GenericApp.c 文件,然后添加了三个文件:Coordinator.h, Coordinator.c 和 Enddevice.c 。给出了 Common.h 和 Coo

52、rdinator.c 的代码,并给出了部分注释,其中 Common.h文件中主要是一些宏定义,Coordinator.c 文件中很多代码格式是固定的,读者只需要熟悉上述代码格式即可。l下面还需要改动一下 OSAL_GenericApp.c 文件,因为我们需要自己添加任务,所以得在OSAL_TestA.c 文件添加自己的任务,需要在 OSAL_TestA.c 做如下的修改。在Workspace 下面的下拉列表框中选择CoordinatorEB,然后右键单击Enddevice.c 文件,在弹出的下拉菜单中选择 Options,如图 4-9 所示。在函数 osalInitTasks( void )最

53、后添加GenericApp_Init( taskID );/为任务分配在 const pTaskEventHandlerFn tasksArr数组的最后面添加GenericApp_ProcessEvent/佳杰科技图 4-9 选择 Options在弹出的对话框中,选择 Exclude form build,此时,Enddevice.c 文件呈灰白显示状态此时,可以打开 Tools 文件夹,可以看到 f8wEndev.cfg 和 f8wRouter.cfg 文件也是呈灰白显示状态,如图 4-12 所示,文件呈灰白显示状态说明该文件不参与编译,ZigBee 协议栈正是使用这种方式实现对源文件的控制。F8w2530.xc1、f8wConfig.cfg、f8wCoord.cfg 三个文件包含了节点的配置信息,具体功能如下:lf8W2530.xc1包含了 CC2530 单片机的链接控制指令(如定义堆栈大小、内存分配等),一般

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论