开发者学堂课程【嵌入式之RFID开发与应用2020版:Zigbee 数据收发原理介绍】学习笔记与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/665/detail/11137
Zigbee 数据收发原理介绍
内容简介
一、zstack配置
二、创建端点
三、发数据函数
一、zstack配置
组完网络,接下来就要介绍通信,首先了解一下协议配置
1.在协议栈的Projects\zstack\Tools\CC2530DB下有几个配置文件:
F8wConfig.cfg,包含信道channel、panID、绑定表、加密方式等相关公共配置。终端、路由器都可以
F8wCoord.cfg,协调器配置。
F8wRouter.cfg,路由器配置。
F8wEndDev.cfg、终端配置。
打开工程SampleApp.eww
左边有一列工作空间,主要用的是 coordinatoiEB、routerEB、enddeviceEB
选择不同的工作空间,本质上也是 zstack 配置文件的选择,还有一些宏的区别
工作空间右键找到 options
-f $PROJ_DIR$\ 1. \Tools\CC2530DB\f8wEndev.cfg
-f $PRDJ_DIR$\ . 1. \ToolsACC2530DB\f8wConfig.cfg
当前选中的是协调器,对于协调器来说,它所引入的配置文件,就是有一个文件,和它的公共文件
接下里将工作空间切换成设备,再打开 options
此时 coord 就会切换成 endev,公共配置文件不变
所以在对公共空间进行切换的时候,也是在完成不同的配置,所以编辑的代码不相同,同样的代码编出不一样的结果
2.Zstack 通信地址:
路由或终端首次入网过程:
NLMENetworkDiscovervReauest(uint32ScanChannels,uint8 scanDuration);
//指定信道和扫描时间发现网络
路由或终端首次入网接口对应回调:
ZDO NetworkDiscoveryConfirmCB(status)
入网成功后又失去联系的回调函数:
ZDO_SyncIndicationCB()
路由器重新入网:
nwk_ScanJoining0rphanO
终端重新入网:
NLME_OrphanJoinRequest()
想获得地址,
常用地址函数接口://以 NLME 开头都是不可见的
>NLME_GetShortAddr()//获取本节点短地址
>NLME_GetExtAddr()//获取本节点长地址
NLME_GetCoordShortAddr()//获取父节点短地
NLME_GetCoordExtAddr()//获取父节点长地址
二、创建端点
1.接下里介绍一下通信过程,主要介绍点播通信,不管用什么通信,首先是要创建端点
typedef struct
uint8 endPoint;//端点号1-240任选一个
uint8 *task_id;//当前任务ID
SimpleDescriptionFormat_t *simpleDesc;//端点简单描述符
afNetworkLatencyReq_t latencyReq;//网络延迟信标设置,一般默认参数noLatencyReqs
endPointDesc_t;
2.将这些参数全部设好后,用到注册函数
Afregister( endpotintdesc_t *epdesc)
注册后才能够收到数据,也能够发送数据
为什么接收和发送数据都要注册端点?
在 demoapp 文件中有自己的任务 mutask,如果协议站收到了一包数据 pack, 如何通知给自己的任务,所以任务 id 就是与自己的任务对应起来的,当我们有一天收到一包数据的时候,发现端点是设定的端点号,id 是当前任务的 id,然后就能发给自己的任务一个消息(数据监控器),这样才能拿到数据包,去解析数据,这是定义端点的一个很重要的原因
不仅任务号要对、端点号也要对,例如注册的端点号是10,发来的数据包为20,是不能得到数据的,所以必须要同时满足
// 端点描述符就是对应端点一些参数的说明:
typedef struct
uint8 EndPoint;//端点号1-240
uinl Aoobcefeadyd用的,表示应用领域比如建筑、衣业,家居等
uint8 AppDevVer:4;//应用设备版本号
uint esoetacl(用/输入误命令个数
cld_t*pAppInClusterList;//输入簇命令ID列表,如打开、关闭、停止等操作命令
uint8 AppNumOutClusters;//输出簇命令个数
cld_t*pAppOutClusterList;//输出簇命令ID列表,如温度、湿度等传感数据 SimpleDescriptionFormat_t;
以上参数,除去端点号,其它只是建议数据,例如应用程序是应用在建筑、农业、家具、灯、哪个电器...,这里就要用到簇命令,可以叫做命令列表,端点 appprofld 的主要应用方向是只能家居,然后可以控制冰箱、空调、加湿器....,任何东西都有独立的 id,方便以后区分
收到的数据究竟是控制空调还是冰箱,可以区分好
所有数据计算好后,就可以通过 afregister 注册
三、注册完后,发数据函数
1.发数据函数参考
AF_DataRequest(
afAddrType_t*dstAddr,//目标地址
endPointDesc_t*srcEP,//源端点
uint16 cID,//簇命令ID,对于接收方可以通过该命令来区分数据包
uint16 len,//发送数据的长度
uint8buf,//发送数据的起始地址
uint8*translD,//事务ID,可以是包计数器,用于信息确认
uint8 options,//告知AF层做的一些预处理,一般为AF _DISCV ROUTE
uint8 radius)//转发数据最多经过的路由深度(AF_DEFAULT RADIUS)
除了发给谁以外,第二个参数就是端点的数据结构,以及本次数据所包含的信息,是前面智能家居中的哪一项命令,例如加湿器命令会有一个编号,对方收到后就可以知道这条命令是对加湿器的控制或数据采集
接收的时候由于整个底层协议已经被封装,在接收过程中会很被动,因为唯一知道的接收数据就是任务被调,被执行。如何区分被调的是 b 内数据还是其他数据
打开任务处理函数,首先会收到 SYS_EVENT_MSG,然后根据消息里面的事件判断,是节点网络发生变化
break;
case AF INCOMING MSG CMD;
my_MessageNSGCB(MSGpkt)
break;
case CMD SERIAL MSG:
代表发来的数据是什么类型的,AF_INCOMING_MSG_CMD就是协议站在任务发送的数据,通过这个就能判断是 b 协议站发来的数据包,可以从消息队列里提取出消息,并且把数据拿到
2.接收数据中断回调过程:
(1)afIncomingDataO->afBuildMSGIncomingO
(2)afIncomingMSGPacket_t*MSGpkt;//封装所有接收到的信息到数据结构,并通过消息上报给应用层任务处理:
申请接收数据缓存
MSGpkt->hdr.event = AF_INCOMING_MSG_CMD;
osal_msg_send(*(epDesc->task_id),(uint8 *)MSGpkt)
(3)上层任务被触发后会不断接收并处理消息:
osal_msg_receive(task ID)
3.判断事件类型,并处理接收到的消息中的数据包
释放接收数据缓存
在发送数据的时候会涉及到一些地址的概念,发送的对象会涉及到地址的类型:长地址、短地址、组播地址
不同的地址要选择不同的模式,选择长地址、模式就是长地址,选择组播,模式就是组播模式,以此类推,以及要指定端点号、网络 id,指定完后才能将数河北据发给唯一设备
后面内容就是具体怎样通过软件、代码来实现入网,以及加入到网络之后,怎样去给指定的对象发送、接收采集到的数据数据。