-
一.串口收发HEX数据包
-
1-1发送HEX数据包(固定包长)
包头包尾和数据载荷重复的问题,传输的数据本身是FF和FE,可能引起误判
解决:限制载荷数据的范围,限幅(例如只发送0~100)
如果无法避免数据与包头包尾重复,则尽量使用固定长度的数据包
增加包头包尾的数量,尽量是其呈现出载荷数据出现不了的状态
extern uint8_t Serial_TxPacket[]; //声明外部可调用
uint8_t Serial_TxPacket[4];
void Serial_SendPacket(void)
{
Serial_SendByte(0xFF);
Serial_SendArray(Serial_TxPacket, 4); //发送四个字节
Serial_SendByte(0xFE);
}
主函数使用
外部设备现象
1-2接受HEX数据包
中断状态机流程图
uint8_t Serial_RxPacket[4];
uint8_t Serial_RxFlag;
void USART1_IRQHandler(void)
{
static uint8_t RxState = 0; //静态变量 只能在本函数使用 函数进入只会初始化一次
static uint8_t pRxPacket = 0; //记录接受的数量
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
uint8_t RxData = USART_ReceiveData(USART1);
if (RxState == 0) //等待包头
{
if (RxData == 0xFF) //包头
{
RxState = 1;
pRxPacket = 0;
}
}
else if (RxState == 1) //接收数据
{
Serial_RxPacket[pRxPacket] = RxData;
pRxPacket ++;
if (pRxPacket >= 4) //接受四个载荷数据
{
RxState = 2;
}
}
else if (RxState == 2) //等待包尾
{
if (RxData == 0xFE) //包尾RXData==0xFE
{
RxState = 0;
Serial_RxFlag = 1;
}
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
使用
if (Serial_GetRxFlag() == 1)
{
OLED_ShowHexNum(4, 1, Serial_RxPacket[0], 2);
OLED_ShowHexNum(4, 4, Serial_RxPacket[1], 2);
OLED_ShowHexNum(4, 7, Serial_RxPacket[2], 2);
OLED_ShowHexNum(4, 10, Serial_RxPacket[3], 2);
}
使用现象:
二.串口接受文本数据包
2-1发送文本数据包
中断状态机流程图
接受缓存区
char Serial_RxPacket[100]; //"@MSG\r\n" 接收缓存区
void USART1_IRQHandler(void)
{
static uint8_t RxState = 0;
static uint8_t pRxPacket = 0;
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
uint8_t RxData = USART_ReceiveData(USART1);
if (RxState == 0)
{
if (RxData == '@' && Serial_RxFlag == 0)
{
RxState = 1;
pRxPacket = 0;
}
}
else if (RxState == 1)
{
if (RxData == '\r')
{
RxState = 2;
}
else //接受数据
{
Serial_RxPacket[pRxPacket] = RxData;
pRxPacket ++;
}
}
else if (RxState == 2)
{
if (RxData == '\n')
{
RxState = 0;
Serial_RxPacket[pRxPacket] = '\0'; //添加结束标志位
Serial_RxFlag = 1;
}
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
使用代码
现象 (发送区输入@ABC“换行”)
#include "string.h"
if (strcmp(Serial_RxPacket, "LED_ON") == 0) //strcmp 判断字符串是否相等
{
LED1_ON();
Serial_SendString("LED_ON_OK\r\n");
OLED_ShowString(2, 1, " ");
OLED_ShowString(2, 1, "LED_ON_OK");
}
else if (strcmp(Serial_RxPacket, "LED_OFF") == 0)
{
LED1_OFF();
Serial_SendString("LED_OFF_OK\r\n");
OLED_ShowString(2, 1, " ");
OLED_ShowString(2, 1, "LED_OFF_OK");
}
else
{
Serial_SendString("ERROR_COMMAND\r\n");
OLED_ShowString(2, 1, " ");
OLED_ShowString(2, 1, "ERROR_COMMAND");
}
Serial_RxFlag = 0; //防止数据乱码