大数跨境

ZigBee最简单的串口透传例程

ZigBee最简单的串口透传例程 芯片之家
2017-03-27
2
导读:打开GenericApp工程,在Workspace中我们可以看到有这几个选项Coordinator:协调器、

打开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。


芯片之家

长按左侧二维码,识别关注




【声明】内容源于网络
0
0
芯片之家
1234
内容 1436
粉丝 0
芯片之家 1234
总阅读252
粉丝0
内容1.4k