3. ZigBee 设备类型与角色:协调器、路由器、终端设备

这一章咱们聊聊 ZigBee 网络里的三种设备角色。说白了,一个 ZigBee 网络就像一个小型团队,有人当组长,有人当传话筒,还有人当省电的普通成员。这三种角色分工明确,缺一不可。

我在做项目时经常遇到有人问:「为什么我的终端设备连不上网?」「为什么路由器加进去后网络就乱了?」——这些问题,多半是对设备角色理解不够深。咱们今天就把这三个角色彻底讲透。

3.1 协调器(Coordinator)——网络的发起者

协调器是每个 ZigBee 网络的第一个节点。它负责建立网络、分配地址、管理入网。一个网络只能有一个协调器,而且它一旦启动,就不能再改变角色。

3.1.1 协调器的核心功能

  • 网络建立:扫描信道,选择一个干扰最小的信道,启动网络
  • 地址分配:为加入的路由器和终端设备分配 16 位短地址
  • 入网管理:允许或拒绝设备加入网络
  • 信标发送:在信标使能模式下定期发送信标帧

关键点:协调器本质上也是一个全功能设备(FFD),它拥有完整的协议栈功能。但它不是路由器,不能转发数据包——这一点很多人搞混。

3.1.2 协调器的初始化流程

我习惯把协调器的启动过程分成三步。嗯,每一步都有坑,咱们一个一个说。

  1. 硬件初始化:MCU 时钟、GPIO、SPI/UART 外设、中断系统
  2. 协议栈初始化:调用 ZigBeeInit(),加载 NV 参数,初始化 MAC 层
  3. 网络启动:调用 ZDO_StartDevice(),选择信道,建立网络
// 协调器初始化代码示例(基于 Z-Stack)
void zbStartRequest( void )
{
    // 1. 初始化硬件
    HalDriverInit();
    
    // 2. 初始化协议栈
    ZMacInit();
    nvInit();
    
    // 3. 启动设备为协调器
    ZDOInitDevice( 0 );  // 0 表示协调器
    
    // 4. 等待网络建立完成
    // 回调函数 zbStartConfirm() 会通知结果
}

void zbStartConfirm( uint8 status )
{
    if( status == ZB_SUCCESS )
    {
        // 网络建立成功
        // 此时可以获取网络短地址 0x0000
        // 协调器的短地址固定为 0x0000
    }
    else
    {
        // 网络建立失败,检查信道干扰
    }
}

我曾经踩过的坑:有一次协调器启动后,终端设备死活加不进来。查了半天,发现是 NV 参数里残留了上次测试的网络信息。解决办法很简单——每次量产前做一次 NV 擦除。记住:协调器的 NV 必须干净。

3.2 路由器(Router)——网络的中继者

路由器的作用说白了就是「传话」。它接收数据包,然后转发给下一个节点。没有路由器,ZigBee 网络就只能覆盖几十米范围。

3.2.1 路由器的功能

  • 数据中继:接收并转发数据包,扩展网络覆盖范围
  • 路由发现:通过 AODV 算法寻找最优路径
  • 子节点管理:允许终端设备通过它加入网络
  • 路由表维护:动态更新路由表,处理链路失效

个人经验:我建议在部署路由器时,尽量让它们形成「网状」结构,而不是「链状」。链状结构一旦中间一个路由器掉电,后面的节点全断。网状结构有冗余路径,可靠性高得多。

3.2.2 路由发现过程

你想想看,当一个终端设备要发数据给另一个设备,路由器怎么知道往哪走?它靠的是路由发现。

  1. 源节点广播路由请求(RREQ)
  2. 中间路由器收到 RREQ,记录上一跳地址,继续广播
  3. 目标节点收到 RREQ,回复路由应答(RREP)
  4. RREP 沿原路径返回,沿途路由器更新路由表

这个过程我见过很多次。有一次在工厂里,设备之间距离太远,路由发现总是超时。后来加了两个路由器做中继,问题就解决了。

3.3 终端设备(End Device)——网络的省电者

终端设备是 ZigBee 网络里最「懒」的角色。它不转发数据,大部分时间都在睡觉。这正是它的价值所在——低功耗。

3.3.1 终端设备的低功耗特性

特性 说明 典型值
休眠模式 设备大部分时间处于睡眠状态 休眠电流 < 1 μA
轮询机制 定期醒来向父节点查询是否有数据 轮询间隔 100ms ~ 10s
数据发送 发送完数据立即进入休眠 发送电流 ~ 30 mA
父节点缓存 数据由父节点暂存,等待终端设备轮询 缓存超时 7.68s

关键点:终端设备必须关联一个父节点(协调器或路由器)。父节点负责缓存发给它的数据。如果终端设备休眠时间太长,父节点会丢弃缓存数据。

3.3.2 终端设备的轮询机制

终端设备怎么知道有数据要收?它不会一直监听,那样太费电。它用轮询——定期醒来问父节点:「有我的数据吗?」

// 终端设备轮询示例
void pollForData( void )
{
    // 设置轮询间隔为 1 秒
    uint16 pollInterval = 1000;  // 单位:毫秒
    
    while(1)
    {
        // 进入休眠
        halSleep( pollInterval );
        
        // 醒来,发送数据请求
        zbSendDataRequest( parentAddr, NULL, 0, 0, AF_ACK_REQUEST );
        
        // 如果有数据,回调函数会处理
        // 处理完继续休眠
    }
}

// 数据接收回调
void zbReceiveDataIndication( uint16 source, uint16 command, 
                              uint16 len, uint8 *pData )
{
    // 处理接收到的数据
    // 处理完后自动进入下一轮休眠
}

注意:轮询间隔不能太长。我曾经有个项目,终端设备设了 10 秒轮询一次,结果父节点缓存超时只有 7.68 秒,数据全丢了。后来改成 3 秒轮询,问题解决。记住:轮询间隔必须小于父节点缓存超时时间。

3.4 三种角色的分工对比

咱们用一张表把三种角色放在一起对比,一目了然。

特性 协调器 路由器 终端设备
设备类型 FFD FFD RFD
网络数量 1 个 多个 多个
数据转发 否 是 否
低功耗 否 否 是
子节点管理 是 是 否
典型应用 网关、集中器 中继器、智能插座 传感器、遥控器

3.5 设备角色在组网中的分工

一个典型的 ZigBee 网络是这样工作的:

  • 协调器:启动网络,分配地址,管理入网
  • 路由器:扩展覆盖范围,转发数据,提供冗余路径
  • 终端设备:采集数据,发送给父节点,大部分时间休眠

说白了,协调器是「大脑」,路由器是「神经」,终端设备是「感官」。三者配合,才能形成一个稳定、可靠、低功耗的无线网络。

我的建议:在设计网络拓扑时,尽量让终端设备直接连接路由器,而不是协调器。协调器要处理网络管理任务,负载已经很重了。把终端设备分散到各个路由器上,网络会更稳定。

ZigBee 设备角色与组网拓扑 协调器 短地址:0x0000 路由器 A 中继 + 子节点管理 路由器 B 中继 + 子节点管理 终端设备 1 休眠轮询 终端设备 2 休眠轮询 终端设备 3 休眠轮询 终端设备 4 休眠轮询 图例: 协调器 路由器 终端设备 数据链路 网状连接(可选)

这张图展示了一个典型的 ZigBee 星型+网状混合拓扑。协调器在中心,两个路由器扩展覆盖范围,四个终端设备分别挂在不同路由器下。路由器之间还有网状连接,提供冗余路径。