在Zigbee网络里,模块间通信时,发送的模块非常明确知道接收模块的网络地址,以这个地址发送数据给接收模块,叫单播。
Zigbee模块在入网时父节点会随机分配网络地址给子节点,但协调器模块在网络中地址永远是0x0000。
那么基于ZStack协议栈,做一个发送模块需要做哪些修改呢?
在应用层GenericApp的GenericApp_ProcessZDOMsgs函数中,
有如下代码
GenericApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
GenericApp_DstAddr.addr.shortAddr = pRsp->nwkAddr; //发送目标地址
// Take the first endpoint, Can be changed to search through endpoints
GenericApp_DstAddr.endPoint = pRsp->epList[0]; //终端地址
将shortAddr改成0x0000表示发送给协调器。
endPoint改成GENERICAPP_ENDPOINT表示自己的地址。(在Init函数中可以找到)
ZStack在应用层的.c文件中最后有一个GenericApp_SendTheMessage函数。其效果是将hello world发送到空气中。我们可以用其中的代码来发送我们想要发送的东西
char theMessageData[] = {8};
GenericApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
GenericApp_DstAddr.addr.shortAddr = 0x0000;
GenericApp_DstAddr.endPoint = GENERICAPP_ENDPOINT;
AF_DataRequest( &GenericApp_DstAddr, &GenericApp_epDesc,
GENERICAPP_CLUSTERID,
1, //这里表示要发送的字节数,我们只发一个8,所以就1个字节
(byte *)&theMessageData,
&GenericApp_TransID,
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
这就完成了一个发送的指令修改。
那么基于ZStack协议栈,做一个接收模块需要做哪些修改呢?
在应用层.c中有一个函数名为GenericApp_MessageMSGCB
他负责处理数据接收。直接可以从pkt->cmd.Data中获取发送数据。
另外可以在事件处理函数中找到它的AF_INCOMING_MSG_CMD消息,也就是数据接收消息。这个消息调用了GenericApp_MessageMSGCB函数。
也就是协调器模块底层任务拿到了这个无线数据,然后将它发送给了应用层一个消息,在消息处理中将有用的数据拿出来处理。
上边呢是发送数字的,现在让发送端发送字符串
//发送端
char theMessageData[] = "Hello Jhou";
GenericApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
GenericApp_DstAddr.addr.shortAddr = 0x0000;
GenericApp_DstAddr.endPoint = GENERICAPP_ENDPOINT;
AF_DataRequest( &GenericApp_DstAddr, &GenericApp_epDesc,
GENERICAPP_CLUSTERID,
(byte)osal_strlen(theMessageData) + 1, //在c中,字符串末尾默认有个\0。要一并发送
(byte *)&theMessageData,
&GenericApp_TransID,
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
接收端 字符串可以用串口验证。请参照先前的串口文章.没什么特别的
将串口初始化函数放在ZMain的main函数靠近系统启动的最底下,并且引入相关头文件
如何配置自定义串口初始化
在引入自定义串口初始化时,要注意将ZStack底层的串口初始化函数给做一些处理。
在ZMain的Main函数中找到HalDriverInit函数,这是驱动初始化的函数,转到定义后寻找HalUARTInit函数,这是串口初始化函数。我们将if中的HAL_UART这个宏转到定义,将它的值改成False来预防默认的串口初始化,从而使用我们自己的初始化函数。
若要在应用层使用串口通信,记得引用头文件
还有地方 再来占楼一波~