程序流程: 1、 ZigBee 模块接收到从 PC机发送信息,然后无线发送出去
2、 ZigBee 模块接收到其它 ZigBee 模块发来的信息,然后发送给 PC机
workspace 目录下比较重要的两个文件夹, Zmain 和 App。 这里我们主要用到 App,这也是用户自己添加自己代码的地方。 ========================================== 初始化串口(参考协议栈串口实验)
1、
SampleApp.c
#include "MT_UART.h" //串口头文件引用
2、 SampApp.c
SampApp_Init()
SampApp_TransID() = 0;
MT_UartInit();
3、 void MT_UartInit()
uartConfig.baudRate =MT_UART_DEFAULT_BAUDRATE;
uartConfig.flowControl = MT_UART_DEFAULT_OVERFLOW;
#define MT_UART_DEFAULT_BAUDRATE HAL_UART_BR_115200 //38400
#define MT_UART_DEFAULT_OVERFLOW FALSE //TRUE
4、 用 ZTOOL,串口 0。我们可以在 option——C/C++ 的 CompilerPreprocessor 里面看到,已经默认添加 ZTOOL_P1 预编译。
5、
void SampleApp_Init( uint8 task_id )
MT_UartInit();
MT_UartRegisterTaskID(task_id);//登记任务号
至此,就可以使用 HalUARTWrite(0, "Hello,world\n", 12); //(串口, 字符, 字符个数) 发送数据了。
==========================================
1、 ZigBee 模块接收到从 PC机发送信息,然后无线发送出去
MT_UART.c
void MT_UartInit ()
#ifdefined (ZTOOL_P1) || defined (ZTOOL_P2)
uartConfig.callBackFunc =MT_UartProcessZToolData;///
#elifdefined (ZAPP_P1) || defined (ZAPP_P2)
uartConfig.callBackFunc = MT_UartProcessZAppData;
#else
uartConfig.callBackFunc = NULL;
#endif
MT_UartProcessZToolData
串口发来的数据包进行打包,校验,生成一个消息,发给处理数据包的任务。
用 ZTOOL 通过串口来沟通协议栈,那么发过来的串口数据具有以下格式:
0xFE, DataLength, CM0, CM1, Data payload, FCS
翻译:
0xFE:数据帧头
DataLength: Datapayload 的数据长度,以字节计,低字节在前;205
CM0:命令低字节;
CM1:命令高字节; (ZTOOL 软件就是通过发送一系列命令给 MT 实现和协议栈交互)
Data payload:数据帧具体的数据,这个长度是可变的,但是要和DataLength 一致;
FCS :校验和,从 DataLength 字节开始到 Data payload 最后一个字节所有字节的异或按字节操作;
这样处理太复杂。。
。
串口从 PC 机接收到信息
1、 接收 串口数据,判断起始码是否为 0xFE
2、 得到数据长度然后给数据包 pMsg 分配内存
3、 给数据包 pMsg 装数据
4、 打包成任务发给上层 OSAL 待处理
5、 释放数据包内存
void MT_UartProcessZToolData ( uint8 port, uint8 event ) 把该函数换成我们自己的串口处理函数
***************************************************
void MT_UartProcessZToolData ( uint8 port, uint8 event )
{
uint8 flag=0,i,j=0; //flag是判断有没有收到数据,j记录数据长度
uint8 buf[128]; //串口buffer最大缓冲默认是128,我们这里用128.
(void)event; // Intentionally unreferenced parameter
while (Hal_UART_RxBufLen(port)) //检测串口数据是否接收完成
{
HalUARTRead (port,&buf[j], 1); //把数据接收放到buf中
j++; //记录字符数
flag=1; //已经从串口接收到信息
}
if(flag==1) //已经从串口接收到信息
{
/* Allocate memory for the data */
//分配内存空间,为结构体内容+数据内容+1个记录长度的数据
pMsg = (mtOSALSerialData_t *)osal_msg_allocate( sizeof ( mtOSALSerialData_t )+j+1);
//事件号用原来的CMD_SERIAL_MSG
pMsg->hdr.event = CMD_SERIAL_MSG;
pMsg->msg = (uint8*)(pMsg+1); // 把数据定位到结构体数据部分
pMsg->msg [0]= j; //给上层的数据第一个是长度
for(i=0;i<j;i++) //从第二个开始记录数据
pMsg->msg [i+1]= buf[i];
osal_msg_send( App_TaskID, (byte *)pMsg ); //登记任务,发往上层
/* deallocate the msg */
osal_msg_deallocate ( (uint8 *)pMsg ); //释放内存
}
}
数据包中数据部分的格式是:datalen + data 至此,数据接收的处理函数已经完成。 *************************************************** 接下来要做的就是处理这个包的内容
在函数SampleApp_ProcessEvent里面加入 case CMD_SERIAL_MSG:
SampleApp_SerialCMD((mtOSALSerialData_t *)MSGpkt);
break;
CMD_SERIAL_MSG在 #include "MT.h" 中,因此在SampleApp.c中添加头文件#include "MT.h"
SampleApp.c
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
if ( events & SYS_EVENT_MSG )
MSGpkt(afIncomingMSGPacket_t*)osal_msg_receive( SampleApp_TaskID );
while ( MSGpkt )
switch ( MSGpkt->hdr.event )
//串口收到数据后由MT_UART层传递过来的数据,用该方法接收,编译时不定义MT相关内容
case CMD_SERIAL_MSG:
SampleApp_SerialCMD((mtOSALSerialData_t *)MSGpkt);
break;
解释:串口收到信息后,事件号 CMD_SERIAL_MSG 就会被登记,便进入case CMD_SERIAL_MSG: 执行 SampleApp_SerialCMD((mtOSALSerialData_t *)MSGpkt); 大家是不是很奇怪怎么在协议栈里找不到这个函数,当然了,我们那边只把他打包了,然后登记任务,这个包是我们自己的,想怎么处理当然由自己决定,这个函数是信息无线发送出去。 *************************************************** 自己定义该函数
void SampleApp_SerialCMD(mtOSALSerialData_t *cmdMsg)
{
uint8 i,len,*str=NULL; //len有用数据长度
str=cmdMsg->msg; //指向数据开头
len=*str; //msg里的第1个字节代表后面的数据长度
/********打印出串口接收到的数据,用于提示*********/
for(i=1;i<=len;i++)
HalUARTWrite(0,str+i,1 );
HalUARTWrite(0,"\n",1 );//换行
/*******发送出去,同无线数据传输********/
if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
SAMPLEAPP_COM_CLUSTERID,//自己定义一个
len+1, // 数据长度
str, //数据内容
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
}
else
{
// Error occurred in request to send.
}
}
别忘了函数声明:
void SampleApp_SerialCMD(mtOSALSerialData_t *cmdMsg);
*************************************************** SampleApp.h 定义 SAMPLEAPP_COM_CLUSTERID这个自己定义的 ID,用于接收方判别
//
#define SAMPLEAPP_MAX_CLUSTERS 3 //2
//
#define SAMPLEAPP_PERIODIC_CLUSTERID 1
#define SAMPLEAPP_FLASH_CLUSTERID 2
///
#define SAMPLEAPP_COM_CLUSTERID 3
///
***************************************************
2、 ZigBee 模块接收到其它 ZigBee 模块发来的信息,然后发送给 PC机
SampleApp.c
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
uint16 flashTime;
switch ( pkt->clusterId )
{
uint8 i,len;
//.....
///
case SAMPLEAPP_COM_CLUSTERID: //如果是串口透传的信息
len=pkt->cmd.Data[0];
for(i=0;i<len;i++)
HalUARTWrite(0,&pkt->cmd.Data[i+1],1);//发给PC机
HalUARTWrite(0,"\n",1); // 回车换行
break;
///
}
}
最后还要修改预编译,注释掉 MT 层的内容。这里注意,选择了协调器、路由器、或者终端 编译时 都要修改 options 。 参考如下:
ZTOOL_P1
xMT_TASK
xMT_SYS_FUNC
xMT_ZDO_FUNC
xLCD_SUPPORTED=DEBUG
接下来烧写程序到板子上面就可以了。