Zigbee协议栈————广播组网

article/2025/10/22 3:33:04

目录

1.基础概念

2.Zigbee协议栈工作流程

3。代码讲解


1.基础概念

在Zigbee网络中存在3中逻辑设备:协调器、路由器、终端。

(这个实验当中我们只用到协调器以及终端)。

协调器:协调器负责启动网络,当启动和配置好网络后,协调器就会像一个路由器一样或者就消失了。

终端:网络中的一个设备,一个节点。

 广播:当应用程序需要将数据包发送给网络的每一个设备时,使用这种模式。地址模式设置为
AddrBroadcast。目标地址可以设置为下面广播地址的一种:
NWK BROADCAST SHORTADDR DEVALL(0xFFFF)--数据包将被传送到网络上的所有设备,包括睡眠中的设备。
NWK BROADCAST SHORTADDR DEVRXON(0xFFFD)-数据包将被传送到网络上除了睡眠中的所有设备。
NWK BROADCAST SHORTADDR DEVZCZR(0xFFFC)--数据包发送给所有的路由器,包括协调器。

2.Zigbee协议栈工作流程

main()函数中初始化操作系统osal_init_system(),初始化一些外设(协议栈已经将这些外设封装好了,可以像32一样调用函数使用。),最后进入osal_start_system()中执行操作系统,并且程序会一直处于这个函数当中,不会返回(函数中有死循环),在这个函数当中判断是否有事件发生,然后会根据优先级来处理这些事件(任务)。我们以后主要需要修改在SampleApp_Init()当中.

 3.代码讲解

协议栈中很多东西已经帮我们写好,我们以后使用仅仅需要修改增加一些内容。因此代码不需要全部都懂。(初学者不要尝试将所有的代码都看懂,循序渐进。)

在目录中找到SampleApp.c,打开它,并在该C文件的顶部包含#include"MT_UART.h"
#include "MT_APP.h"
#include "MT.h"
#include "string.h"

这四个头文件。接下来找到void SampleApp_Init( uint8 task_id )这个函数

void SampleApp_Init( uint8 task_id )
{ SampleApp_TaskID = task_id;SampleApp_NwkState = DEV_INIT;SampleApp_TransID = 0;//这一部分为新加进来的代码//------------------------配置串口---------------------------------MT_UartInit();                    //串口初始化MT_UartRegisterTaskID(task_id);   //注册串口任务HalUARTWrite(0,"UartInit OK\n", sizeof("UartInit OK\n"));//-----------------------------------------------------------------#if defined ( BUILD_ALL_DEVICES )if ( readCoordinatorJumper() )zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR;elsezgDeviceLogicalType = ZG_DEVICETYPE_ROUTER;
#endif // BUILD_ALL_DEVICES#if defined ( HOLD_AUTO_START )ZDOInitDevice(0);
#endifSampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;//广播模式SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;//广播地址
/*//组播的代码// Setup for the flash command's destination address - Group 1SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;*/SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;SampleApp_epDesc.task_id = &SampleApp_TaskID;SampleApp_epDesc.simpleDesc= (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;SampleApp_epDesc.latencyReq = noLatencyReqs;afRegister( &SampleApp_epDesc );RegisterForKeys( SampleApp_TaskID );
/*//组播的代码// By default, all devices start out in Group 1SampleApp_Group.ID = 0x0001;osal_memcpy( SampleApp_Group.name, "Group 1", 7  );aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );
*/#if defined ( LCD_SUPPORTED )HalLcdWriteString( "SampleApp", HAL_LCD_LINE_1 );
#endif
}

 其中 MT_UartInit()在目录中MT文件中的MT_UART.c的文件当中,为串口的初始化。



 

 这个初始化的函数当中,我们需要将波特率设置好,流控制关闭,其他的可以不用管。

        然后我们就可以调用HalUARTWrite(0,"UartInit OK\n", sizeof("UartInit OK\n"))来发送初始化完成的提示。然后,如上面的代码块一样,将组播的代码注释掉。

        接下来,我们进入到uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )当中。

//在这个函数当中完成对事件的处理
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{afIncomingMSGPacket_t *MSGpkt;(void)task_id;  if ( events & SYS_EVENT_MSG ){MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );while ( MSGpkt ){switch ( MSGpkt->hdr.event ){case KEY_CHANGE:SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );break;case AF_INCOMING_MSG_CMD://接收到数据包就进行处理SampleApp_MessageMSGCB( MSGpkt );break;case ZDO_STATE_CHANGE://协调器状态改变就进入下面的函数,协调器刚建立网络就会进去SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);if ( (SampleApp_NwkState == DEV_ZB_COORD)|| (SampleApp_NwkState == DEV_ROUTER)|| (SampleApp_NwkState == DEV_END_DEVICE) ){osal_start_timerEx( SampleApp_TaskID,SAMPLEAPP_SEND_PERIODIC_MSG_EVT,SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );}else{}break;default:break;}osal_msg_deallocate( (uint8 *)MSGpkt );MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );}return (events ^ SYS_EVENT_MSG);}if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )//上面有出现哦,协调器状态改变{SampleApp_SendPeriodicMessage();//协调器发送数据 osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);}return 0;
}

接下来进入SampleApp_SendPeriodicMessage()函数当中。

void SampleApp_SendPeriodicMessage( void )
{//联网后进入这个函数uint8 *buff=NULL;if(zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR)//判断Zigbee的逻辑类型,如果是协调器{buff="I am coordinator device\r\n";}else if(zgDeviceLogicalType == ZG_DEVICETYPE_ENDDEVICE)//如果是终端{buff="I am endpoint device\r\n";}// AF_DataRequest()这个函数是真正发送数据的函数,我们需要将第三第四个参数该为数组的大小,以及数组的内容,然后就可以发送了。if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,SAMPLEAPP_PERIODIC_CLUSTERID,strlen(buff),//传输数据的字节大小buff,//传输数据&SampleApp_TransID,AF_DISCV_ROUTE,AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ){}else{}
}

 数据发送完了,当接受到数据包后,MSGpkt->hdr.event=AF_INCOMING_MSG_CMD,接下来,我们就要进入SampleApp_MessageMSGCB( MSGpkt )当中。

void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )//无线数据包接收到之后
{uint16 flashTime;switch ( pkt->clusterId ){case SAMPLEAPP_PERIODIC_CLUSTERID://接收到该命令后执行的代码HalUARTWrite(0,(pkt->cmd).Data,(pkt->cmd).DataLength);//将接受到的数据打印到串口中break;case SAMPLEAPP_FLASH_CLUSTERID:flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] );HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) );break;}
}

至此,代码就完成了。接下来就可以烧录,看现象了。

4.可能遇到的问题

 1.注意协调器与终端的烧录,需要分开烧录。可由上图所示更改。

2.以下问题为版本不兼容

以及一堆 Undefined external "?V1" referred in AF类似的,都是由于版本不兼容的原因。解决方法:

 

 将16改为8

  ZStack-CC2530-2.5.1a\Projects\zstack\ZMain\TI2530DB下的chipcon_cstartup.s51文件中删除END,并添加以下代码:

;----------------------------------------------------------------;
; Virtual registers						 ;
; =================						 ;
; Below is some segment needed for the IAR ICC C/EC++ compiler   ;
;								 ;
; BREG  : A segment for 8 bit registers for use by the compiler. ;
;         ?B0 is the first register.                             ;
; VREG  : Segment that holds up to 32 virtual registers for      ;
;         use by the compiler. ?V0 is the first register.        ;
; PSP   : Segment containing the PDATA stack pointer (?PSP)      ;
; XSP   : Segment containing the XDATA stack pointer (?XSP)      ;
; 								 ;
;----------------------------------------------------------------;
;----------------------------------------------------------------;PROGRAM VIRTUAL_REGISTERSPUBLIC  ?B0PUBLIC  ?V0PUBLIC  ?V1PUBLIC  ?V2PUBLIC  ?V3PUBLIC  ?V4PUBLIC  ?V5PUBLIC  ?V6PUBLIC  ?V7PUBLIC  ?V8PUBLIC  ?V9PUBLIC  ?V10PUBLIC  ?V11PUBLIC  ?V12PUBLIC  ?V13PUBLIC  ?V14PUBLIC  ?V15PUBLIC  ?V16PUBLIC  ?V17PUBLIC  ?V18PUBLIC  ?V19PUBLIC  ?V20PUBLIC  ?V21PUBLIC  ?V22PUBLIC  ?V23PUBLIC  ?V24PUBLIC  ?V25PUBLIC  ?V26PUBLIC  ?V27PUBLIC  ?V28PUBLIC  ?V29PUBLIC  ?V30PUBLIC  ?V31PUBLIC  ?PSPPUBLIC  ?XSPRSEG    BREG:BIT:NOROOT
?B0:DS      8RSEG    VREG:DATA:NOROOT
?V0:DS      1
?V1:DS      1
?V2:DS      1
?V3:DS      1
?V4:DS      1
?V5:DS      1
?V6:DS      1
?V7:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V7
?V8:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V8
?V9:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V9
?V10:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V10
?V11:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V11
?V12:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V12
?V13:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V13
?V14:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V14
?V15:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V15
?V16:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V16
?V17:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V17
?V18:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V18
?V19:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V19
?V20:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V20
?V21:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V21
?V22:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V22
?V23:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V23
?V24:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V24
?V25:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V25
?V26:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V26
?V27:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V27
?V28:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V28
?V29:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V29
?V30:DS      1RSEG    VREG:DATA:NOROOTREQUIRE ?V30
?V31:DS      1RSEG    PSP:DATA:NOROOTEXTERN  ?RESET_PSPREQUIRE	?RESET_PSP
?PSP:DS      1RSEG    XSP:DATA:NOROOTEXTERN  ?RESET_XSPREQUIRE	?RESET_XSP
?XSP:DS      2ENDMOD ; VIRTUAL_REGISTERSEND

3.注意在烧录前需要预编译

 

只有ZTOOL_P1前没有x,其它的都需要在前面加一个x。

4.注意协议栈里的串口0,使用的是P0_2(RX),P0_3(TX)。


http://chatgpt.dhexx.cn/article/XxLnansX.shtml

相关文章

zibgee协议

1.概述 1.1解析ZigBee堆栈架构 ZigBee堆栈是在IEEE 802.15.4标准基础上建立的,定义了协议的MAC和PHY层。ZigBee设备应该包括IEEE802.15.4(该标准定义了RF射频以及与相邻设备之间的通信)的PHY和MAC层,以及ZigBee堆栈层:网络层(NWK)、应用层和安…

[ZigBee] 15、Zigbee协议栈应用(一)——Zigbee协议栈介绍及简单例子(长文,OSAL及Zigbee入门知识)...

1、Zigbee协议栈简介 协议是一系列的通信标准,通信双方需要按照这一标准进行正常的数据发射和接收。协议栈是协议的具体实现形式,通俗讲协议栈就是协议和用户之间的一个接口,开发人员通过使用协议栈来使用这个协议,进而实现无线数据收发。 如图1所示:Zigbee协议分为两部分…

ZigBee协议栈简介

文章目录 Zigbee协议栈简介如何理解Zigbee协议栈如何使用Zigbee协议栈 Zigbee协议栈简介 Zigbee协议分为2部分: IEEE 802.15.4定义了PHY(物理层)和MAC(介质访问层)技术规范。Zigbee联盟定义了NWK(网络层)、APS(应用程序支持层)、APL(应用层)技术规范。 Zigbee协议栈…

[zigbee][z-Stack]协议栈简介及工作流程

文章目录 什么是zigbee协议栈?如何使用zigbee协议栈?z-Stack工作流程 什么是zigbee协议栈? 协议栈是协议的具体实现形式,通俗点来理解就是协议栈是协议和用户之间的一个缺口,开发人员通过使用协议栈来使用这个协议的&…

相机标定和双目相机标定标定原理推导及效果展示

文章目录 前言一、相机标定1.相机的四个坐标系2.相机的畸变 二、张正友标定法1.求解内参矩阵与外参矩阵的积2.求解内参矩阵3.求解外参矩阵4.标定相机的畸变参数5.双目标定6.极线矫正(立体校正) 三、视差图与深度图 前言 参考了一些大佬的文章&#xff0c…

视觉基础之相机标定

点击上方“小白学视觉”,选择加"星标"或“置顶” 重磅干货,第一时间送达 基于视觉的图像处理,通常要在实验前进行相机的标定,以获取相应的参数。为方便查阅,遂将常用到的三种相机标定总结如下。 相机内参标定…

照相机标定

一.相机标定的原理 1.1 相机如何成像: 相机成像系统中,共包含四个坐标系:世界坐标系、相机坐标系、图像坐标系、像素坐标系。 1.1.1 世界坐标系: 世界坐标系(world coordinate),也称为测量坐…

Opencv——相机标定

相机标定的目的:获取摄像机的内参和外参矩阵(同时也会得到每一幅标定图像的选择和平移矩阵),内参和外参系数可以对之后相机拍摄的图像就进行矫正,得到畸变相对很小的图像。 相机标定的输入:标定图像上所有…

为什么需要对相机标定?

以下内容来自系统教程如何搞定单目/鱼眼/双目/阵列 相机标定? 点击领取相机标定资料和代码 为什么需要对相机标定? 我们所处的世界是三维的,而相机拍摄的照片却是二维的,丢失了其中距离/深度的信息。从数学上可以简单理解为&…

1. 相机标定原理(学习笔记)

相机标定(Camera Calibration)-学习笔记 文章目录 相机标定(Camera Calibration)-学习笔记一、简介二、原理1. 坐标系 *coordinates*2. 相机参数 *camera matrix*2.1 外参数矩阵2.2 内参数矩阵2.3 畸变矩阵2.3.1 径向畸变2.3.2 切向畸变 2.4 小结 三、相机标定方法1. 张正友相机…

相机标定目的及原理

相机标定的目的: 相机标定的目的有两个,一个就是矫正由于镜头畸变造成的图片的变形,例如,现实中的直线,拍摄成图像后会外凸或内凹,进行相机标定后可以对这种情况进行校正;另一个是根据获得得图像…

Python之OpenCV相机标定方法

本文结合OpenCV官方样例,对官方样例中的代码进行修改,使其能够正常运行,并对自己采集的数据进行实验和讲解。 一、准备 OpenCV使用棋盘格板进行标定,如下图所示。为了标定相机,我们需要输入一系列三维点和它们对应的…

相机标定,内参数与外参数

相机标定 简介 所谓的相机标定就是将外界世界的坐标信息转化为计算机(自带相机/摄像头)可以理解的“距离”,将世界坐标系转换到相机坐标系。我们可以理解为从一个坐标系转换到另一个坐标系所需要的转换关系就是相机标定。 简单滴说&#x…

相机标定——张氏标定法

目录 前言动机为什么要进行相机标定什么是张氏标定法 张氏标定法的原理透镜成像原理世界坐标系到相机坐标系的转换相机坐标系到图像坐标系的转换图像坐标系到像素坐标系单应性矩阵内参求解外参求解Matlab实操 前言 动机 前段时间在整机械臂的手眼标定,也就是标定3D…

相机标定系列(三)利用matlab进行相机标定

相机标定系列(三)利用matlab进行相机标定 文章目录 相机标定系列(三)利用matlab进行相机标定前言一、棋盘格图像的采集二、单目相机标定三、双目相机标定 前言 matlab的应用程序中含有对双目相机和单目相机的标定工具箱&#xff…

机器视觉——相机标定

1 机器视觉为什么要做相机标定 机器视觉是采用相机成像来实现对三维场景的测量、定位、重建等过程。是一个利用二维图像进行三维反推的过程,我们所处的世界是三维的,而图像或者照片是二维的,可以把相机认为是一个函数,输入量是一…

相机标定篇——相机标定

认为相机标定是三维重建的核心,研究生期间主要方向为结构光三维重建 必要的数学知识 线性方程求解 Gauss消元法;LU分解;Cholesky分解 最小二乘问题-线性方法 特征值分解;奇异值分解;超定线性方程;最小二乘…

【相机标定】相机内参

相机标定 相机在计算机视觉方面的一些应用一般需要相机标定。我们总是听到标定这个词,那么具体标定的是什么呢?相机的拍摄是一个三维到二维(透视投影)的过程,这个过程可以用数学模型去表述,标定便是计算这…

什么是相机标定

1. 相机标定的定义及作用 相机标定是指借助标定板来计算单个或多个相机的内参、外参和镜头畸变参数。 作用: 将畸变的图像恢复为正常的图像,为后续进行拼接、SLAM等奠定基础。 多相机标定可以将所有相机输出变换到同一个坐标系。 相机标定是三维视觉…

相机标定究竟在标定什么?

点击上方“小白学视觉”,选择加"星标"或“置顶” 重磅干货,第一时间送达 相机标定可以说是计算机视觉/机器视觉的基础,但是初学者不易上手,本文将给读者整理一遍相机标定的逻辑,并在文末回答评论区提出的问题…