实验一:Z-Stack 简单组网实验
一句话理解
本实验直接利用《2.3 ZigBee 3.0 组网实验》的组网方法完成网络组建,并在此基础上做一件事:在入网成功的位置插入 Terminal(串口终端)打印,把 PAN ID、信道、短地址、父节点等网络信息实时打印到 PC 端,作为组网成果的"验收凭证"。
前置知识
本实验完全基于 2.3 ZigBee 3.0 组网实验 一节的知识,请先按该章节完成:
- 裁剪应用层冗余 UI(删除
UI_相关内容); - 编写组网代码:
- 协调器:
bdb_StartCommissioning(BDB_COMMISSIONING_MODE_NWK_FORMATION | BDB_COMMISSIONING_MODE_FINDING_BINDING)+NLME_PermitJoiningRequest(255); - 路由器/终端:
bdb_StartCommissioning(BDB_COMMISSIONING_MODE_NWK_STEERING | BDB_COMMISSIONING_MODE_FINDING_BINDING);
- 协调器:
- 选择设备角色(CoordinatorEB / RouterEB / EndDeviceEB)编译下载;
- 观察协调器屏幕显示 PanID、节点屏幕显示 网络地址与父节点地址。
本实验的增量是:在入网成功的位置,用串口终端打印辅助信息,替代/补充屏幕显示,便于批量验证与记录。
实验目的
- 掌握 ZigBee 网络组建全流程(复用 2.3 章节知识:协调器建网、设备入网);
- 掌握 在入网成功处插入 Terminal 打印的方法(串口输出网络参数);
- 能够用 PC 端串口终端"验收"组网成果(PAN ID 一致、地址分配正确)。
实验器材
| 器材 | 数量 | 用途 |
|---|---|---|
| GEC2530 开发板 | 3 块 | 1 协调器 + 1 路由器 + 1 终端 |
| ZigBee 仿真器 | 1 个 | 烧录程序 |
| USB 转串口线 | 1~3 根 | 节点 → PC 串口终端 |
| 串口调试助手 / Xshell | 1 套 | Terminal 打印观察 |
| IAR EW for 8051 | 1 套 | 编译工程 |
实验原理
组网与终端打印的整体流程
→ 建网成功 → 终端打印 "NETWORK UP"
→ 入网成功 → 终端打印 "JOIN OK"
PAN ID / 信道 / 短地址 / 父节点
为什么要用终端打印?
2.3 章节中组网成果显示在开发板 LCD 屏幕上,但 LCD 字符少、难记录。把同样的信息打印到串口终端,可以:
- 一次性看到完整网络参数(PAN ID、信道、短地址、父节点、扩展地址);
- 在 PC 端留存日志,方便实验报告截图与多节点批量验证;
- 与上位机开发衔接(后续实验六的串口数据链路就是从这里起步)。
打印哪些信息?
| 打印项 | 获取 API | 含义 |
|---|---|---|
| PAN ID | _NIB.nwkPanId | 网络号,同一网络内所有节点相同 |
| 信道 CH | _NIB.nwkLogicalChannel | 无线通信通道 |
| 短地址 Addr | NLME_GetShortAddr() | 入网后分配的 16 位地址 |
| 父节点 Parent | NLME_GetCoordShortAddr() | 所挂接的上级节点地址 |
| 扩展地址 ExtAddr | NLME_GetExtAddr() | 芯片唯一 64 位地址 |
实验步骤
步骤 1:按 2.3 章节完成组网工程
- 打开 Z-Stack 3.0.1 的 SampleSwitch 工程(与 2.3 章节一致);
- 完成 UI 裁剪、组网代码、入网失败自动重连(可选用);
- 分别编译 CoordinatorEB / RouterEB / EndDeviceEB 三个角色固件。
步骤 2:编写终端打印函数
在应用层(如 zcl_samplesw.c)添加一个网络信息打印函数:
#include <stdio.h> // 使用 sprintf 需要
/* 打印网络信息到串口终端 */
static void PrintNetworkInfo(uint8 *tag)
{
uint8 buf[64];
uint16 panId = _NIB.nwkPanId; // 网络号
uint8 channel = _NIB.nwkLogicalChannel; // 信道
uint16 addr = NLME_GetShortAddr(); // 本节点短地址
uint16 parent = NLME_GetCoordShortAddr(); // 父节点地址
// 组装一行文本: [标签] PAN:0xXXXX CH:X Addr:0xXXXX Parent:0xXXXX
sprintf((char *)buf, "[%s] PAN:0x%04X CH:%d Addr:0x%04X Parent:0x%04X\r\n",
tag, panId, channel, addr, parent);
// 通过串口 0 输出到 PC 终端
HalUARTWrite(0, buf, osal_strlen((char *)buf));
}步骤 3:在入网成功处插入打印
方式 A(推荐,通用):在应用层事件循环的 ZDO_STATE_CHANGE 事件中,判断入网成功状态后打印:
case ZDO_STATE_CHANGE:
{
// devState 为设备当前网络状态
if (devState == DEV_ZB_COORD)
{
PrintNetworkInfo("NETWORK UP"); // 协调器建网成功
}
else if (devState == DEV_ROUTER || devState == DEV_END_DEVICE)
{
PrintNetworkInfo("JOIN OK"); // 路由器/终端入网成功
}
}
break;方式 B(与 2.3 章节衔接):在 zclSampleSw_ProcessCommissioningStatus() 的入网成功分支中插入:
/* 协调器 */
#ifdef ZDO_COORDINATOR
/* 建网成功 */
PrintNetworkInfo("NETWORK UP");
/* 路由器或者终端 */
#else
/* 入网成功 */
PrintNetworkInfo("JOIN OK");
#endif提示
- 串口初始化已在 2.3 章节的工程预编译中开启(LED、串口、显示屏等功能),无需额外配置;
- 方式 A 通用性更强(SampleApp / zcl 工程均适用);方式 B 紧贴 2.3 章节的代码位置,二选一即可。
步骤 4:编译下载与终端观察
- 三台设备分别编译对应角色固件并下载;
- 协调器连接 USB 转串口到 PC,打开串口助手(波特率与固件一致,默认 115200);
- 先给协调器上电 → 终端应打印
[NETWORK UP] PAN:0xXXXX CH:XX Addr:0x0000 Parent:0xFFFF; - 再依次给路由器、终端上电 → 终端应打印
[JOIN OK] PAN:0xXXXX ... Addr:0xXXXX Parent:0xXXXX; - 记录三台设备的打印结果。
步骤 5:验证与记录
- 对比三台设备打印的 PAN ID 是否一致(同一网络)、信道是否相同;
- 对比父节点地址:路由器直连协调器(Parent = 0x0000),终端挂在路由器下(Parent = 路由器短地址);
- 将打印内容截图,作为组网成功的"验收凭证"。
在线仿真环节:printf + Terminal I/O 查看辅助信息
在线仿真(连接仿真器、进入 C-SPY 调试会话)过程中,程序里的 printf 输出会实时显示在 IDE 界面的 Terminal I/O 窗口——无需外接串口线,是调试阶段查看辅助信息最直接的方式。
配置步骤(在线仿真)
- 接线:仿真器连接开发板与 PC(在线仿真必需);
- Project → Options → General Options → Library Configuration:Library 选择 Full(完整库,
printf才可用); - 点击 Debug(Ctrl+D) 进入在线仿真调试会话(C-SPY 连接仿真器);
- 菜单 View → Terminal I/O 打开 IDE 界面上的 Terminal I/O 窗口;
- 全速运行程序,
printf辅助信息实时显示在该窗口。
代码改造:用 printf 打印
把前面的串口打印函数改用 printf(输出到 Terminal I/O 窗口):
#include <stdio.h>
/* 用 printf 打印网络信息(输出到 IAR Terminal I/O 窗口) */
static void PrintNetworkInfoTF(uint8 *tag)
{
uint16 panId = _NIB.nwkPanId; // 网络号
uint8 channel = _NIB.nwkLogicalChannel; // 信道
uint16 addr = NLME_GetShortAddr(); // 本节点短地址
uint16 parent = NLME_GetCoordShortAddr(); // 父节点地址
printf("[%s] PAN:0x%04X CH:%d Addr:0x%04X Parent:0x%04X\r\n",
tag, panId, channel, addr, parent);
}入网成功处调用方式不变:
case ZDO_STATE_CHANGE:
if (devState == DEV_ZB_COORD)
PrintNetworkInfoTF("NETWORK UP");
else if (devState == DEV_ROUTER || devState == DEV_END_DEVICE)
PrintNetworkInfoTF("JOIN OK");
break;现象
进入调试后,Terminal I/O 窗口实时显示 [NETWORK UP] PAN:0xXXXX CH:X Addr:0x0000 / [JOIN OK] PAN:0xXXXX ...——这就是组网成功的"验收凭证"。
注意
- Library 必须为 Full,否则
printf不可用; - Terminal I/O 只在**在线仿真调试会话(Debug)**中显示,退出调试窗口内容清空;
- 若同时接串口,
HalUARTWrite与printf可并存,两边都能看。
实验现象与检查点
| 检查点 | 期望现象(串口终端) |
|---|---|
| 协调器上电 | [NETWORK UP] PAN:0xXXXX CH:X Addr:0x0000 |
| 路由器上电 | [JOIN OK] PAN:0xXXXX ... Parent:0x0000 |
| 终端上电 | [JOIN OK] PAN:0xXXXX ... Parent:0xXXXX(父节点=路由器) |
| 三台 PAN ID | 完全相同 |
| 入网失败重连 | (若实现)失败后 1s 自动重试,成功时打印 JOIN OK |
常见问题
- 终端无打印:确认串口已初始化(波特率匹配)、
HalUARTWrite调用无误;部分板型需将板载串口拨码开关拨到 USB 侧; - PAN ID 不一致:确认附近无其他协调器抢占,或固定
ZDAPP_CONFIG_PAN_ID; - 打印乱码:PC 串口助手的波特率、数据位(8N1)与固件一致;
- 看不到 JOIN OK:先给协调器上电建网,再给节点上电;必要时按协调器 Reset 键。
思考题
- 为什么
NETWORK UP的地址是0x0000、父节点是0xFFFF?协调器在 ZigBee 网络中扮演什么角色? - 终端与路由器的
Parent地址有何不同?这说明了什么网络拓扑关系? - 如果 10 台设备同时入网,如何用终端打印快速确认"全部入网成功且 PAN ID 一致"?(提示:日志留存、PAN ID 过滤)
- 与 2.3 章节的 LCD 屏幕显示相比,串口终端打印有哪些优势?
实验报告要求
- 说明本实验复用了 2.3 章节的哪些组网知识;
- 粘贴终端打印函数的代码及注释;
- 附三台设备的串口终端打印截图,标注 PAN ID / 信道 / 短地址 / 父节点;
- 填写网络参数记录表格并分析拓扑关系;
- 回答思考题;
- 写出遇到的问题及解决办法。
关联知识:2.3 ZigBee 3.0 组网实验、网络层、串口应用