【笔记】接收不定长串口数据的方式(附代码)

描述


 

在不定长串口数据接收方面,有多种方式可供选择。以下是几种常见的方法:1. 基于帧头帧尾:通过在数据帧的开头和结尾添加特定的帧头和帧尾标识来确定数据的起始和结束。在接收端,通过检测帧头和帧尾来截取完整的数据帧。这种方法需要约定好帧头和帧尾的标识,并在接收端进行相应的处理。例如,可以使用特定的字符或字节序列作为帧头和帧尾标识。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

#define FRAME_HEAD 0xAA#define FRAME_TAIL 0x55
uint8_t rxBuffer[100];uint8_t rxIndex = 0;uint8_t frameStarted = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ if (huart->Instance == USART1) { if (rxData == FRAME_HEAD) { frameStarted = 1; rxIndex = 0; } else if (rxData == FRAME_TAIL && frameStarted) { // 完整的数据帧接收完成,进行处理 // rxBuffer 中保存了完整的数据帧 // 可以进行后续的数据解析和处理操作 frameStarted = 0; } else if (frameStarted) { rxBuffer[rxIndex++] = rxData; }
HAL_UART_Receive_IT(&huart1, &rxData, 1); }}

2. 基于定长数据:如果数据包的长度是固定的,可以通过设定一个固定的字节数来接收数据。在达到指定的字节数后,即可认为接收到了完整的数据。这种方式适用于数据包长度固定且已知的情况。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

#define DATA_LENGTH 10
uint8_t rxBuffer[DATA_LENGTH];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ if (huart->Instance == USART1) { // 完整的数据包接收完成,进行处理 // rxBuffer 中保存了完整的数据包 // 可以进行后续的数据解析和处理操作
HAL_UART_Receive_IT(&huart1, rxBuffer, DATA_LENGTH); }}

3. 基于超时机制:在串口接收时,可以设置一个超时时间,如果在规定的时间内没有接收到数据,即认为当前数据接收结束。通过不断检查接收状态和计时器,可以实现超时机制。这种方式适用于数据包长度不确定且无法使用帧头帧尾方式的情况。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

#define TIMEOUT_MS 100
uint8_t rxBuffer[100];uint8_t rxIndex = 0;uint32_t startTime = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ if (huart->Instance == USART1) { if (rxIndex == 0) { startTime = HAL_GetTick(); }
rxBuffer[rxIndex++] = rxData;
if (rxIndex >= 2 && HAL_GetTick() - startTime >= TIMEOUT_MS) { // 接收超时,数据接收结束 // 进行数据处理操作 rxIndex = 0; }
HAL_UART_Receive_IT(&huart1, &rxData, 1); }}

4. 基于特定字符:可以通过在数据中插入特定的字符来表示数据的开始和结束。接收端可以根据特定的字符来判断数据的起始和结束。例如,可以使用换行符('\n')或回车符('\r')作为数据的起始和结束标识。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

#define START_CHAR '\n'#define END_CHAR '\r'
uint8_t rxBuffer[100];uint8_t rxIndex = 0;uint8_t frameStarted = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ if (huart->Instance == USART1) { if (rxData == START_CHAR) { frameStarted = 1; rxIndex = 0; } else if (rxData == END_CHAR && frameStarted) { // 完整的数据接收完成,进行处理 // rxBuffer 中保存了完整的数据 // 可以进行后续的数据解析和处理操作 frameStarted = 0; } else if (frameStarted) { rxBuffer[rxIndex++] = rxData; }
HAL_UART_Receive_IT(&huart1, &rxData, 1); }}

5. 基于计数:可以在接收端设置一个计数器,根据接收到的数据逐步增加计数器的值。当达到指定的计数值时,即认为接收到了完整的数据。这种方式适用于在接收到固定数量的数据后即认为数据接收完成的情况。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

#define FRAME_LENGTH 10
uint8_t rxBuffer[FRAME_LENGTH];uint8_t rxIndex = 0;uint8_t frameStarted = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ if (huart->Instance == USART1) { if (frameStarted) { rxBuffer[rxIndex++] = rxData; if (rxIndex == FRAME_LENGTH) { // 完整的数据接收完成,进行处理 // rxBuffer 中保存了完整的数据 // 可以进行后续的数据解析和处理操作 frameStarted = 0; } } else { // 如果接收到起始字符,则开始计数 if (rxData == START_CHAR) { frameStarted = 1; rxIndex = 0; } }
HAL_UART_Receive_IT(&huart1, &rxData, 1); }}

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分