外观
2.3 ZigBee 3.0 组网实验
学习提示
本节课讲解多个理论知识,理解起来并不容易,如果暂时不理解也没关系,随着后续的学习,相信大家会逐步加深理解!
上节课学习了 BDB Commissioning Modes 基本原理之后,本节课讲解怎么样实现设备之间的网络组建。
一. 裁剪应用层 UI
(1)协议栈裁剪是开发者需要掌握的一项技术,因为 Z-Stack 3.0 包含了丰富的功能,但是在实际的开发过程中,部分功能可能是冗余的,甚至会影响到开发过程。
(2)打开本章节配套的工程代码,展开 App 层代码,如图所示。

(3)红框中的两个文件是针对 TI 的评估板而设计的 UI,在产品开发过程并不需要用到,而且还会影响其他的开发工作,因此需要把它们裁剪掉。右击文件,选择 Remove,如图所示。

(4)裁剪后如图所示。

(5)zcl_samplesw.c 文件中会调用到这些 UI,也需要把其全部删除。点击 Edit,然后选择 Find and Replace → Find in Files...,如图所示。

(6)在弹出的窗口中输入"UI_",然后点击 Find 按钮,如图所示。

(7)最后,在文件 zcl_samplesw.c 中根据搜索结果,一个一个地把带"UI_"的地方删除,如图所示。

(8)正确删除完成后,工程代码是可以编译通过的。
二. 编写设备组网代码
(1)如同前面章节所述,设备组网代码非常简单:
第一步,调用 bdb_StartCommissioning() 让协调器创建网络。
第二步,还是调用 bdb_StartCommissioning(),让其他设备加入到网络。
(2)角色判断
在编译工程的时候,可以选择让编译出来的程序工作在协调器(Coordinator)中、路由器(Router)中或者终端(EndDevice)中,即选择设备在 ZigBee 网络中的角色。在代码中,可以利用宏 ZDO_COORDINATOR 来判断当前的工作模式,判断方法是如果宏 ZDO_COORDINATOR 被定义了,那么说明程序工作在协调器环境中,否则就是工作在路由器或者终端环境中。
(3)编写代码
在 zcl_samplesw.c 的初始化函数 zclSampleSw_Init() 中添加如下代码:
c
#ifdef ZDO_COORDINATOR
bdb_StartCommissioning( BDB_COMMISSIONING_MODE_NWK_FORMATION |
BDB_COMMISSIONING_MODE_FINDING_BINDING );
NLME_PermitJoiningRequest(255);
#else
bdb_StartCommissioning( BDB_COMMISSIONING_MODE_NWK_STEERING |
BDB_COMMISSIONING_MODE_FINDING_BINDING );
#endif代码比较简单,如果是协调器那么就让协调器创建网络,如果是路由器或者终端那么就加入到网络。
其中的 NLME_PermitJoiningRequest(255) 是允许其他设备加入到由本协调器创建的网络中,这一点在介绍 Network Formation 时也有讲述过,也就是设备要经过信任中心的同意才能加入到网络中。参数 255 表示一直允许,如果改为 0 则表示一直不允许;如果改为 1~254 表示在 1~254 秒内允许。
三. 处理设备入网失败
(1)然而,设备入网的过程可能会受到多种因素的影响,从而导致入网失败,例如在入网过程信号受到干扰等。开发者需要学会处理设备入网失败。一种简单而有效的办法就是在设备入网失败后,让设备自动重新尝试入网。
(2)在 zcl_samplesw.c 文件中可以找到一个 zclSampleSw_ProcessCommissioningStatus() 函数,这个函数的作用是处理 Commissioning 结果,例如协调器创建网络是否成功、设备是否成功加入到网络等。
(3)可以在这个函数中根据 Commissioning 的结果采取相应的处理,例如在设备入网失败后重新调用 bdb_StartCommissioning() 来再次入网。
(4)可以用事件的机制来实现这个过程,当设备入网失败后就启动一个事件,让程序在 1s 后重新尝试入网。Z-Stack 3.0 的事件使用方法在前面的章节已经讲解过了,这里就不再讲了,而是直接使用。
(5)在头文件 zcl_samplesw.h 定义一个用户事件,并且定义重新入网的时间间隔,代码如下:
c
/* 协调器 */
#ifdef ZDO_COORDINATOR
/* 路由器或者终端 */
#else
// 重新加入事件
#define SAMPLEAPP_REJOIN_EVT 0x0100
// 时间间隔:1000ms(1秒)
#define SAMPLEAPP_REJOIN_PERIOD 1000
#endif由于设备入网是针对路由器或者终端类型的 ZigBee 设备的,因此同样地使用了宏来判断程序角色。
(6)在函数 zclSampleSw_ProcessCommissioningStatus 中找到入网失败处理位置,如图所示。

(7)在入网失败的位置添加如下代码:
c
/* 协调器 */
#ifdef ZDO_COORDINATOR
/* 路由器或者终端 */
#else
/* 启动重新加入事件 */
osal_start_timerEx(zclSampleSw_TaskID,
SAMPLEAPP_REJOIN_EVT,
SAMPLEAPP_REJOIN_PERIOD);
#endif代码中,首先判断设备角色,然后启动刚才定义的事件。
开发者也可以在入网成功的位置添加一些代码,例如在显示器上显示入网成功的信息等。
(8)在应用层事件处理函数 zclSampleSw_event_loop() 中处理该事件,也就是重新启动入网,代码如下。
c
#ifdef ZDO_COORDINATOR
#else
if ( events & SAMPLEAPP_REJOIN_EVT ) //如果事件类型为重新加入网络事件
{
/* 重新加入网络 */
bdb_StartCommissioning(BDB_COMMISSIONING_MODE_NWK_STEERING |
BDB_COMMISSIONING_MODE_FINDING_BINDING );
return ( events ^ SAMPLEAPP_REJOIN_EVT );
}
#endif四. 编译下载
(1)角色选择
前文中多次提及到设备的网络角色,其实在编译代码的时候可以选择不同的网络角色,从而编写不同角色的程序。
在工程中单击选项卡,可以看到如图所示的选择框,可以选择待开发设备的对应的工作模式。

其中 CoordinatorEB、RouterEB、EndDeviceEB 的含义分别是:
(1)CoordinatorEB:协调器角色设备。
(2)RouterEB:路由器角色设备。
(3)EndDeviceEB:终端角色设备。
除了此之外,还有 EndDeviceEB-OTAClient 和 RouterEB-OTAClient,其实这两个指的是带 OTA 功能的终端设备和带 OTA 功能的路由设备。
(2)使用角色
(2-1)首先选择 CoordinatorEB,如图所示。编译完成后下载到其中一块开发板中,建议使用 ZigBee 3.0 Mini 板。此开发板在 ZigBee 网络中会充当协调器角色设备。

(2-2)选择 RouterEB,如图所示。同样编译完成后下载到另一个板子中,建议使用 ZigBee 3.0 标准板。此开发板 ZigBee 网络中即会充当路由器角色设备。

注意
切换工程后,同样需要在工程的预编译那里开启 LED、串口、显示屏等功能,并且把屏幕的路径加入到工程中。
五. 仿真调试
(1)给协调器上电后,协调器会自动创建网络。创建网络成功后,在屏幕上可以看到网络 ID(PanID),如图所示。

(2)接着给路由器或终端上电后,它会自动加入到由协调器创建的网络中,加入后可以在屏幕上看到被分配到的网络地址和父节点的网络地址,路由器或终端设备加入后如图所示。
- 路由器

- 终端

六. 常见问题处理
路由器(节点)无法加入协调器 ?
搭建项目时,务必按照以下顺序执行:
(1)先烧录「协调器」固件并上电;
(2)后烧录路由器(节点)固件,并上电;
(3)路由器(节点)会自动搜索协调器,并加入其中。
(4)如路由器(节点)仍没有自动加入,按一下协调器中的 Reset 按键重启协调器,路由器(节点)也可自动加入。
路由器(节点)如何加入新的协调器中 ?
一个简单的方法是:
(1)重新烧录「路由器(节点)」固件;
(2)烧录完成后,会自动搜索协调器并加入到其中。
实验要点
本节课完成了 ZigBee 3.0 组网实验的全流程:裁剪冗余 UI → 编写组网代码(协调器创建网络 / 设备加入网络)→ 处理入网失败自动重连 → 选择设备角色编译下载 → 仿真调试观察结果。核心 API 仍是 bdb_StartCommissioning() + NLME_PermitJoiningRequest(),配合事件机制实现入网失败自动重试。
内容来源:紫甲 IoT《ZigBee 3.0 开发指南》第四部分·2.3 ZigBee 3.0 组网实验,原站链接
AI 伴学本章知识点智能答疑
👋 你好!我是本节课程的 AI 伴学助手。
可以问我:
请先 配置模型 API 后开始对话