Zigbee MAC地址通信中发送模块指定了接收模块MAC地址却发送不了数据包的解决办法
事情缘由
在做MAC地址通信的实验中,我将程序分别下载进模块,组网成功后,发送模块终端按下按键,接收模块协调器什么反应也没有,上位机也没接收到消息。
通过抓包发现,按下按键的时候确实没有数据包发出。只有协调器模块和终端模块之间进行父子点询问的帧和协调器模块的网络状态帧。并没有我们按下按键通过指定协调器MAC发送的数据帧。
经过半天的百度查阅,但网上关于Zigbee模块MAC地址通信的资料少之又少,困扰了我一晚上,找到了一个可能可行的方法。
我参考了这篇博客https://www.cnblogs.com/gary-guo/p/5737076.html
错误原因
首先我们要搞清楚MAC地址通信的本质是什么:
在网络里面的每一个zigbee模块,它都有一个地址管理器,它会记录与它经常通信的模块的MAC地址以及网络短地址,然后存放到地址管理器里面;
以MAC地址发送数据:在数据发送的时候,它会去检查地址管理器看是否有对应的MAC地址,如果有,那么它会把对应的网络短地址放到无线数据包里面去发送;如果没有对应的MAC地址,为了确保通信成功,那么我们应该怎么做呢?
其中ZDP_NwkAddrReq(DestMac,ZDP_ADDR_REQTYPE_SINGLE,0,0);的作用是让MAC对应的目标模块将当前的网络短地址回复给我
然后收到对应MAC地址的网络短地址后,就可以在地址管理器当中建立这样的映射关系,然后延时30毫秒,发送事件,GENERICAPP_SEND_MSG_EVT,然后进入到该事件里面去发送实际的数据
将程序下载到模块进行抓包
我们发现,按下按键后,请求网络地址的通信过程是正常的,而终端依然无法将数据通过MAC地址发送给协调器。不过至少验证了模块硬件没有问题。
最后我重新安装了一个TI 协议栈:ZStack-CC2530-2.3.0-1.4.0,我原来使用的版本是ZStack-CC2530-2.5.1a。
将我们的原终端程序重新移植到新的新协议栈,通信成功!
char theMessageData[] = "Zigbee MAC实验";
uint8 DestMac[8]={0xFD,0xE7,0x59,0x2A,0x00,0x4B,0x12,0x00};//0x00124B002A59E7FD
GenericApp_DstAddr.addrMode = (afAddrMode_t)Addr64Bit;//发送模式是MAC
//StarryApp_DstAddr.addr.shortAddr = 0x0000;
memcpy(GenericApp_DstAddr.addr.extAddr,DestMac,8);
// Take the first endpoint, Can be changed to search through endpoints
GenericApp_DstAddr.endPoint = GENERICAPP_ENDPOINT;
AF_DataRequest( &GenericApp_DstAddr, &GenericApp_epDesc,
GENERICAPP_CLUSTERID,
(byte)osal_strlen( theMessageData ) + 1,
(byte *)&theMessageData,
&GenericApp_TransID,
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
最终现象
抓包发现,按下S1后,终端成功通过协调器的MAC地址发送了数据包给协调器
串口也成功接收到数据
结果分析
我们可以发现,发送数据包的目标地址不是MAC,而是目标的网络短地址。
这是因为当以MAC地址进行发送的时候,发送模块首先会查看自己的地址管理器有没有节点的MAC与我们所指定通信的MAC地址是一致的。如果发现有,它会将目标节点的网络短地址作为无线数据包的发送地址。如果两个模块之间距离很远,且不怎么互相通信,地址管理器查不到对方的MAC。那我们在发送数据包前就必须使用网络短地址请求函数
ZDP_NwkAddrReq(DestMac,ZDP_ADDR_REQTYPE_SINGLE,0,0);
通过发送一个信号,来让我们的MAC地址对应的模块把网络短地址回复给我们,之后等待30ms再发送(确保发送模块成功获取目标模块网络地址),就一定会成功。这也是我刚刚提到的一个解决数据包发送失败的处理办法。