
打开GenericApp工程,在Workspace中我们可以看到有这几个选项

Coordinator:协调器、RouterEB:路由器、EndDevice:终端节点,选择不同的选项,编译后就会生成不同的固件。现在我们就先写一个协调器吧。
1、协调器串口功能的使用
在GenericApp.c中的GenericApp_Init函数中添加我们的串口初始化函数
halUARTCfg_t uartconfig;
uartconfig.configured = TRUE;
//设置串口的波特率38400
uartconfig.baudRate = HAL_UART_BR_38400;
uartconfig.flowControl = FALSE;
//设置串口回调函数SerialCallBackFunc
uartconfig.callBackFunc = SerialCallBackFunc;
//打开串口
HalUARTOpen(0,&uartconfig);
一旦上电,协议栈就回调用GenericApp_Init函数对串口进行初始化,说白了就是对寄存器初始化一下,如果实在闹不明白也可以自己直接对寄存器操作。但是如果只是添加了上面的代码,你会发现,串口是没有反应的,CC2530有两个串口:P02&P03 P04&P05,这里我们一般用P02&P03,不要问我为什么,我也不知道我为什么习惯用这个串口。这个时候我们还要在预编译中添加ZTOOL_P1才能使能这个串口。如果你还在看这篇帖子,说明你才刚开始学习ZigBee,预编译选项在哪里请参考我的ZigBee开发环境的搭建与IAR的配置使用这篇帖子。然后我们再写一个串口回调函数:
static void SerialCallBackFunc(uint8 port, uint8 event)
{
unsigned char serialdata[256];
unsigned char seriallength;
//读取串口数据
seriallength = HalUARTRead(0,serialdata,256);
GenericApp_SendTheMessage(serialdata,seriallength,0xFFFF);//0xFFFF广播
URX0IF = 0;
}
HalUARTRead的返回值是当前收到的缓冲区的长度,这点协议栈已经封装过了,不用自己去拼接,是不是很爽!好了,现在编译一下,肯定报错了,第一,还没有申明串口回调函数,第二,我改了一下GenericApp_SendTheMessage这个函数。
Void GenericApp_SendTheMessage(
unsigned char *theMessageData,
unsigned char theMessageDataLength,
unsigned int theMessageAddr )
{
//使用网络地址传输
GenericApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; //点对点传输GenericApp_DstAddr.endPoint = GENERICAPP_ENDPOINT; //目的地址GenericApp_DstAddr.addr.shortAddr = theMessageAddr; //调用发送函数AF_DataRequest( &GenericApp_DstAddr, &GenericApp_epDesc,GENERICAPP_CLUSTERID, theMessageDataLength, theMessageData,&GenericApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ); }
修改GenericApp_SendTheMessage这个函数后也记得修改下他的申明,再次编译就OK了,现在你串口收到的所有数据都将发送给这个网络中的所有节点。
2、协调器无线收据的收发
完成了串口数据的接收,我们再来看看协调器在哪里,怎么去处理无线数据。
同样,在这个GenericApp.c文件中,我们找到GenericApp_ProcessEvent函数,这个函数是GenericApp任务的事件处理函数,在这个函数中,无线数据处理的地方就在AF_INCOMING_MSG_CMD这个case中显然,协议栈在收到无线数据后调用了GenericApp_MessageMSGCB( MSGpkt );函数,向其传递了afIncomingMSGPacket_t指针,这个指针中包含的数据都可以goto看得到,这里不再赘述。在GenericApp_MessageMSGCB函数中我们就可以对我们的无线数据进行处理了。
/*查找匹配簇ID,具体簇ID是个什么玩意儿,baidu有很多这里给出一个链接,大家可以看看
http://www.360doc.com/content/13/1211/21/14855936_336431501.shtml
*/
switch ( pkt->clusterId )
{
case GENERICAPP_CLUSTERID:
//添加对无线数据的处理,串口直接打印,pkt就是上面提到的afIncomingMSGPacket_t指针
HalUARTWrite(0,pkt->cmd.Data,pkt->cmd.DataLength); break;
}
其他多余的代码其实可以删掉了,反正也没用(有用除外,放着碍眼)。
到此,协调器的编程就到此OK了,现在可以通过串口发送数据给协调器,协调器广播给所有节点,如果协调器收到了无线数据也会通过串口打印出来。
这里有个坑,我一直没弄明白,有时候莫名其妙的我串口打印的时候,第二个字节会丢掉。后来我自己重写了下HalUARTWrite就OK了。如果有哪位朋友知道还望点明啊。
3、节点无线数据和串口数据的处理
其实节点的编程和协调器的编程差不多,在Workspace中改选EnddeciveEB

编译同样能够通过,但是请注意,第一,预编译中同样需要加ZTOOL_P1,第二,在节点的串口回调函数中,数据任然是广播的形式发送的,也就是所有节点都能收到。在这里我们只需要发送给协调器即可,所以在串口回调函数中我们做如下改动:
static void SerialCallBackFunc(uint8 port, uint8 event)
{
unsigned char serialdata[256];
unsigned char seriallength;
//读取串口数据
seriallength = HalUARTRead(0,serialdata,256);
#if defined (ZDO_COORDINATOR)
//如果编译的是协调器就广播
GenericApp_SendTheMessage(serialdata,seriallength,0xFFFF);//0xFFFF广播
#else
//否者如果是路由节点或者是终端节点,就将数据发送给协调器
GenericApp_SendTheMessage(serialdata,seriallength,0x0000);//0x0000是协调器的网络地址
#endif
URX0IF = 0;
}
编译后下载到终端节点。
4、总结
广播速度不能太快了,否则你会发现节点丢包很严重的,一个是因为协调器需要缓存串口的数据,另一个原因是终端节点是靠轮询来获取父节点上的数据的,大量使用广播还会造成其他问题,例如广播风暴。
本文转载自Internet of Things。
长按左侧二维码,识别关注

