串口数据带帧头帧尾数据接收整体思路:
1.串口中断函数接收到数据后判断每一个字节的值;
2.如果串口数据是帧头数据,则帧头帧尾计次++;
3.帧头帧尾计次值判断,如果帧头值、计次值正确,则将数据转移;
4.帧尾判断,如果正确,接收成功标志位置1;
5.接收成功标志位置1后,数据解析;
6.解析完成后,标志位清0。
keil5配置
.h文件
#ifndef __MY_UART_H_
#define __MY_UART_H_
#include "stdint.h"
#include "usart.h"
#include "string.h"
#define BUF_SIZE 64
#define Head1 0xAA
#define Head2 0xBB
#define Head3 0xCC
#define End1 0xDD
#define End2 0xEE
#define End3 0xFF
typedef struct{
uint8_t Rx_data;//数据接收
uint8_t Rx_buf[BUF_SIZE];//字节转移缓存区
uint8_t Rx_flag;//接收到数据标志位
uint8_t Rx_succeed;//接收到正确的帧头、帧尾数据
uint8_t Rx_Index;//接收索引
uint8_t Rx_count;//帧头帧尾计次判断
uint16_t Data_CRC;//数据校验
uint8_t data_error;//数据解析错误
} Rx_flag;
void Data_dispose(void);
#endif
.c文件
#include "my_uart.h"
Rx_flag Rx_State = {0};
/*
CRC表
*/
/********************
函数名:串口初始化
********************/
void UART_Init(void)
{
HAL_UART_Receive_IT(&huart2,&Rx_State.Rx_data,sizeof(Rx_State.Rx_data));
}
/********
函数名:串口中断回调函数
UART_HandleTypeDef *huart:传入的串口句柄指针
********/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart == &huart2)
{
HAL_UART_Receive_IT(&huart2,&Rx_State.Rx_data,sizeof(Rx_State.Rx_data));
switch(Rx_State.Rx_flag)//数据判断
{
case 0:
if(Rx_State.Rx_data == Head1)
{
Rx_State.Rx_count++;//帧头计次
Rx_State.Rx_flag = 0;
}
if(Rx_State.Rx_data == Head2 && Rx_State.Rx_count == 1)
{
Rx_State.Rx_count++;//帧头帧尾计次
Rx_State.Rx_flag = 0;
}
if(Rx_State.Rx_data == Head3 && Rx_State.Rx_count == 2)
{
Rx_State.Rx_count++;//帧头帧尾计次
Rx_State.Rx_flag = 1;//帧头判断完成,准备将字节转移至缓存区
}
break;
case 1:
//数据传入接收缓存区内
Rx_State.Rx_buf[Rx_State.Rx_Index++] = Rx_State.Rx_data;
if(Rx_State.Rx_data == End1 && Rx_State.Rx_count == 3)
{
Rx_State.Rx_count++;//帧头帧尾计次
Rx_State.Rx_flag = 1;
}
if(Rx_State.Rx_data == End2 && Rx_State.Rx_count == 4)
{
Rx_State.Rx_count++;//帧头帧尾计次
Rx_State.Rx_flag = 2;
}
break;
case 2:
//在此可增加CRC校验
if(Rx_State.Rx_data == End3 && Rx_State.Rx_count == 5)
{
Rx_State.Rx_count++;//帧头帧尾计次
Rx_State.Rx_flag = 3;
Rx_State.Rx_succeed = 1;//数据接收成功标志位
}
break;
default:
Rx_State.Rx_flag = 0;
break;
}
}
}
/****************
数据解析函数
****************/
void Data_dispose(void)
{
if(Rx_State.Rx_succeed == 1)//数据接收成功标志位
{
Rx_State.Data_CRC = VerifyCRC16(&Rx_State.Rx_buf[0],Rx_State.Rx_Index - 3);//数据校验
//数据解析
if(Rx_State.Data_CRC == (Rx_State.Rx_buf[Rx_State.Rx_Index - 3] >> 8) + Rx_State.Rx_buf[Rx_State.Rx_Index - 4])
{
}
else
{
Rx_State.data_error = 1;//数据解析错误标志位
}
/*数据标志位、索引、计次、缓存区清0,为下一次数据的到来做准备*/
memset(&Rx_State,0,sizeof(Rx_State));//缓存区清0
}
}