Skip to content

实验三:Z-Stack 广播、组播通信实验(多节点) ​

一句话理解

本实验延续《3.4 ZigBee 3.0 通信实验》的工程,把节点扩展到 3 个以上,重点验证两种通信模式的行为差异:广播 = "群发短信给所有人",组播 = "只拉一个群聊"。谁的屏幕上出现数据,一眼就能看出用的是哪种模式。

前置知识 ​

本实验基于 3.4 ZigBee 3.0 通信实验 的工程与代码,并建议先完成 实验二:通信实验(学号传输)。请先掌握:

  1. 设备初始化(zclSampleSw_Init()):协调器建网 + 定时事件,节点入网 + aps_AddGroup() 入组 + P2P 定时事件;
  2. 三种通信的发送封装:zclSampleSw_AF_P2P() / zclSampleSw_AF_Broadcast() / zclSampleSw_AF_Groupcast();
  3. 接收处理(zclSampleSw_AF_RxProc()):按 clusterId 分类显示;
  4. 3.4 章节中节点加入的组为 组 21(GROUP_ID)。

本实验的增量是:扩展到 3 个以上节点,让不同节点加入不同的组,从而在同一个网络中直观对比"广播谁都收得到、组播只有组员收得到"。

实验目的 ​

  1. 理解通讯模式:广播、组播(及单播)的行为差异与适用场景;
  2. 掌握相关网络参数配置:组 ID、端点、信道、PAN ID 对通信的影响;
  3. 修改 Z-Stack 协议栈程序,实现 3 个节点以上的广播通信。

实验器材 ​

器材数量用途
GEC2530 开发板3 块以上1 协调器 + 2 个以上路由器/终端
ZigBee 仿真器1 个烧录程序
USB 数据线若干供电 + 串口
IAR EW for 80511 套编译工程

实验原理 ​

三种通信模式对比 ​

📞
单播
点对点专线
目标:指定短地址
只有目标节点收到
📢
广播
大喇叭喊话
目标:0xFFFF 全网
网络内所有节点收到
👥
组播
群聊
目标:组 ID
只有加入该组的节点收到

多节点分组设计(本实验核心) ​

🏛️
协调器(发送方)
发 ①广播 ②组播到组21 ③组播到组22
(三个定时事件,每秒一次)
📡 广播 0xFFFF
🟢
节点 A(加入组 21)
收到:广播 ✅ 组播21 ✅ 组播22 ❌
📡 组播21
🔵
节点 B(加入组 22)
收到:广播 ✅ 组播21 ❌ 组播22 ✅
  • 广播(0xFFFF):A、B 都能收到 → 验证"全网可达";
  • 组播到组 21:只有 A 收到,B 收不到 → 验证"只有组员收到";
  • 组播到组 22:只有 B 收到,A 收不到 → 反向验证。

实验步骤 ​

步骤 1:按 3.4 章节搭好工程 ​

  1. 打开 Z-Stack 3.0.1 的 SampleSwitch 工程;
  2. 按 3.4 章节完成初始化、事件定义、事件处理、接收处理(含实验二的学号修改,可继续用学号作为传输数据)。

步骤 2:为不同节点配置不同的组 ​

3.4 章节中所有节点加入的都是组 21。本实验让节点 A 加入组 21、节点 B 加入组 22:

c
// 节点 A:加入组 21(保持 3.4 章节原样)
#define GROUP_ID  21

// 节点 B:改为加入组 22(编译节点 B 固件前修改)
#define GROUP_ID  22

初始化代码不变,仍然是:

c
// 节点 A / B 初始化中创建并加入自己的组
aps_Group_t group = {
  .ID = GROUP_ID,     // 21 或 22,取决于编译哪个固件
  .name = "",
};
aps_AddGroup(SAMPLESW_ENDPOINT, &group);

步骤 3:协调器增加"第二个组"的组播发送 ​

在 zclSampleSw_event_loop() 中,为组 22 增加一个组播定时事件(组 21 沿用 3.4 的 SAMPLEAPP_GROUPCAST_EVT):

c
// 头文件中新增:组 22 组播事件
#define SAMPLEAPP_GROUP22_EVT    0x0200
#define SAMPLEAPP_GROUP22_PERIOD 1000
#define GROUP22_ID               22

// 初始化中启动事件(协调器)
osal_start_timerEx(zclSampleSw_TaskID,
                   SAMPLEAPP_GROUP22_EVT,
                   SAMPLEAPP_GROUP22_PERIOD);

事件处理中发送到组 22:

c
// Group 22 event
if ( events & SAMPLEAPP_GROUP22_EVT )
{
  zclSampleSw_AF_Groupcast(GROUP22_ID,          // 目标组:22
                           CLUSTER_GROUP22,
                           STUDENT_ID_LEN,
                           (uint8 *)STUDENT_ID);   // 数据:学号

  osal_start_timerEx(zclSampleSw_TaskID,
                     SAMPLEAPP_GROUP22_EVT,
                     SAMPLEAPP_GROUP22_PERIOD);

  return ( events ^ SAMPLEAPP_GROUP22_EVT );
}

在 zcl_samplesw.c 中定义新的簇 ID:

c
#define CLUSTER_GROUP22  3    // 用于区分"发往组22"的数据

步骤 4:接收处分类显示 ​

在 zclSampleSw_AF_RxProc() 中增加 CLUSTER_GROUP22 分支,并保留原有分类:

c
case CLUSTER_GROUP22:
  gcCnt++;
  HalLcdWriteString((char *)MSGpkt->cmd.Data, 3);          // 显示学号
  HalLcdWriteStringValue("G22:", gcCnt, 10, 4);            // 显示组22计数
  HalUARTWrite(0, MSGpkt->cmd.Data, MSGpkt->cmd.DataLength);  // 串口打印
  break;

步骤 5:编译下载与验证 ​

  1. 编译 CoordinatorEB → 协调器(Mini 板);
  2. 编译 RouterEB(组21) → 节点 A(标准板);
  3. 编译 EndDeviceEB(组22) → 节点 B(另一块板);
  4. 上电顺序:协调器 → 节点 A → 节点 B(全部入网);
  5. 观察三块板屏幕/串口:
板子广播(0xFFFF)组播21组播22
协调器收不到收不到收不到
节点 A(组21)✅ 收到✅ 收到❌ 不收
节点 B(组22)✅ 收到❌ 不收✅ 收到

在线仿真环节:printf + Terminal I/O 查看辅助信息 ​

在线仿真(连接仿真器、进入 C-SPY 调试会话)过程中,程序里的 printf 输出会实时显示在 IDE 界面的 Terminal I/O 窗口——无需外接串口线,是调试阶段查看辅助信息最直接的方式。

配置步骤(在线仿真) ​

  1. 接线:仿真器连接开发板与 PC(在线仿真必需);
  2. Project → Options → General Options → Library Configuration:Library 选择 Full(完整库,printf 才可用);
  3. 点击 Debug(Ctrl+D) 进入在线仿真调试会话(C-SPY 连接仿真器);
  4. 菜单 View → Terminal I/O 打开 IDE 界面上的 Terminal I/O 窗口;
  5. 全速运行程序,printf 辅助信息实时显示在该窗口。

代码改造:接收处用 printf 分类打印 ​

在 zclSampleSw_AF_RxProc() 中补充(或改用)printf,让三类数据带标签输出:

c
#include <stdio.h>

static void zclSampleSw_AF_RxProc(afIncomingMSGPacket_t *MSGpkt)
{
  static uint8 bcCnt = 0, g21Cnt = 0, g22Cnt = 0;

  switch( MSGpkt->clusterId )
  {
    case CLUSTER_BROADCAST:       // 广播(全网)
      bcCnt++;
      printf("[BC] %s Cnt:%d\r\n", MSGpkt->cmd.Data, bcCnt);
      break;

    case CLUSTER_GROUPCAST:       // 组播到组 21
      g21Cnt++;
      printf("[G21] %s Cnt:%d\r\n", MSGpkt->cmd.Data, g21Cnt);
      break;

    case CLUSTER_GROUP22:         // 组播到组 22
      g22Cnt++;
      printf("[G22] %s Cnt:%d\r\n", MSGpkt->cmd.Data, g22Cnt);
      break;

    default:
      break;
  }
}

现象

  • 节点 A(组21)的 Terminal I/O:只有 [BC] 和 [G21] 在增长,看不到 [G22];
  • 节点 B(组22)的 Terminal I/O:只有 [BC] 和 [G22] 在增长,看不到 [G21]。

三块板各开一个调试会话,谁收到什么一目了然。

注意

  • Library 必须为 Full,否则 printf 不可用;
  • Terminal I/O 只在**在线仿真调试会话(Debug)**中显示;
  • 多板同时调试时,每个调试会话对应各自的 Terminal I/O 窗口。

实验现象与检查点 ​

检查点期望现象
广播后节点 A、B 都显示学号 + 广播计数增长
组播到组 21只有节点 A 显示(G21 计数增长)
组播到组 22只有节点 B 显示(G22 计数增长)
三台设备 PAN ID完全一致(同一网络,呼应实验一)
节点 A / B信道一致,均正常入网

常见问题

  • 节点 B 收不到组播22:确认节点 B 编译时 GROUP_ID 已改为 22,且协调器组播目标为 GROUP22_ID;
  • 广播谁都没收到:检查协调器是否 NLME_PermitJoiningRequest(255) 且节点已入网;广播地址为 0xFFFF 时休眠终端收不到,可用 0xFFFD(发给所有非休眠设备)代替;
  • 计数混在一起:A 收到广播和组播21 时屏幕行会互相覆盖,建议用串口打印区分(在打印中标注 BC/G21/G22);
  • PAN ID 不一致:附近有其他协调器时固定 ZDAPP_CONFIG_PAN_ID。

思考题 ​

  1. 广播、组播、单播分别适合什么场景?为什么 ZigBee 中广播地址 0xFFFF 不发给休眠终端?
  2. 如果节点 B 同时加入组 21 和组 22(aps_AddGroup 调用两次),它能收到哪些数据?
  3. 一个节点最多能加入多少个组?组的 endpoint 字段有什么作用?
  4. 结合实验一:组播能否替代广播实现"只让指定区域节点收到数据"?网络参数(PAN ID/信道)在其中起什么作用?

实验报告要求 ​

  1. 说明本实验基于 3.4 章节的哪些代码,新增了什么;
  2. 粘贴分组配置、组22 事件、接收处理的代码及注释;
  3. 附三块板的屏幕/串口截图,用表格记录"广播/组播21/组播22"的接收情况;
  4. 记录三台设备的网络参数(PAN ID、信道)并分析;
  5. 回答思考题;
  6. 写出遇到的问题及解决办法。

关联知识:3.4 ZigBee 3.0 通信实验、实验二:通信实验(学号传输)、实验一:简单组网

aioteer · 物联网专业课程群

💬AI 伴学配置