ZigBee组网(原理分析)

转自:http://wjf88223.blog.163.com/blog/static/351680012011731105424480/(小峰博客)


星形网络和树型网络可以看成是网状网络的一个特殊子集,所以接下来分析如何组建一个Zigbee网状网络。组建一个完整的Zigbee网络分为两步:第一步是协调器初始化一个网络;第二步是路由器或终端加入网络。加入网络又有两种方法,一种是子设备通过使用MAC层的连接进程加入网络,另一种是子设备通过与一个先前指定的父设备直接加入网络。 

一、 协调器初始化网络

    协调器建立一个新网络的流程如图1所示。


图1 协调器建立一个新网络

 

1、  检测协调器

建立一个新的网络是通过原语NLME_NETWORK_FORMATION.request发起的,但发起NLME_NETWORK_FORMATION.request原语的节点必须具备两个条件,一是这个节点具有ZigBee协调器功能,二是这个节点没有加入到其它网络中。任何不满足这两个条件的节点发起建立一个新网络的进程都会被网络层管理实体终止,网络层管理实体将通过参数值为INVALID_REQUEST的NLME_NETWORK_FORMATION.confirm的原语来通知上层这是一个非法请求。

2、  信道扫描

协调器发起建立一个新网络的进程后,网络层管理实体将请求MAC子层对信道进行扫描。信道扫描包括能量扫描和主动扫描两个过程。首先对用户指定的信道或物理层所有默认的信道进行一个能量扫描,以排除干扰。网络层管理实体将根据信道能量测量值对信道进行一个递增排序,并且抛弃能量值超过了可允许能量值的信道,保留可允许能量值内的信道等待进一步处理。接着在可允许能量值内的信道执行主动扫描,网络层管理实体通过审查返回的PAN描述符列表,确定一个用于建立新网络的信道,该信道中现有的网络数目是最少的,网络层管理实体将优先选择没有网络的信道。如果没有扫描到一个合适的信道,进程将被终止,网络层管理实体通过参数仠为STARTUP_FAILURE的NLME_NETWORK_FORMATION.confirm的原语来通知上层初始化启动网络失败。

3、配置网络参数

如果扫描到一个合适的信道,网络层管理实体将为新网络选择一个PAN描述符,该PAN描述符可以是由设备随机选择的,也可以是在NLME_NETWORK_FORMATION.request里指定的,但必须满足PAN描述符小于或等于0x3fff,不等于0xffff,并且在所选信道内是唯一的PAN描述符,没有任何其它PAN描述符与之是重复的。如果没有符合条件的PAN描述符可选择,进程将被终止,网络层管理实体通过参数值为STARTUP_FAILURE的NLME_NETWORK_FORMATION.confirm的原语来通知上层初始化启动网络失败。确定好PAN描述符后,网络层管理实体为协调器选择16位网络地址0x0000,MAC子层的macPANID参数将被设置为PAN描述符的值,macShortAddress PIB参数设置为协调器的网络地址。

4、运行新网络

网络参数配置好后,网络层管理实体通过MLME_START.request原语通知MAC层启动并运行新网络,启动状态通过MLME_START.confirm原语通知网络层,网络层管理实体再通过NLME_NETWORK_FORMATION.confirm原语通知上层协调器初始化的状态。

5、允许设备加入网络

只有ZigBee协调器或路由器才能通过NLME_PERMIT_JOINING.request原语来设置节点处于允许设备加入网络的状态。当发起这个进程时,如果PermitDuration参数值为0x00,网络层管理实体将通过MLME_SET.request原语把MAC层的macAssociationPermit PIB属性设置为FALSE,禁止节点处于允许设备加入网络的状态;如果PermitDuration参数值介于0x01和0xfe之间,网络层管理实体将通过MLME_SET.request原语把macAssociationPermit PIB属性设置为TRUE,并开启一个定时器,定时时间为PermitDuration,在这段时间内节点处于允许设备加入网络的状态,定时时间结束,网络层管理实体把MAC层的macAssociationPermit PIB属性设置为FALSE;如果PermitDuration参数的值为0xff,网络层管理实体将通过MLME_SET.request原语把macAssociationPermit PIB属性设置为TRUE,表示节点无限期处于允许设备加入网络的状态,除非有另外一个NLME_PERMIT_JOINING.request原语被发出。允许设备加入网络的流程如图2所示。


图2 允许设备加入网络

 

    通过以上流程协调器就建立了一个网络并处于允许设备加入网络的状态,然后等待其它节点加入网络。

 

二、 节点加入网络

    一个节点加入网络有两种方法,一种是通过使用MAC层关联进程加入网络,另一种是通过与先前指定父节点连接而加入网络。

 

1) 通过MAC层关联加入网络

    子节点请求通过MAC关联加入网络进程如图3所示。父节点响应通过MAC关联加入网络进程如图2-6所示。

1、  子节点发起信道扫描

子节点通过NLME_NETWORK_DISCOVERY.request原语发起加入网络的进程,网络层接收到这个原语后通过发起MLME_SCAN.request原语请求MAC层执行一个主动扫描或被动扫描以接收包含了PAN标志符的信标帧,扫描的信道以及每个信道的扫描时间分别由NLME_NETWORK_DISCOVERY.request原语的参数ScanChannels和ScanDuration决定。

2、  子节点存储各PAN信息

MAC层通过MLME_BEACONNOTIFY.indication原语将扫描中接收到的信标帧信息发送到网络层管理实体,信标帧信息包括信标设备的地址、是否允许连接以及信标净载荷。如果信标净载荷域里的协议ID域与自己的协议ID相同,子设备就将每个匹配的信标帧相关信息保存在邻居表中。信道扫描完成后,MAC层通过MLME_SCAN.confirm原语通知网络层管理实体,网络层再通过NLME_NETWORK_DISCOVERY.confirm原语通知上层,该原语包含了每个扫描到的网络的描述符,以便上层选择一个网络加入。

3、  子节点选择PAN

如果上层需要发现更多网络,则可以重新执行网络发现,如果不需要,则通过NLME_JOIN.request原语从被扫描到的网络中选择一个网络加入。参数PANID设置为被选择网络的PAN标识符。

4、  子节点选择父节点

一个合适的父节点需要满足三个条件:匹配的PAN标志符、链路成本最大为3、允许连接,为了寻找合适的父节点,NLME_JOIN.request原语请求网络层搜索它的邻居表,如果邻居表中不存在这样的父节点则通知上层,如果存在多个合适的父节点则选择具有最小深度的父节点,如果存在多个具有最小深度的合适的父节点则随机选择一个父节点。

5、  子节点请求MAC关联

确定好合适的父节点后,网络层管理实体发送一个MLME_ASSOCIATE.request原语到MAC层,地址参数设置为已选择的父节点的地址,尝试通过父节点加入网络。

6、  父节点响应MAC关联

父节点通过MLME_ASSOCIATE.indication原语通知网络层管理实体一个节点正尝试加入网络,网络层管理实体将搜索它的邻居表查看是否有一个与尝试加入节点相匹配的64位扩展地址,以便确定该节点是否已经存在于它的网络中了。如果有匹配的扩展地址,网络层管理实体获取相应的16位网络地址并发送一个连接响应到MAC层。如果没有匹配的扩展地址,在父节点的地址分配空间还没耗尽的条件下网络层管理实体将为尝试加入的节点分配一个16位网络地址。如果父节点地址分配空间耗尽,将拒绝节点加入请求。当同意节点加入网络的请求后,父节点网络层管理实体将使用加入节点的信息在邻居表中产生一个新的项,并通过MLME_ASSOCIATE.request原语通知MAC层连接成功。

7、  子节点响应连接成功

如果子节点接收到父节点发送的连接成功信息,发送一个传输成功响应信息以确认接收,然后子节点MAC层将通过MLME_ASSOCIATE.confirm原语通知网络层,原语包含了父节点为子节点分配的网内唯一的16位网络地址,然后网络层管理实体设置邻居表相应邻居设备为它的父设备,并通过NLME_JOIN.confirm原语通知上层节点成功加入网络。

8、  父节点响应连接成功

父节点接收到子节点的传输成功响应信息后,将通过MLME_COMM_STATUS.indication原语将传输成功的响应状态发送给网络层,网络层管理实体通过NLME_JOIN.indication原语通知上层一个节点已经加入了网络。

 



图3 子节点请求加入网络进程

 



图4 父节点响应加入网络进程

 

2) 通过与先前指定父节点连接加入网络

    子节点通过与指定的父节点直接连接加入网络,这个时候父节点预先配置了子节点的64位扩展地址。父节点处理一个直接加入网络的进程如图5所示。子节点通过孤立方式加入网络进程如图6所示。

 

1、  父节点处理子设备直接加入网络

父节点通过NLME_DIRECT_JOIN.request原语开始处理一个设备直接加入网络的进程。父节点网络层管理实体将首先搜索它的邻居表查看是否存在一个与子节点相匹配的64位扩展地址,以便确定该节点是否已经存在于它的网络中了。如果存在匹配的扩展地址,网络层管理实体将终止这个进程并告诉上层该设备已经存在于设备列表中了。如果不存在匹配的扩展地址,在父节点的地址分配空间还没耗尽的条件下网络层管理实体将为子节点分配一个16位网络地址,并使用子节点的信息在邻居表中产生一个新的项。然后通过NLME_DIRECT_JOIN.confirm原语上层设备已经加入网络。

2、  子节点连接父节点确认父子关系

子节点通过NLME_JOIN.request原语发起孤立扫描来建立它与父节点之间的关系。这时网络层管理实体将通过MLME_SCAN.request请求MAC层对物理层所默认的所有信道进行孤立扫描,如果扫描到父设备,MAC层通过MLME_SCAN.confirm原语通知网络层,网络层管理实体再通过NLME_JOIN.confirm原语通知上层节点请求加入成功,即与父节点建立了父子关系,可以互相通信。

 


图5 父节点处理一个直接加入网络进程

 


图6 子节点通过孤立方式加入网络进程

ZigBee组网流程如下: 1. 初始化协调器,设置协调器的PAN ID和网络信道。 2. 启动协调器,等待设备加入网络。 3. 初始化设备,设置设备的PAN ID和网络信道。 4. 启动设备,加入网络。 5. 协调器接收到设备的加入请求后,将设备加入网络并分配短地址。 6. 设备加入网络后,进行路由表的更新和路由发现。 以下是一个简单的ZigBee组网的示例代码,使用了TI的Z-Stack协议栈: ```c #include "ZComDef.h" #include "AF.h" #include "ZDApp.h" #include "ZDObject.h" #include "ZDProfile.h" #include "ZDConfig.h" #include "OSAL.h" #include "hal_defs.h" #include "hal_drivers.h" #include "hal_key.h" #include "hal_lcd.h" #include "hal_led.h" #include "hal_uart.h" #include "hal_timer.h" #include "mac_api.h" #include "aps.h" #define APP_ENDPOINT 1 #define APP_MSG_ID 0x10 #define APP_MSG_LEN 2 typedef struct { uint8 cmd; uint8 param; } appMsg_t; static uint8 appState = 0; static void appSendMsg(uint16 dstAddr, uint8 cmd, uint8 param) { appMsg_t *msg; uint8 bufLen = APP_MSG_LEN + sizeof(afAddrType_t); uint8 *buf = osal_mem_alloc(bufLen); if (buf != NULL) { msg = (appMsg_t *)(buf + sizeof(afAddrType_t)); msg->cmd = cmd; msg->param = param; afAddrType_t dstAddr; dstAddr.addrMode = afAddr16Bit; dstAddr.endPoint = APP_ENDPOINT; dstAddr.addr.shortAddr = dstAddr; AF_DataRequest(&dstAddr, &epDesc, APP_MSG_ID, bufLen, buf); osal_mem_free(buf); } } static void appRecvMsg(afIncomingMSGPacket_t *pkt) { if (pkt->clusterId == APP_MSG_ID) { appMsg_t *msg = (appMsg_t *)(pkt->cmd.Data); if (msg->cmd == 0x01) { halLedToggle(1); appState = msg->param; } } } static void appInit(void) { appState = 0; uint8 *extAddr = NULL; uint16 shortAddr = NLME_GetShortAddr(); uint8 bufLen = 8 + sizeof(afAddrType_t); uint8 *buf = osal_mem_alloc(bufLen); if (buf != NULL) { osal_memcpy(buf + sizeof(afAddrType_t), &shortAddr, sizeof(uint16)); osal_memcpy(buf + sizeof(afAddrType_t) + sizeof(uint16), extAddr, 8); ZDP_MgmtPermitJoinReq((afAddrType_t *)buf, 0); osal_mem_free(buf); } } void appMainLoop(void) { if (appState == 0) { appSendMsg(0xFFFF, 0x01, 0x01); } else if (appState == 1) { appSendMsg(0x0000, 0x01, 0x02); } else if (appState == 2) { appSendMsg(0x0001, 0x01, 0x03); } } void afIncomingMessage(afIncomingMSGPacket_t *pkt) { appRecvMsg(pkt); } void afDataConfirm(afStatus_t status) {} void ZDApp_Init(void) { appInit(); } uint16 ZDApp_eventLoop(uint8 taskId, uint16 events) { appMainLoop(); return events; } void main(void) { HAL_BOARD_INIT(); osal_init_system(); ZDApp_Init(); ZDApp_Startup(); while (1) { osal_run_system(); } } ``` 这个示例代码简单地实现了一个ZigBee设备的状态机,根据设备的状态依次发送不同的消息。在初始化时,设备向协调器发送一个Mgmt_Permit_Join_Req请求,允许其他设备加入网络。在主循环中,设备根据状态发送不同的消息,消息包括命令和参数,协调器接收到消息后进行处理并发送响应。当设备收到响应时,根据响应的参数更新设备的状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值