您好,欢迎访问三七文档
当前位置:首页 > 临时分类 > ZigBee简易串口透传
1第十六讲ZigBee串口透传一、串口透明传输工程说明串口透明传输工程是在SampleApp工程基础之上进行修改而成,主要功能是完成简单的串口透明传输,功能要求:1、设备上电后自动选择设备类型。第一个启动的设备为协调器,后续启动的为路由器。(所有设备中程序相同)2、路由器的232串口接收到数据后将数据以单播的形式发送到协调器。当路由器接收到来自空中的数据包将数据写入232串口。3、协调器的232串口接收到数据后将数据以广播的形式发送到网络中所有的设备。当协调器接收到来自空中的数据包将数据写入232串口。图X串口透明传输应用二、编译选项说明串口透明传输工程在SampleApp工程基础之上进行修改,但是编译选项使用原SampleApp工程的编译选项,SampleApp工程编译选项具体如下:CC2430EB、ZTOOL_P1、MT_TASK、SOFT_START通过编译选项ZTOOL_P1编译选项SOFT_START。三、工程初始化与事件处理函数串口透明传输工程来源于对SampleApp工程的修改,工程初始化函数与SampleApp工程的初始化函数完全相同,读者可以参见前面章节。串口透明传输工程事件处理函数在SampleApp工程事件处理函数的基础之上添加了对事件UART_RX_CB_EVT的处理,具体代码如下。程序代码:uint16SampleApp_ProcessEvent(uint8task_id,uint16events){if(events&SYS_EVENT_MSG){while(MSGpkt)PC机协调器路由器路由器传感器传感器路由器传感器2{switch(MSGpkt-hdr.event){caseKEY_CHANGE:……break;caseAF_INCOMING_MSG_CMD:……break;caseZDO_STATE_CHANGE:……break;default:break;}}return(events^SYS_EVENT_MSG);}if(events&SAMPLEAPP_SEND_PERIODIC_MSG_EVT){……return(events^SAMPLEAPP_SEND_PERIODIC_MSG_EVT);}if(events&UART_RX_CB_EVT)//串口有数据需要处理{SampleApp_SPI_SendData(rbuf,rxlen+1);//调用处理函数,将信息发送出去return(events^UART_RX_CB_EVT);}return0;}四、工程修改1、添加事件串口透明传输工程在SampleApp工程基础上添加事件UART_RX_CB_EVT,当串口回调函数有接收到数据后将触发该事件,该事件在SampleApp.h中被定义,具体代码如下。程序代码:#defineUART_RX_CB_EVT0x00022、回调函数编译选项中的ZTOOL_P1说明原SampleApp工程默认使用Z-Tool,我们这里对其修改,将其在串口初始化中的回调函数函数进行修改。程序代码:3voidSPIMgr_Init(){……#ifdefined(ZTOOL_P1)||defined(ZTOOL_P2)uartConfig.callBackFunc=rxCB;……}相应我们在SPIMgr.c文件中添加该回调函数rxCB(uint8port,uint8event),具体代码如下。程序代码staticvoidrxCB(uint8port,uint8event){externuint8SampleApp_TaskID;rxlen=Hal_UART_RxBufLen(SPI_MGR_DEFAULT_PORT);//接收缓冲区数据长度,字节为单位rbuf=osal_mem_alloc(rxlen+1);//多分配1字节,分配如下rbuf[0]=rxlen;//一字节存放数据长度HalUARTRead(SPI_MGR_DEFAULT_PORT,rbuf+1,rxlen);//读接收缓冲区数据到内存databuf+1if(!rxlen)osal_mem_free(rbuf);//释放内存osal_set_event(SampleApp_TaskID,UART_RX_CB_EVT);}3、发送函数当串口接收到数据在串口回调函数中触发事件UART_RX_CB_EVT,应用层对其处理,并最终调用数据发送函数将串口接收到的数据发送出去。为此我们在SampleApp工程基础之上添加了数据发送函数SampleApp_SPI_SendData(),该函数具体如下。程序代码voidSampleApp_SPI_SendData(uint8*buf,uint8len){if(devStartMode==MODE_HARD)//如果启动的时候是协调器,则用广播{SampleApp_SPI_SendData_DstAddr.addrMode=(afAddrMode_t)AddrBroadcast;SampleApp_SPI_SendData_DstAddr.endPoint=SAMPLEAPP_ENDPOINT;SampleApp_SPI_SendData_DstAddr.addr.shortAddr=0xFFFF;}else//其它设备类型则用单播{SampleApp_SPI_SendData_DstAddr.addrMode=(afAddrMode_t)Addr16Bit;SampleApp_SPI_SendData_DstAddr.endPoint=SAMPLEAPP_ENDPOINT;SampleApp_SPI_SendData_DstAddr.addr.shortAddr=0x0000;}4if(AF_DataRequest(&SampleApp_SPI_SendData_DstAddr,(endPointDesc_t*)&SampleApp_epDesc,SAMPLEAPP_FLASH_CLUSTERID,len,buf,&SampleApp_TransID,0,AF_DEFAULT_RADIUS)==afStatus_SUCCESS){osal_mem_free(rbuf);//必须释放内存,不然造成溢出!}else{osal_mem_free(rbuf);//必须释放内存,不然造成溢出!}}五、数据流程该串口透明传输工程与同为串口透明传输的SerialApp工程相比数据流程有很大的区别。该工程主要实现了多对一的数据透明传输,即协调器向所有路由广播,而路由器单播发送数据到协调器。数据流可分为两大部分,协调器到路由器和路由器到协调器。下面我们梳理协调器到路由器数据流程,而路由器到协调器数据流程与其类似,读者可以自行对其梳理。协调器到路由器数据流程的流程图如图X所示。PC机串口回调函数触发事件发送数据触发事件处理事件写入串口232串口设备图X协调器到路由器数据流程图1、回调函数当与协调器连接的设备(通常为PC机)向协调器通过232串口写入数据时,协调器的串口回调函数将处理相关信息,并在串口回调函数中触发事件UART_RX_CB_EVT通知应用层进行处理。串口回5调函数代码如下。程序代码staticvoidrxCB(uint8port,uint8event){externuint8SampleApp_TaskID;rxlen=Hal_UART_RxBufLen(SPI_MGR_DEFAULT_PORT);//接收缓冲区数据长度,字节为单位rbuf=osal_mem_alloc(rxlen+1);//多分配3字节,分配如下rbuf[0]=rxlen;//一字节存放数据长度HalUARTRead(SPI_MGR_DEFAULT_PORT,rbuf+1,rxlen);//读接收缓冲区数据到内存databuf+3if(!rxlen)osal_mem_free(rbuf);//释放内存osal_set_event(SampleApp_TaskID,UART_RX_CB_EVT);}2、处理事件UART_RX_CB_EVT当接收到来自串口的信息后,在串口回调函数的最后触发了事件UART_RX_CB_EVT,而该事件的任务ID为SampleApp_TaskID,即应用层任务ID,所以会被SampleApp工程应用层的事件处理函数SampleApp_ProcessEvent()处理,具体程序如下。程序代码uint16SampleApp_ProcessEvent(uint8task_id,uint16events){……if(events&UART_RX_CB_EVT)//串口有数据需要处理{SampleApp_SPI_SendData(rbuf,rxlen+1);//调用处理函数,将信息发送出去return(events^UART_RX_CB_EVT);}……}3、数据发送函数SampleApp_SPI_SendData()在处理事件UART_RX_CB_EVT时,协议栈调用了函数SampleApp_SPI_SendData()将串口数据发送到空中,具体代码如下。程序代码voidSampleApp_SPI_SendData(uint8*buf,uint8len){if(devStartMode==MODE_HARD)//如果启动的时候是协调器,则用广播{SampleApp_SPI_SendData_DstAddr.addrMode=(afAddrMode_t)AddrBroadcast;6SampleApp_SPI_SendData_DstAddr.endPoint=SAMPLEAPP_ENDPOINT;SampleApp_SPI_SendData_DstAddr.addr.shortAddr=0xFFFF;}else//其它设备类型则用单播{SampleApp_SPI_SendData_DstAddr.addrMode=(afAddrMode_t)Addr16Bit;SampleApp_SPI_SendData_DstAddr.endPoint=SAMPLEAPP_ENDPOINT;SampleApp_SPI_SendData_DstAddr.addr.shortAddr=0x0000;}if(AF_DataRequest(&SampleApp_SPI_SendData_DstAddr,(endPointDesc_t*)&SampleApp_epDesc,SAMPLEAPP_FLASH_CLUSTERID,len,buf,&SampleApp_TransID,0,AF_DEFAULT_RADIUS)==afStatus_SUCCESS){osal_mem_free(rbuf);//必须释放内存,不然造成溢出!}else{osal_mem_free(rbuf);//必须释放内存,不然造成溢出!}}在函数SampleApp_SPI_SendData()中根据设备的类型确定了地址为广播地址还是单播地址,因为我们现在梳理的是协调器到路由器的数据流程,所示devStartMode==MODE_HARD,即将地址设置为广播地址,串口数据被以广播的形式发送到网络中的所有设备。4、数据的接收当协调器的串口接收到数据后将信息以广播的形式发送到网络中所有设备,网络中的路由器接收到来自空中的信息时会触发事件AF_INCOMING_MSG_CMD,具体程序如下。程序代码uint16SampleApp_ProcessEvent(uint8task_id,uint16events){if(events&SYS_EVENT_MSG)//判断任务(一个任务可以有多个事件){while(MSGpkt)//对比事件{switch(MSGpkt-hdr.event){caseAF_INCOMING_MSG_CMD:SampleApp_MessageMSGCB(MSGpkt);break;7……}当触发事件AF_INCOMING_MSG_CMD时,协议中中调用
本文标题:ZigBee简易串口透传
链接地址:https://www.777doc.com/doc-5315990 .html