ZigBee组网学习笔记(六)--串口透传

程序流程:
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;imsg [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;icmd.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


接下来烧写程序到板子上面就可以了。

ZigBee组网学习笔记(六)--串口透传_第1张图片

你可能感兴趣的:(ZigBee)