Skip to content

实验二:Z-Stack 通信实验(传输学号) ​

一句话理解

本实验直接利用《3.4 ZigBee 3.0 通信实验》的工程与流程,把三种通信方式(点对点 / 广播 / 组播)在真实板子上跑起来,并把传输的数据改成你自己的学号——接收方屏幕上看到的是学号在"飞"。

前置知识 ​

本实验完全基于 3.4 ZigBee 3.0 通信实验 一节的知识,请先按该章节完成:

  1. 设备初始化(zclSampleSw_Init()):
    • 协调器:建网 + NLME_PermitJoiningRequest(255) + 启动广播/组播定时事件;
    • 路由器/终端:入网 + aps_AddGroup() 加入组 + 启动点对点定时事件;
  2. 事件定义(zcl_samplesw.h):SAMPLEAPP_P2P_EVT / SAMPLEAPP_BROADCAST_EVT / SAMPLEAPP_GROUPCAST_EVT;
  3. 事件处理(zclSampleSw_event_loop()):周期触发 zclSampleSw_AF_P2P() / zclSampleSw_AF_Broadcast() / zclSampleSw_AF_Groupcast() 发送;
  4. 接收处理(zclSampleSw_AF_RxProc()):按 clusterId 分类显示。

本实验的增量是:把发送的数据内容从 "P2P"/"Broadcast"/"Groupcast" 改为自己的学号,并在接收处理中显示/打印学号。

实验目的 ​

  1. 掌握 ZigBee 三种通信方式(点对点 / 广播 / 组播)的工程实现(复用 3.4 章节);
  2. 掌握修改传输数据内容的方法(把示例数据替换为自己的学号);
  3. 能够在接收方屏幕/串口看到自己学号的传输结果。

实验器材 ​

器材数量用途
GEC2530 开发板2 块1 协调器(Mini 板)+ 1 路由器/终端(标准板)
ZigBee 仿真器1 个烧录程序
USB 数据线2 根供电 + 串口
IAR EW for 80511 套编译工程
串口调试助手1 个查看接收到的学号

实验原理 ​

三种通信方式与学号数据流 ​

🔗
点对点 P2P
路由器/终端 → 协调器(0x0000)
定时发送【学号】
📡
📢
广播 Broadcast
协调器 → 全网
定时发送【学号】
📡
👥
组播 Groupcast
协调器 → 组21
定时发送【学号】
  • P2P 链路:终端把学号单播给协调器(目标地址 0x0000);
  • 广播链路:协调器把学号发给网络中所有节点;
  • 组播链路:协调器把学号只发给加入了组 21 的设备。

修改点就两处 ​

  1. 发送处:把 zclSampleSw_AF_P2P() / AF_Broadcast() / AF_Groupcast() 中作为数据传入的字符串,改成你的学号;
  2. 接收处:zclSampleSw_AF_RxProc() 中把接收到的学号显示在屏幕,并可用串口打印(呼应实验一的 Terminal 打印习惯)。

实验步骤 ​

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

  1. 打开 Z-Stack 3.0.1 的 SampleSwitch 工程;
  2. 按 3.4 章节完成初始化代码、事件定义、事件处理、接收处理;
  3. 先编译下载验证:协调器收到 "P2P"、标准板收到 "Broadcast"/"Groupcast",三种通信方式全部跑通。

步骤 2:定义自己的学号 ​

在应用层(zcl_samplesw.c 或 zcl_samplesw.h)定义学号数据:

c
// 学号(请换成你自己的学号!)
#define STUDENT_ID   "202311040123"
#define STUDENT_ID_LEN  (sizeof(STUDENT_ID))   // 含结尾 '\0',共 13 字节

步骤 3:发送处改为学号 ​

终端(或路由器)— 点对点发送学号给协调器:

c
// P2P Event
if ( events & SAMPLEAPP_P2P_EVT )
{
  zclSampleSw_AF_P2P(0x0000,               // 目标:协调器
                     CLUSTER_P2P,
                     STUDENT_ID_LEN,        // 数据长度(学号长度+1)
                     (uint8 *)STUDENT_ID);  // 数据内容:学号

  osal_start_timerEx(zclSampleSw_TaskID,
                     SAMPLEAPP_P2P_EVT,
                     SAMPLEAPP_P2P_PERIOD);

  return ( events ^ SAMPLEAPP_P2P_EVT );
}

协调器 — 广播/组播学号:

c
// Broadcast event
if ( events & SAMPLEAPP_BROADCAST_EVT )
{
  zclSampleSw_AF_Broadcast(CLUSTER_BROADCAST,
                           STUDENT_ID_LEN,
                           (uint8 *)STUDENT_ID);   // 广播学号

  osal_start_timerEx(zclSampleSw_TaskID,
                     SAMPLEAPP_BROADCAST_EVT,
                     SAMPLEAPP_BROADCAST_PERIOD);

  return ( events ^ SAMPLEAPP_BROADCAST_EVT );
}

// Groupcast event
if ( events & SAMPLEAPP_GROUPCAST_EVT )
{
  zclSampleSw_AF_Groupcast(GROUP_ID,
                           CLUSTER_GROUPCAST,
                           STUDENT_ID_LEN,
                           (uint8 *)STUDENT_ID);   // 组播学号

  osal_start_timerEx(zclSampleSw_TaskID,
                     SAMPLEAPP_GROUPCAST_EVT,
                     SAMPLEAPP_GROUPCAST_PERIOD);

  return ( events ^ SAMPLEAPP_GROUPCAST_EVT );
}

步骤 4:接收处显示 + 串口打印学号 ​

在 zclSampleSw_AF_RxProc() 中,把示例的显示逻辑改为显示学号,并加串口打印:

c
static void zclSampleSw_AF_RxProc(afIncomingMSGPacket_t *MSGpkt)
{
  static uint8 p2pCnt = 0;
  static uint8 bcCnt  = 0;
  static uint8 gcCnt  = 0;

  switch( MSGpkt->clusterId )
  {
    case CLUSTER_P2P:
      p2pCnt++;
      // 屏幕显示:收到的学号 + 计数
      HalLcdWriteString((char *)MSGpkt->cmd.Data, 3);
      HalLcdWriteStringValue("Cnt:", p2pCnt, 10, 4);
      // 串口打印学号到 PC 终端(可选)
      HalUARTWrite(0, MSGpkt->cmd.Data, MSGpkt->cmd.DataLength);
      break;

    case CLUSTER_BROADCAST:
      bcCnt++;
      HalLcdWriteString((char *)MSGpkt->cmd.Data, 3);
      HalLcdWriteStringValue("BC:", bcCnt, 10, 4);
      HalUARTWrite(0, MSGpkt->cmd.Data, MSGpkt->cmd.DataLength);
      break;

    case CLUSTER_GROUPCAST:
      gcCnt++;
      HalLcdWriteString((char *)MSGpkt->cmd.Data, 3);
      HalLcdWriteStringValue("GC:", gcCnt, 10, 4);
      HalUARTWrite(0, MSGpkt->cmd.Data, MSGpkt->cmd.DataLength);
      break;

    default:
      break;
  }
}

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

  1. 选择 RouterEB(或 EndDeviceEB) 编译下载到标准板;
  2. 选择 CoordinatorEB 编译下载到 Mini 板;
  3. 先给 Mini 板上电(建网),再给标准板上电(自动入网);
  4. 观察两块板的屏幕与串口:
板子角色期望现象
Mini 板协调器屏幕/串口显示你的学号(来自终端的 P2P 数据,每秒一次,计数递增)
标准板路由器/终端屏幕/串口显示你的学号(来自协调器的广播 + 组播数据)

在线仿真环节: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 p2pCnt = 0, bcCnt = 0, gcCnt = 0;

  switch( MSGpkt->clusterId )
  {
    case CLUSTER_P2P:
      p2pCnt++;
      // 输出到 Terminal I/O 窗口
      printf("[P2P] %s Cnt:%d\r\n", MSGpkt->cmd.Data, p2pCnt);
      break;

    case CLUSTER_BROADCAST:
      bcCnt++;
      printf("[BC] %s Cnt:%d\r\n", MSGpkt->cmd.Data, bcCnt);
      break;

    case CLUSTER_GROUPCAST:
      gcCnt++;
      printf("[GC] %s Cnt:%d\r\n", MSGpkt->cmd.Data, gcCnt);
      break;

    default:
      break;
  }
}

现象

进入调试后,Terminal I/O 窗口实时显示 [P2P] 202311040123 Cnt:1、[BC] 202311040123 Cnt:5……学号与计数一目了然,且不会被 LCD 截断。

注意

  • Library 必须为 Full,否则 printf 不可用;
  • Terminal I/O 只在**在线仿真调试会话(Debug)**中显示;
  • HalUARTWrite 串口打印与 printf 可并存。

实验现象与检查点 ​

检查点期望现象
协调器屏幕显示学号 + P2P 计数(每秒递增)
标准板屏幕显示学号 + 广播计数、组播计数
串口输出两块板串口均周期性打印学号
学号正确性显示内容与你的学号逐位一致
三种通信均通P2P、广播、组播计数都在增长

常见问题

  • 屏幕只显示 4 个字符:LCD 单行显示宽度有限,学号超过 4 位时可用 HalLcdWriteStringValue() 分段显示,或直接用串口打印完整学号;
  • 看不到 P2P 数据:确认终端发送目标地址为 0x0000(协调器),且簇 ID 两端一致;
  • 组播收不到:确认标准板已 aps_AddGroup() 加入组 21(GROUP_ID),且协调器组播地址用 afAddrGroup;
  • 乱码:串口波特率与固件一致(默认 115200)。

思考题 ​

  1. 为什么 LCD 显示学号会截断?串口打印相比屏幕显示有什么优势?
  2. 广播和组播都发给标准板,clusterId 为什么能区分两种数据?(提示:CLUSTER_BROADCAST / CLUSTER_GROUPCAST)
  3. 如果想把学号按"数字位"逐字节发送(如发送 12 个数字而不是字符串),应该怎么改长度与发送内容?
  4. 三种通信方式分别适合什么业务场景?结合 ZigBee 应用举例。

实验报告要求 ​

  1. 说明本实验复用了 3.4 章节的哪些知识;
  2. 粘贴修改后的核心代码(发送处 + 接收处)及注释;
  3. 附两块板的屏幕/串口截图,标注显示的学号与计数;
  4. 记录三种通信方式的传输现象;
  5. 回答思考题;
  6. 写出遇到的问题及解决办法。

关联知识:3.4 ZigBee 3.0 通信实验、AF 数据发送 API、实验一:简单组网

aioteer · 物联网专业课程群

💬AI 伴学配置