串口(流数据)协议封装,拆包解析

8 篇文章 2 订阅
8 篇文章 0 订阅



功能:
对数据进行封包,加入校验,简单加密


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;  
}


  • 5
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是一个简单的 Qt 串口 RS232 协议数据解析的示例代码: ```cpp #include <QtSerialPort/QSerialPort> #include <QCoreApplication> #include <QDebug> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QSerialPort serialPort; serialPort.setPortName("COM1"); // 串口名称 serialPort.setBaudRate(QSerialPort::Baud115200); // 波特率 serialPort.setDataBits(QSerialPort::Data8); // 数据位 serialPort.setParity(QSerialPort::NoParity); // 校验位 serialPort.setStopBits(QSerialPort::OneStop); // 停止位 if (!serialPort.open(QIODevice::ReadWrite)) { qDebug() << "Failed to open serial port."; return 1; } QByteArray buffer; // 数据缓存 while (true) { if (serialPort.waitForReadyRead(100)) { buffer.append(serialPort.readAll()); // 读取串口数据 } // 查找数据头和数据尾 int headIndex = buffer.indexOf(0xAA); int tailIndex = buffer.indexOf(0x55); if (headIndex != -1 && tailIndex != -1 && tailIndex > headIndex) { QByteArray data = buffer.mid(headIndex, tailIndex - headIndex + 1); // 提取有效数据 buffer = buffer.mid(tailIndex + 1); // 更新数据缓存 // 解析数据 if (data.size() == 10 && data[1] == 0x01 && data[9] == 0x0D) { int value = (data[2] << 8) + data[3]; qDebug() << "Received data:" << value; } } } return a.exec(); } ``` 该示例中,我们使用 `QSerialPort` 类来打开一个串口,然后不断从串口读取数据。我们假设协议中的数据头为 `0xAA`,数据尾为 `0x55`,有效数据长度为 10 字节,其中第 2 个字节为 0x01,第 9 个字节为 0x0D。如果收到符合协议数据,我们将提取其中的数值并输出到控制台中。 请注意,该示例中的代码仅用于演示如何进行串口数据解析,并未考虑数据丢失、错误校验等问题,实际使用时需要按照具体情况进行修改和完善。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值