ZigBee笔记(zstack篇)

前言

由于一些原因放弃个人博客,先逐渐将博客内容搬运至CSDN,本文原写于年初。zigbee篇默认掌握8051框架。

zstack协议栈是ZigBee学习中极为重要的一部分,在实践中我们主要利用官方的库进行添加修改。本篇所述版本为Zstack-CC2530-2.3.0-1.4.0.

基础概念

ZigBee堆栈是在IEEE 802.15.4标准基础上建立的,定义了协议的MAC和PHY层。ZigBee设备应该包括IEEE802.15.4(该标准定义了RF射频以及与相邻设备之间的通信)的PHY和MAC层,以及ZigBee堆栈层:网络层(NWK)、应用层和安全服务提供层。图1给出了这些组件的概况。

ZigBee协议栈相当于一个小型的操作系统(一系类代码),协议栈可实现ZigBee协议。用户只需要使用协议栈提供的API进行开发即可,具体细节不必关注。我们要关心的是数据怎么发出去、从哪里发出去,数据怎么接受,从哪里接受、使用了那些函数。

Zigbee主要通信方式有单播、组播、广播、绑定和MAC通信这五种。

除此还要介绍一个工具——USBDongle,该工具可抓取空间中无线数据包,可用分析协调器建网、路由器、终端入网过程。

单播通信

在Zigbee网络里,模块之间要进行通信,发射模块非常明确知道接收模块的网络地址,以这个地址发送数据给接收模块,叫单播。

Zigbee模块的地址特点:
模块在入网的时候,父节点随机分配网络地址给子节点。但是协调器模块在网络里的地址永远是0x0000.

具体过程:
//这里我们把终端作为发送模块,协调器作为接受模块
发送字符的流程
在ORIApp.c文件里的ORIApp_MY_EVT 事件处理中(UINT16 SDApp_ProcessEvent( byte task_id, UINT16 events )按钮1 按下的相关处理代码
该处代码可在ORIApp.c文件最下方void SDApp_SendTheMessage( void )中获取。


char theMessageData[] ="Hello ";

ORIApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
ORIApp_DstAddr.addr.shortAddr = 0x0000;//接收模块的网络地址
// Take the first endpoint, Can be changed to search through endpoints
ORIApp_DstAddr.endPoint =ORIApp_ENDPOINT ;//接收模块的端点房间号

//SDApp_epDesc 结构体 端点描述符有源端点的信息,也是10

AF_DataRequest( &SDApp_DstAddr, &ORIApp_epDesc,
ORIApp_CLUSTERID,//目标端点镞,房间里的接收人数据宏是1,2个字节,所以在射频0x0001
(byte)osal_strlen( theMessageData ) + 1,//发送字符串的长度
(byte *)&theMessageData,//字符串内容数组的首地址
&ORIApp_TransID,
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );

P1SEL &=0Xfe;// 1111 1110
P1DIR |=0X01;
P1_0 ^=1;

接受模块

大致过程:把协调器作为接收模块,当终端模块发送数据时候,协调器模块底层任务拿到这个无线数据,给我们应用层任务发送一个AF_INCOMING_MSG_CMD在消息处理里,把有用数据拿出来在数码管上显示。

因为要接收字符串,移植串口模块化文件
UART.C UART.h头文件到 工程源文件目录
在ZMain.c文件的main 靠近模块void InitUart();
取消TI默认对串口的配置在main函数 HalDriverInit函数 把宏#define HAL_UART FALSE
在ZMain,c添加UART.h头文件
初始化算完成了
Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength);
记得在SDApp.c文件添加UART.h头文件

端点Endpoint

  1. 他是一个字节编号的,数据收和发送的基本单元,在模块通信的时候,发送模块必须指定收发双方模块的网络地址和端点。
  2. 端点要使用必须要和模块里的某个任务挂钩定义;首先每一个端点可以看成是一个1个字节数字编号的开有一扇门的房间,数据最终的目标是进入到无线数据包指定的目标端点房间,而取无线数据这个相关的代码在任务事件处理函数里,TI协议栈有那么多的任务事件处理函数,所以必须要指定在哪个任务事件处理函数 来取这个无线数据包里面的有用数据。
  3. 一个端点只能挂钩在一个任务上,而一个任务可以挂钩多个端点,且端点对所有的任务是公用的,定义一个少一个。
    一个端点加入可以挂钩在多个任务上,那么接收模块接到无线数据时候,这个时候同一个端点有多个任务事件处理函数去处理,不合理;一个任务上挂多个端点(6 7 挂应用层任务),发送给协调器模块的6 7端点的数据都会进入到应用层任务事件处理函数里来,仅仅做个判断到底是投递到6房间还是7号房间就可以了。

簇 ClusterID
簇就是相当于端点房间里面的人,是接收最终的目标。这东西是2个字节编号,在射频发送的时候,必须要指定接收模块的簇,发送模块不需要指定。

具体过程:
端点挂钩:


SDApp.c

void SDApp_Init( byte task_id ) //定义了10号端点并且和这个模块的应用层任务挂钩
{
....
// Fill out the endpoint description.
SDApp_epDesc.endPoint = 10;//SDApp_ENDPOINT; 此端点编号为10
SDApp_epDesc.task_id = &SDApp_TaskID; 和我们应用层任务挂钩
SDApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&SDApp_SimpleDesc;//更加详细的描述这个端点一些情况就像我们定义一个编号房间,描述房间里大概有多少人之类的信息。
SDApp_epDesc.latencyReq = noLatencyReqs;//差不多
// Register the endpoint description with the AF
afRegister( &SDApp_epDesc );//这个函数必须要调用才能完成整个挂钩操作
...
}

无线数据包发出去以后,首先目标协调器模块的网络地址0x0000对上了,协调器可以拿到这个无线数据包在底层任务,判断10号端点房间已经定义且和应用层任务挂钩,那么这个无线数据包发送一个消息到应用层任务

case AF_INCOMING_MSG_CMD:
SDApp_MessageMSGCB( MSGpkt );
break;

端点在带编号的房子,代码里一个结构体SDApp_epDesc
在消息处理里,把接受的数据通过串口送出去

Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength);

在void SDApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )函数里添加这行代码就可实现把接受的数据在led上呈现。


LS164_BYTE(pkt->cmd.Data[0]);

补充:

在发送模块里,我们用的数据发送源端点,也是10,所以我们也定义这个10端点也挂钩应用层任务,原则上,外部给我们终端模块10号端点来数据,也会进入终端应用层任务事件处理 函数里。而我们这个端点仅仅这里作为发送模块,但是我们要实用10端点,必须要挂钩定义。

补充:
发送帧里面的东西在代码里体现
byte SDApp_TransID; // This is the unique message ID (counter) SDApp.c全局变量,记录我们引用层任务发送的数据包的个数。


void SDApp_Init( byte task_id )

{
SDApp_TransID = 0;
}

补充参考代码

"发送模块"

#define SDApp_PROFID 0x0F04是在端点描述符里有提到,所以在无线数据包里有看到


if(0==P1_1)
{//按钮3按下
char theMessageData[] ="Hello lao da";






SDApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
SDApp_DstAddr.addr.shortAddr = 0x0000;//接收模块的网络地址
// Take the first endpoint, Can be changed to search through endpoints
SDApp_DstAddr.endPoint =SDApp_ENDPOINT ;//接收模块的端点房间号


//SDApp_epDesc 结构体 端点描述符有源端点的信息,也是10


AF_DataRequest( &SDApp_DstAddr, &SDApp_epDesc,
SDApp_CLUSTERID,//目标端点镞,房间里的接收人数据宏是1,2个字节,所以在射频0x0001
(byte)osal_strlen( theMessageData ) + 1,//发送字符串的长度
(byte *)&theMessageData,//字符串内容数组的首地址
&SDApp_TransID,
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );




P1SEL &=0Xfe;// 1111 1110
P1DIR |=0X01;
P1_0 ^=1;


发送模块
1、定义11号端点与应用层任务挂钩
char theMessageData[] ={3};
SDApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
SDApp_DstAddr.addr.shortAddr = 0x0000;
// Take the first endpoint, Can be changed to search through endpoints
SDApp_DstAddr.endPoint = 7;


AF_DataRequest( &SDApp_DstAddr, &SDApp_epDesc,
0x0001,
1,//(byte)osal_strlen( theMessageData ) + 1,
(byte *)&theMessageData,
&SDApp_TransID,
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ORI2333

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值