实现内容,终端发消息给协调器,协调器发消息给全部终端
串口透传,终端设备串口进来的数据,第一字节设备编号,0为协调器,1为终端1,(广播),第二字节命令编号,如果1,发送位置信息,如果是2,发送温湿度,先实现透传,2k链接之后需要和不同终端通信,发送不同编号
1.串口初始化
2.MT_UartProcessZToolData函数解释
MT_UartProcessZToolData
串口发来的数据包进行打包,校验,生成一个消息,发给处理数据包的任务。
用 ZTOOL 通过串口来沟通协议栈,那么发过来的串口数据具有以下格式:
0xFE, DataLength, CM0, CM1, Data payload, FCS
翻译:
0xFE:数据帧头
DataLength: Datapayload 的数据长度,以字节计,低字节在前;205
CM0:命令低字节;
CM1:命令高字节; (ZTOOL 软件就是通过发送一系列命令给 MT 实现和协议栈交互)
Data payload:数据帧具体的数据,这个长度是可变的,但是要和DataLength 一致;
FCS :校验和,从 DataLength 字节开始到 Data payload 最后一个字节所有字节的异或按字节操作;
3. 消除流控制
#define MT_UART_DEFAULT_OVERFLOW FALSE
4.关于两个串口
CC2530芯片的所有片上外设中,总共有2个串口,分别称为串口0和串口1。在实际项目开发当中,一般我们会将串口0用作“调试串口”,用于打印一些提示信息;而将串口1用于与外围硬件设备对接,实现实际的项目需求。本节中我们将通过串口0实现字符串打印功能。
5.自己创建projectapp调用zstack文章
6.按道理说这样就可以组网,用不同的工作空间下载程序就可以组网了
但是是因为不同工作空间其中配置不同吗,内部设置了节点地址?切换工作空间就把地址配置好了?
7.实现串口发送的文章
ZigBee组网-基于协议栈的UART实验(实现收发)(保姆级)
`HalUARTWrite`函数是模块通过串口(UART)发送数据的。回调是实现将串口收到的数据发送回给发送方上位机。是串口收到的,我通过串口助手用串口发消息给模块,模块串口收到后显示出来,但是没有发出去,要实现AF收到数据(射频),通过串口传出来
竹子的
我只写到了发送,没完全理解其中调度
8.协议栈中文说明
不知道有没有说空座空间配置区分节点的说明
9.协议栈工作主要流程,含有每个函数是啥
zigbee协议栈工作流程 From zigbee菜鸟笔记(十 一)
这个人也写得挺好的,他也写了一些实验步骤
10.Zigbee协议栈网络管理
点播给协调器自己的编号
点播给协调器自己的编号
收到信息,如果是1,协调器串口输出信息包中的地址还有打印一些字
这里面有说分工作区下载还有涉及短地址,还是不清楚如何区分节点类型,可能手册里有?
11.这个博主写的很详细可以照着他的来做实验,讲的比较清楚
叫甜小圈,和10是一个人,博客的,很厉害,还有透传
12.买的模块配置视频
13.Zigbee协议栈的使用
有关于节点判断的部分,这是按键控制之类的,辅助理解协议栈的工作
lesson7-2 Zigbee协议栈的使用-----竹烟淮雨他最开始的组网
13.这人的串口透传写的很简单
ZigBee组网学习笔记(六)--串口透传—— 吃果冻不吐果冻皮——他是竹淮烟雨的参考
13.如何检验组网是否成功
14.关于初始化,网络状态的定义
做的10的实验,在此之前做了6,7的实验
这是10中博主的函数,有关节点;
这个`typedef enum`定义了一个名为`devStates_t`的枚举类型,用于描述设备在网络中的不同状态。下面是每个状态的解释:
1. `DEV_HOLD`:设备已初始化,但不会自动启动。
2. `DEV_INIT`:设备已初始化,但尚未连接到任何网络。
3. `DEV_NWK_DISC`:设备正在发现要加入的个人区域网络(PANs)。
4. `DEV_NWK_JOINING`:设备正在尝试加入一个PAN。
5. `DEV_NWK_REJOIN`:仅对终端设备,设备正在尝试重新加入一个PAN。
6. `DEV_END_DEVICE_UNAUTH`:设备已加入,但尚未被信任中心认证。
7. `DEV_END_DEVICE`:设备经过认证后作为终端设备启动。
8. `DEV_ROUTER`:设备已加入,经过认证,并作为路由器运行。
9. `DEV_COORD_STARTING`:设备正在启动作为Zigbee协调器。
10. `DEV_ZB_COORD`:设备已启动作为Zigbee协调器。
11. `DEV_NWK_ORPHAN`:设备失去了对其父设备的信息,即设备成了孤儿。
这个枚举类型可以用于跟踪设备在网络中的生命周期和状态变化,从而在代码中根据设备的状态采取适当的行动。
这段代码定义了一个名为 `afIncomingMSGPacket_t` 的结构体,用于存储Zigbee网络中接收到的消息的相关信息。这个结构体包含以下字段:
1. `osal_event_hdr_t hdr`:这是OSAL消息头,包含了关于消息的基本信息,如消息类型和优先级。
2. `uint16 groupId`:消息所属的组ID,如果未设置,则为0。
3. `uint16 clusterId`:消息所属的簇(Cluster)ID,用于识别消息的具体功能或服务。
4. `afAddrType_t srcAddr`:源地址,如果是`STUBAPS_INTER_PAN_EP`,则表示这是一条跨PAN(Personal Area Network)的消息。
5. `uint16 macDestAddr`:MAC层头部的短地址目的地。
6. `uint8 endPoint`:目的地端点号。
7. `uint8 wasBroadcast`:一个布尔值,表示网络目的地是否是广播地址。
8. `uint8 LinkQuality`:接收到的数据帧的链路质量。
9. `uint8 correlation`:接收到的数据帧的原始相关性值。
10. `int8 rssi`:接收到的射频功率,单位为dBm。
11. `uint8 SecurityUse`:已弃用的安全使用标志。
12. `uint32 timestamp`:从MAC层接收的时间戳。
13. `uint8 nwkSeqNum`:网络头中的帧序列号。
14. `afMSGCommandFormat_t cmd`:应用数据部分,包含了消息的实际内容。
这个结构体用于封装从Zigbee网络接收的所有必要信息,方便进一步的处理和解析。
`#define SAMPLEAPP_MAX_CLUSTERS 2` 是一个宏定义,用于设置在`SampleApp`中最多支持的集群(Cluster)数量。在Zigbee或其他类似网络协议中,集群是设备上定义功能或服务的逻辑单元。每个设备可以支持多个集群,每个集群都有一个唯一的ID。
在这个定义中,`SampleApp` 被限制最多只能处理或模拟两个集群。这可能是为了优化资源使用,简化代码,或者是因为应用的设计仅需要与两个特定的集群交互。实际应用中,这个数值可以根据需要调整,以适应更多的集群功能。如果`SampleApp`需要与超过两个的集群进行通信,就需要增大这个宏的值。
该函数功能是读取本设备信息并发送出去
#define SAMPLEAPP_POINT_TO_POINT_CLUSTERID 3` 是一个预处理器宏定义,用于在`SampleApp`中指定一个特定的点对点(Point-to-Point)集群ID。在Zigbee或其他类似网络中,集群ID用于标识设备上的特定功能或服务。
在这个例子中,`SAMPLEAPP_POINT_TO_POINT_CLUSTERID` 被设置为3,这意味着`SampleApp`有一个点对点通信的集群,其ID为3。当应用程序需要发送或接收点对点消息时,它将使用这个ID来识别相关数据的目的地或来源。
请注意,实际的集群ID应该符合Zigbee联盟或相关标准的规定,除非你创建了自定义的私有簇。在标准Zigbee簇中,ID范围从 `0x0000` 到 `0x0FFF`,而 `0x1000` 到 `0xFFFF` 通常用于私有或自定义簇。在你的`SampleApp`中,`3`作为一个自定义的点对点簇ID,表明了你的应用如何与其他设备进行特定的通信。
错误
很奇怪,换成终端编译一下没报错,换回协调器工作空间就可以了
改写之前
改之后
emmmmm,我把1改成协调器后不能正常运行,改回来就可以了,他原本是router
15.上板子现象
现象:router没有消息,协调器有之前的嗨喽world,其他的发消息能回调,返回一样的,协调器也可以,协调器还可以收到router和end device的shortaddr,但是不知道为什么,有时候收不到,三个程序下载需要顺序吗,下载进去的程序应该上电启动啊,上电会不会重置,应该会啊,之前重新开始就有hello world啊,但是之前好像是重新下载的,还有时候串口助手不显示,断开重连就可以了
16.掉电不能组网得问题解决了
ZIGBEE------协调器断开重连,终端设备无法重新入网。
现在只要上电就能收到数据
17.尝试多个end device
每个end device 短地址不一样
18.协调器发消息,终端收到,所有终端
`addrMode` 字段被设置为 `(afAddrMode_t)Addr16Bit`,这意味着目标地址模式被设置为16位短地址。在Zigbee网络中,设备通常使用16位地址进行通信,这是一种节省网络资源的方式,因为每个设备都有一个唯一的16位地址。
`endPoint` 字段被设置为 `SAMPLEAPP_ENDPOINT`,这代表了目标设备的端点号。在Zigbee协议中,端点(Endpoint)是设备上定义不同功能或服务的逻辑标识符。每个设备可以有多个端点,每个端点可以关联一个或多个绑定的簇(Cluster),簇定义了设备的具体功能,如照明控制、温度传感器等。
- `addr.shortAddr` 字段被设置为 `0x0000`。这表示目标设备的16位短地址是0x0000。在实际应用中,这个值应该替换为实际要通信的目标设备的16位网络地址。0000是协调器的
19.透传
这个函数自己定义
在Zigbee或类似的网络协议中,"集群"是设备上具有特定功能的一组相关命令和属性。每个集群都有一个唯一的ID,用于识别和区分不同的功能。这个数组可以用于存储设备支持的集群ID列表,例如在处理Zigbee网络中的事件或命令时,可以使用这个列表来确定设备是否响应特定的集群。
在`SampleApp`中,`SAMPLEAPP_PERIODIC_CLUSTERID`可能代表设备上一个用于周期性数据发送的集群,而`SAMPLEAPP_FLASH_CLUSTERID`可能与设备的固件更新或闪存操作相关。这些ID通常是由开发者自定义的,以便在应用程序代码中引用。
发送函数,这个就是节点发送给别的节点的函数,回调函数就是串口助手通过串口发送出去的数据显示到串口助手
调用发送函数如果有定时发送则调用点对点发送,点对点发送是何种设备号,并且设置了发送族群id,接收时通过id识别
这段代码处理`SAMPLEAPP_SEND_PERIODIC_MSG_EVT`事件,该事件通常由定时器触发,用于周期性地发送消息。
1. 当`events`变量的位掩码中`SAMPLEAPP_SEND_PERIODIC_MSG_EVT`被设置时,表示到了发送周期性消息的时间。
2. 调用`SampleApp_SendPointToPointMessage()`函数来发送点对点消息。这可能是向网络中的特定设备发送数据或命令。
3. 为了实现消息发送的随机抖动,函数使用`osal_start_timerEx`重新设置定时器,使得下一次发送发生在`SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT`基础上加上一个0到255的随机数(`osal_rand() & 0x00FF`)。这有助于防止网络中的多个设备同时发送消息,从而减少冲突。
4. 函数返回未处理的事件,移除了`SAMPLEAPP_SEND_PERIODIC_MSG_EVT`,以便操作系统知道这个事件已经被处理。
这个事件处理确保了周期性消息的发送,并通过随机抖动避免了网络中的同步问题。
发送函数事件置位
这段代码处理`ZDO_STATE_CHANGE`事件,这意味着设备在网络中的状态发生了变化。`MSGpkt->hdr.status`提供了新的状态信息。这里,`SampleApp_NwkState`被更新为新的网络状态,类型为`devStates_t`。 接着,代码检查`SampleApp_NwkState`是否为`DEV_ROUTER`或`DEV_END_DEVICE`。这些状态表示设备是网络中的路由器或终端设备,能够发送和接收数据。如果设备是这两种状态之一,它会启动一个定时器`SAMPLEAPP_SEND_PERIODIC_MSG_EVT`,该定时器在`SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT`(通常表示一个时间间隔,例如5秒)后触发。
如果有消息来就进入这个函数,乱码是说定义了一个定时器,设置定时发送SAMPLEAPP_SEND_PERIODIC_MSG_EVT是事件置位
这段代码是`SampleApp_ProcessEvent`函数的一部分,用于处理`SYS_EVENT_MSG`事件。当系统中有新的消息到达时,函数会进入这个事件处理流程。
SAMPLEAPP_PERIODIC_CLUSTERID发送与接收建立联系,通过id知道是点对点周期发送,再根据发送的数据判断是什么设备
case SAMPLEAPP_PERIODIC_CLUSTERID:”。这个就是在发送部分设置的表示周期性发送数据的编号
所有的数据和信息都在函数传进来的afIncomingMSGPacket里面
数据在cmd里
HalUARTWrite(0, &pkt->cmd.Data[0], pkt->cmd.DataLength);这个代码就是把收到的数据发送给串口
开始透传
修改接收函数
代码很长,注释基本写在代码里面了,总结一下流程。
①判断起始码是不是0xFE(不是就别想继续下去啦)
②读取数据长度,初始化串口数据包pMsg(mtOSALSerialData_t pMsg)
③给pMsg装数据
④校验和,正确则把pMsg向上发送,错误则丢弃
⑤初始化状态
我们要做的就是简化流程,因为我们发送的数据格式是只含有数据内容的,因此要把起始码、数据长度之类的去掉。但是这样会导致数据长度变成未知的,无法声明动态数组。改变思路,定义一个定长的数组!
20.组网 Zigbee协议栈————广播组网
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )//无线数据包接收到之后
协调器组网是通过zdo的程序循环发送消息,让别人检测到,因为是同信道
广播通信通常不涉及特定的拓扑结构,因为它涉及的是单个节点向网络中所有其他节点发送信息,而不关心接收者的确切位置。然而,在讨论无线通信网络时,我们可以说广播通信可以在多种拓扑结构中发生,包括但不限于以下几种:
1. **总线型(Bus Topology)**:在这种结构中,所有设备都连接到一条共享的通信线路上,广播通信天然地适用于总线型网络,因为一个节点发送的信息会被所有其他节点接收。
2. **环形(Ring Topology)**:在环形网络中,信息沿着环状路径从一个节点传到下一个节点,直到达到所有节点。虽然环形网络通常不设计为广播通信,但一个节点可以向环中发送广播消息,让信息绕环一周。
3. **星形(Star Topology)**:在星形网络中,所有节点都连接到一个中心节点(如路由器或交换机)。中心节点可以广播信息到所有连接的节点,即使这种拓扑设计通常用于点对点通信。
4. **树形(Tree Topology)**:树形拓扑是星形拓扑的扩展,其中有一个或多个层次的分支。中心节点可以广播到其下的所有子节点,子节点也可以继续广播给它们的子节点。
5. **网状(Mesh Topology)**:在网状网络中,每个节点都可以与多个其他节点直接通信。虽然不是所有的通信都是广播,但一个节点可以向其邻居广播信息,这些信息可以被转发到整个网络。
在无线通信中,广播通信通常与上述拓扑结构相结合,利用网络的广播特性将信息传递给所有节点或特定范围内的节点。例如,Wi-Fi网络中的无线接入点(AP)可以广播信息,让所有连接的客户端都能接收到。
实现的:模块发送串口数据,串口助手发送数据回调
21.如何使用Zigbee协议栈
以简单的无线数据通信为例,其一般步骤为:
- 组网:调用协议栈组网函数、加入网络函数,实现网络的建立和节点的加入。
- 发送:发送节点调用协议栈的发送函数,实现数据无线发送。
- 接收:接收节点调用协议栈的无线接收函数,实现无线数据接收。
由于协议栈都把这些函数都封装好了,因此我们用起来比较方便。大家可以了解一下下面的关键字:
CCM
:Counter with CBC-MAC
(Mode of Operation
)HAL
:Hardware Abstraction Layer
(硬件抽象层)PAN
:Personal Area Network
(个人局域网)RF
:Radio Frequency
(射频)RSSI
:Received Signal Strength Indicator
(接收信号强度指示)
CC2530 BasicRF
文件夹结构如下图:
docs
文件夹:打开文件夹,里面仅有一个名为CC2530_Software_Examples
的PDF
文档,文档的主要内容是介绍Basic RF
的特点、结构及使用。从中我们可以知道,里面Basic RF
包含三个实验例程:无线点灯、传输质量检测、谱分析应用。Ide
文件夹:打开文件夹后会有三个文件夹,以及一个cc2530_sw_examples.eww
工程,这个工程是上面提及的三个实验例程工程的集合。在IAR
环境中打开该工程,在workspace
看到如下文件夹:Ide\Settings
文件夹是在每个基础实验的文件夹里都会有的,它用于保存读者自己的IAR环境设置;Ide\srf05_CC2530
文件夹里面放有三个工程,即light_switch.eww
、per_test.eww
和spectrum_analyzer.eww
。Source
文件夹:该文件夹里面有apps
文件夹和components
文件夹。Source\apps
文件夹存放Basic RF
三个实验的应用实现的源代码;Source\components
文件夹包含着Basic RF
的应用程序使用不同组件的源代码。
打开文件夹WeBee CC2530 BasicRF\ide\srf05_cc2530\iar
路径里面的工程light_switch.eww
(无线点灯),我们的实验就是对它进行修改的。在介绍Basic RF
之前,来看看这个实验例程设计的大体结构。
Hardware layer
:这是实现数据传输的基础。Hardware Abstraction layer
:它提供了一种接口来访问TIMER
、GPIO
、UART
、ADC
等,这些接口都通过相应的函数进行实现。Basic RF layer
:为双向无线传输提供一种简单的协议。Application layer
:它是用户应用层,相当于用户使用Basic RF
层和HAL
的接口。我们通过在Application layer
就可以使用到封装好的Basic RF
和HAL
的函数。
Basic RF
由TI
公司提供,它包含了IEEE 802.15.4
标准的数据包的收发功能,但并没有使用到协议栈,仅仅让两个结点进行简单的通信。也就是说,Basic RF
仅仅是包含IEEE 802.15.4
标准的一小部分。其主要特点有:
- 不会自动加入协议,也不会自动扫描其他节点也没有组网指示灯(
LED3
)。 - 没有协议栈里面所说的协调器、路由器或者终端的区分,节点的地位都是相等的。
- 没有自动重发的功能。
Basic RF
的工作过程有启动、发射和接收。使用Basic RF
实现无线传输只要学会使用这些过程的相应函数就可以了。
启动的要求如下:
1. 确保外围器件没有问题。
2. 创建一个basicRfCfg_t
的数据结构,并初始化其中的成员,在basic_rf.h
代码中可以找到:
typedef struct {
uint16 myAddr; /* 16位的短地址(就是节点的地址) */
uint16 panId; /* 节点的“PAN ID” */
uint8 channel; /* RF通道(必须在11至26之间 */
uint8 ackRequest; /* 目标确认就置为true */
#ifdef SECURITY_CCM /* 是否加密,预定义里取消了加密 */
uint8 *securityKey;
uint8 *securityNonce;
#endif
} basicRfCfg_t;
3. 调用basicRfInit
函数进行协议的初始化,在basic_rf.c
代码中可以找到:
uint8 basicRfInit ( basicRfCfg_t *pRfConfig );
函数功能是对Basic RF
的数据结构初始化,设置模块的传输通道、短地址和PAD ID
。
发送过程如下:
1. 创建一个buffer
,把payload
放入其中,Payload
不大于103
个字节。
2. 调用basicRfSendPacket
函数发送,并查看其返回值。在basic_rf.c
中可以找到:
uint8 basicRfSendPacket ( uint16 destAddr, uint8 *pPayload, uint8 length )
参数destAddr
是目的短地址,pPayload
是指向发送缓冲区的指针,length
是发送数据长度。函数功能是给目的短地址发送指定长度的数据,发送成功刚返回SUCCESS
,失败则返回FAILED
。
接收过程如下:
1. 上层通过basicRfPacketIsReady
函数来检查是否收到一个新数据包。在basic_rf.c
中可以找到:
uint8 basicRfPacketIsReady ( void );
函数功能是检查模块是否已经可以接收下一个数据,如果准备好了,则返回TRUE
。
2. 调用basicRfReceive
函数,把收到的数据复制到buffer
中。代码可以在basic_rf.c
中找到:
uint8 basicRfReceive ( uint8 *pRxData, uint8 len, int16 *pRssi );
函数功能是接收来自Basic RF
层的数据包,并为所接收的数据和RSSI
值配缓冲区。