1. 程式人生 > >串列埠(流資料)協議封裝,拆包解析

串列埠(流資料)協議封裝,拆包解析



功能:
對資料進行封包,加入校驗,簡單加密


2.主要解析及返回資料

使用說明:
1.主函式呼叫初始化函式wifi_buff_init()
2.串列埠中斷呼叫add_message_queue()
3.主函式迴圈處理analyze_queue()


解釋說明:
此協議固定協議長度為12
加密碼0x03f7
4個幀頭 48 45 53 5a
校驗2個位元組
型別2個位元組
可以自定義各種資料型別
資料長度2個位元組
表示12位元組後的使用者資料長度
版本2個位元組
自定義預留引數
(都是低位元組在前)

這些都是預留開發用,實際中可以不用

基本資料包: 48 45 53 5a 31 05 00 00 00 00 00 00

效果:


wifi_data_tran.h

#ifndef _WIFI_DATA_TRAN
#define _WIFI_DATA_TRAN

/*************************************************
com:未知科技

作者:何少

編寫時間:2017-10-27
	
	1.新增wifi_data_tran檔案

	功能:
					對資料進行封包,加入校驗,簡單加密
			
			
	2.主要解析及返回資料		

	使用說明:
						1.主函式呼叫初始化函式wifi_buff_init()
						2.串列埠中斷呼叫add_message_queue()
						3.主函式迴圈處理analyze_queue()
						
						
	解釋說明:
						此協議固定協議長度為12
						加密碼0x03f7
						4個幀頭 48 45 53 5a
						校驗2個位元組
						型別2個位元組
						資料長度2個位元組
						版本2個位元組
						
						(都是低位元組在前)
						
						這些都是預留開發用,實際中可以不用
						
						基本資料包:	48 45 53 5a 31 05 00 00 00 00 00 00
						

**************************************************/


	

#define _PROTOCOL_HEAD           12 		                                           //固定協議頭長度
#define	USER_DATA								30																							//使用者資料長度
#define HANDLE_DATA							20
#define RX_TX_LEN								20																							//接收與傳送資料長度

extern unsigned char volatile wifi_queue_buff[_PROTOCOL_HEAD + USER_DATA];  //資料包
extern unsigned char wifi_queue_buf_len;

extern volatile unsigned char *queue_out;																	//出隊指標
extern  unsigned short queue_all_len;                             //當前佇列長度



extern unsigned char wifi_rx_buff[_PROTOCOL_HEAD+RX_TX_LEN];								//接收到的正確資料包
extern unsigned char wifi_tx_buff[_PROTOCOL_HEAD+RX_TX_LEN];								//傳送的資料包
extern unsigned char handle_buff[HANDLE_DATA];														//接收到的資料
extern unsigned char wifi_rx_buff_len;																		//接收的資料包長度	
extern unsigned char wifi_tx_buff_len; 																		//傳送資料包長度

extern unsigned char wifiwork_state;   																	//模組工作狀態






/*****************************************************************************
函式名稱 : wifi_buff_init
功能描述 : wifi所有資料初始化
輸入引數 :
返回引數 :
*****************************************************************************/
void wifi_buff_init(void);

/*****************************************************************************
函式名稱 : analyze_queue
功能描述 : 分解佇列
輸入引數 :
返回引數 :
*****************************************************************************/
void analyze_queue(void);

/*****************************************************************************
函式名稱 : add_message_queue
功能描述 : 新增資料到資料包
輸入引數 :
返回引數 :
*****************************************************************************/
void add_message_queue(unsigned char value);
/*****************************************************************************
函式名稱 : get_queue_data
功能描述 : 新增資料到資料包
輸入引數 :
返回引數 :
*****************************************************************************/
unsigned char get_queue_data(void);

/*****************************************************************************
函式名稱 : get_check_sum
功能描述 : 計算校驗和
輸入引數 : pack:資料來源指標
           pack_len:計算校驗和長度
返回引數 : 校驗和
*****************************************************************************/
unsigned short check_sum(unsigned char *pack, unsigned short pack_len);

/*****************************************************************************
函式名稱 : analyze_message_queue
功能描述 : 分析資料包
輸入引數 :
返回引數 :
*****************************************************************************/
void analyze_message_queue(unsigned char len);



/*****************************************************************************
函式名稱 : handle_set_
功能描述 : 處理設定指令
輸入引數 :	
返回引數 :
*****************************************************************************/
void handle_set(unsigned char len);

/*****************************************************************************
函式名稱 : handle_led
功能描述 : 事件處理
輸入引數 :	 函式名,處理引數
返回引數 :
*****************************************************************************/
void handle_led(void (*fun)(),unsigned char n);
/*****************************************************************************
函式名稱 : set_tx_data
功能描述 : 設定傳送資料
輸入引數 :	 要傳送的資料
返回引數 :
*****************************************************************************/
void set_tx_data(unsigned char buf[],unsigned short len);
/*****************************************************************************
函式名稱 : take_data
功能描述 : 提取接收到的資料
輸入引數 :
返回引數 :
*****************************************************************************/
void take_data(void);



/*****************************************************************************
函式名稱 : wifi_uart_write_data
功能描述 : 向wifi uart寫入連續資料
輸入引數 : in:傳送快取指標
           len:資料傳送長度
返回引數 : 無
*****************************************************************************/
 void _wifi_uart_write_data(unsigned char *in, unsigned short len);

/*****************************************************************************
函式名稱 : mymemcpy
功能描述 : 記憶體拷貝
輸入引數 : dest:目標地址
           src:源地址
           count:資料拷貝數量
返回引數 : src:資料處理完後的源地址
*****************************************************************************/
void *my_memcpy(void *dest, const void *src, unsigned short count);  

#endif


wifi_data_tran.c
/*************************************************
com:未知科技

作者:何少

編寫時間:2017-10-27
	
	1.新增wifi_data_tran檔案

		功能:
					對資料進行封包,加入校驗,簡單加密
			
			
	2.主要解析及返回資料		
	
	使用說明:
						1.主函式呼叫初始化函式wifi_buff_init()
						2.串列埠中斷呼叫add_message_queue()
						3.主函式迴圈處理analyze_queue()
						
						
	解釋說明:
						此協議固定協議長度為12
						加密碼0x03f7
						4個幀頭 48 45 53 5a
						校驗2個位元組
						型別2個位元組
											可以自定義各種資料型別
						資料長度2個位元組
											表示12位元組後的使用者資料長度
						版本2個位元組
											自定義預留引數
						(都是低位元組在前)
						
						這些都是預留開發用,實際中可以不用
						
						基本資料包:	48 45 53 5a 31 05 00 00 00 00 00 00

**************************************************/

#include "wifi_data_tran.h"
#include "sys.h"
#include "stdio.h"
/*******************************************************/

 unsigned char volatile wifi_queue_buff[_PROTOCOL_HEAD + USER_DATA];  //資料包
 unsigned char wifi_queue_buf_len;	
 unsigned short queue_all_len;
 unsigned char wifi_rx_buff[_PROTOCOL_HEAD+RX_TX_LEN];								//接收到的正確資料包
 unsigned char wifi_tx_buff[_PROTOCOL_HEAD+RX_TX_LEN];								//傳送的資料包
 unsigned char handle_buff[HANDLE_DATA];
 unsigned char wifi_rx_buff_len;
 unsigned char wifi_tx_buff_len;
 
 volatile unsigned char *queue_out;																	//出隊指標
 unsigned char wifiwork_state;   																	//wifi模組工作狀態
 
 
/*****************************************************************************
函式名稱 : wifi_buff_init
功能描述 : wifi所有資料初始化
輸入引數 :
返回引數 :
*****************************************************************************/
void wifi_buff_init()
{
	queue_out=wifi_queue_buff;	//初始化出隊指標
	queue_all_len=0;						//隊列當前長度
		
	wifi_rx_buff_len=0;					//接收命令快取
	wifi_tx_buff_len=0;					//傳送命令快取
}

/*****************************************************************************
函式名稱 : get_queue_data
功能描述 : 新增資料到資料包
輸入引數 :
返回引數 :
*****************************************************************************/
unsigned char get_queue_data(void)
{
	 unsigned char value;
  
  if(queue_all_len > 0)
  {
    //有資料
    if(queue_out >= (unsigned char *)(wifi_queue_buff + sizeof(wifi_queue_buff)))		//出隊指標要小於資料佇列總長度
    {
      //資料已經到末尾
      queue_out = (unsigned char *)(wifi_queue_buff);		//重新指向陣列頭
    }
    
    value = *queue_out ++;   		//出隊
    queue_all_len --;						//佇列資料-1
  }
  
  return value;
	
	
}
/*****************************************************************************
函式名稱 : add_message_queue
功能描述 : 新增資料到資料包
輸入引數 :	 unsigned char value
返回引數 :
*****************************************************************************/
void add_message_queue(unsigned char value)
{
			if(wifi_queue_buf_len<(_PROTOCOL_HEAD + USER_DATA))	//隊列當前資料長度小於佇列快取總長度
			{
				wifi_queue_buff[wifi_queue_buf_len++]=value;		//新增到佇列
				
				queue_all_len++;			//
			}
			else
			{
				
				wifi_queue_buf_len=0;														//佇列快取索引重新開始
				wifi_queue_buff[wifi_queue_buf_len++]=value;		
				queue_all_len++;																//佇列長度
			
			}
		
	
}
/*****************************************************************************
函式名稱 : analyze_queue
功能描述 : 分解佇列,在主函式裡面迴圈
輸入引數 :
返回引數 :
*****************************************************************************/
void analyze_queue(void)
{
		short data_len=0;				//索引
		short rx_value_len=0;		//接收包長度	
		int i;
	 while((wifi_rx_buff_len < sizeof(wifi_queue_buff)) && queue_all_len > 0)		//接收包長度小於佇列快取長度,佇列資料要大於0
  {
    u8 r=wifi_rx_buff[wifi_rx_buff_len ++] = get_queue_data();
		//printf("%c",r);
  }
	
	if(wifi_rx_buff_len<12) return;				//資料包小於12(最短資料包)
	
	 while((wifi_rx_buff_len - data_len) >= 12)			
  {
    if(wifi_rx_buff[data_len] != 0x48)
    {
      data_len ++;
      continue;
    }
		printf("\r\n H ok\r\n");
		if(wifi_rx_buff[data_len + 1] != 0x45)
    {
      data_len ++;
      continue;
    }
		printf("\r\n E ok\r\n");
		if(wifi_rx_buff[data_len + 2] != 0x53)
    {
      data_len += 2;
      continue;
    }
		printf("\r\n S ok\r\n");
		if(wifi_rx_buff[data_len + 3] != 0x5a)
    {
      data_len += 3;
      continue;
    }     
    printf("\r\n 5a ok\r\n");

    rx_value_len = wifi_rx_buff[data_len + 9] * 0x100 + wifi_rx_buff[data_len + 8] + 12;	//使用者資料+標準資料(幀頭資料)
    if(rx_value_len > sizeof(wifi_rx_buff))
    {
      data_len += 4;
      continue;
    }
     printf("\r\n 長度 ok\r\n");
    if((wifi_rx_buff_len - data_len) < rx_value_len)
    {
      break;
    }
		printf("\r\n 資料長度:%d ok\r\n",rx_value_len);
		 //資料接收完成
    if(check_sum((unsigned char *)wifi_rx_buff + data_len,rx_value_len)
			!= wifi_rx_buff[data_len + 5] * 0x100 + wifi_rx_buff[data_len + 4])
    {
      //校驗出錯
      data_len += 4;
      continue;
    }
		 printf("\r\n 校驗 ok\r\n");
#if 1//1為test
//打印出正確的接收到的協議
		printf("recv:%d:",data_len);
		for(i=0; i<rx_value_len; i++)
		{
			printf("%x ",wifi_rx_buff[data_len + i]);
		}
		printf("\r\n");
#endif
		
 
		analyze_message_queue(rx_value_len);	//處理資料包
		
    data_len += rx_value_len;		
		
	}
	 wifi_rx_buff_len -= data_len;
  if(wifi_rx_buff_len > 0 && data_len>0)
  {
    my_memcpy(wifi_rx_buff,wifi_rx_buff + data_len,wifi_rx_buff_len);
  }
	
}

/*****************************************************************************
函式名稱 : get_check_sum
功能描述 : 計算校驗和
輸入引數 : pack:資料來源指標
           pack_len:計算校驗和長度
返回引數 : 校驗和
*****************************************************************************/
unsigned short check_sum(unsigned char *pack, unsigned short pack_len)
{
  unsigned short i;
  unsigned short check_sum = 0;
  
  for(i = 0; i < pack_len; i ++)
  {
		if(i==4 || i==5) 
		{
			pack ++;
			continue;					// 避開校驗位;
		}
		
    check_sum += *pack++;
  }
  
  return (check_sum + 0x03f7);
}

/*****************************************************************************
函式名稱 : analyze_message_queue
功能描述 : 分析資料包
輸入引數 :
返回引數 :
*****************************************************************************/
void analyze_message_queue(unsigned char len)
{
	
	switch(wifi_rx_buff[6]+wifi_rx_buff[7]*0x100)
	{

	}
}



/*****************************************************************************
函式名稱 : handle_set_
功能描述 : 處理指令
輸入引數 :
返回引數 :
*****************************************************************************/
void handle_set(unsigned char len)
{

		//unsigned char buf[]={0x01,0x02,0x03,0x04,0x05};				//要傳送的資料
	
		take_data();										//提取資料
	
	


}
/*****************************************************************************
函式名稱 : handle_led
功能描述 : 事件處理
輸入引數 :
返回引數 :
*****************************************************************************/
void handle_led(void (*fun)(),unsigned char n)
{
		fun(n);
}

/*****************************************************************************
函式名稱 : set_tx_data
功能描述 : 設定傳送資料
輸入引數 :	 要傳送的資料
返回引數 :
*****************************************************************************/
void set_tx_data(unsigned char buf[],unsigned short len)
{
	unsigned char i;
	unsigned short buf_len = len;																										//傳送資料的長度
	unsigned short buf_sum;																													//傳送資料的總和

	
		char state_re[]={0x48,0x45,0x53,0x5A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};			//標準返回資料頭
	
	wifi_tx_buff_len=12;																
	
	for(i=0;i<wifi_tx_buff_len;i++)								//資料頭
		wifi_tx_buff[i]=state_re[i];
	
	for(i=0;i<buf_len;i++)												//所有資料和
		buf_sum+=buf[i];
	
		buf_sum+=0x0531+buf_len;					//協議頭+校驗和+資料長度
		
	wifi_tx_buff[4]=buf_sum&0x00ff;								//校驗和
	wifi_tx_buff[5]=buf_sum>>8;
	
	wifi_tx_buff[8]=buf_len&0x00ff;								//資料和
	wifi_tx_buff[9]=buf_len>>8;
	
	for(i=0;i<buf_len;i++)												//所有資料
	wifi_tx_buff[wifi_tx_buff_len+i]=buf[i];
	
	_wifi_uart_write_data((unsigned char *)wifi_tx_buff, wifi_tx_buff_len+buf_len);	//指令傳送
	
	
}
/*****************************************************************************
函式名稱 : take_data
功能描述 : 提取接收到資料
輸入引數 :
返回引數 :
*****************************************************************************/
void take_data(void)
{
		unsigned short data_len	=	wifi_rx_buff[8]+wifi_rx_buff[9]*0x100;					//接收到資料長度
		unsigned char i;
		
		for(i=0;i<data_len;i++)														//提取出資料
		handle_buff[i]=wifi_rx_buff[12+i];
		

}

/*****************************************************************************
函式名稱 : wifi_uart_write_data
功能描述 : 向wifi uart寫入連續資料
輸入引數 : in:傳送快取指標
           len:資料傳送長度
返回引數 : 無
*****************************************************************************/
 void _wifi_uart_write_data(unsigned char *in, unsigned short len)
{
  if((NULL == in) || (0 == len))
  {
    return;
  }
  printf("send:");
  while(len --)
  {
		printf("%c",*in);
   
    in ++;
  }
	printf("\r\n");
}

/*****************************************************************************
函式名稱 : mymemcpy
功能描述 : 記憶體拷貝
輸入引數 : dest:目標地址
           src:源地址
           count:資料拷貝數量
返回引數 : src:資料處理完後的源地址
*****************************************************************************/
void *my_memcpy(void *dest, const void *src, unsigned short count)  
{  
  unsigned char *pdest = (unsigned char *)dest;  
  const unsigned char *psrc  = (const unsigned char *)src;  
  unsigned short i;
  
  if(dest == NULL || src == NULL)
  { 
    return NULL;
  }
  
	/* 此判斷是保證未被轉移的源資料不會被轉移操作所汙染; */
  if((pdest <= psrc) || (pdest > psrc + count))
  {  
    for(i = 0; i < count; i ++)
    {  
      pdest[i] = psrc[i];  
    }  
  }
  else
  {
    for(i = count; i > 0; i --)
    {  
      pdest[i - 1] = psrc[i - 1];  
    }  
  }  
  
  return dest;  
}