在单片机串口通信中,接收数据的处理是关键环节,常用的数据处理方法有以下几种,可根据具体场景选择或组合使用:
原理:在主循环中不断检查串口接收标志位(如UART_RX_FLAG)或缓冲区状态。
特点:
实现简单,占用资源少。
实时性差,可能丢失高速数据。
示例代码:
while (1) {
if (UART_DataAvailable()) {
char data = UART_ReadByte();
// 处理数据
} }原理:通过硬件中断触发接收,每收到一个字节即进入中断服务程序(ISR)。
特点:
实时性高,适合高速数据。
需避免在ISR中执行耗时操作。
示例代码:
void UART_ISR() {
if (RX_INTERRUPT_FLAG) {
static uint8_t buffer[64];
static int index = 0;
buffer[index++] = UART_RX_REG;
if (index >= 64) index = 0; // 防止溢出
} }原理:在中断中接收数据并存入环形缓冲区,主程序从缓冲区读取处理。
优势:
解决数据覆盖问题,平衡中断与主程序的速率差异。
适合数据流不稳定的场景。
实现要点:
定义头尾指针(或索引)。
注意缓冲区满/空的判断条件(通常留一字节空位)。
示例结构:
#define BUF_SIZE 128 typedef struct {
uint8_t buffer[BUF_SIZE];
volatile uint16_t head; // 写入位置
volatile uint16_t tail; // 读取位置 } RingBuffer;原理:通过自定义协议(如头尾标志、长度、校验等)提取有效数据帧。
常见协议:
固定长度帧:如每帧5字节,直接按长度截取。
可变长度帧:通过帧头(如0xAA)、长度字段、校验(如CRC)组合。
特殊结束符:如以\r\n结尾的字符串(AT指令常用)。
示例处理流程:
搜索帧头(如0xAA)。
读取长度字段。
校验数据完整性(和校验、CRC等)。
解析有效载荷。
原理:利用DMA自动搬运串口数据到内存,配合串口空闲中断(IDLE)判定一帧结束。
优势:
极大降低CPU负载,适合高速大数据量(如GPS模块、Modbus)。
空闲中断可识别帧间隔(如串口停顿时间)。
示例(STM32 HAL库):
// 启动DMA接收 HAL_UART_Receive_DMA(&huart1, buffer, MAX_LEN); // 空闲中断回调 void HAL_UART_IdleCallback(UART_HandleTypeDef *huart) {
if (huart == &huart1) {
uint32_t len = MAX_LEN - __HAL_DMA_GET_COUNTER(huart->hdmarx);
process_frame(buffer, len); // 处理数据
HAL_UART_Receive_DMA(huart, buffer, MAX_LEN); // 重启接收
} }原理:根据接收进度切换状态(如等待头、读长度、读数据、校验等)。
适用场景:复杂协议(如自定义工业协议、JSON片段)。
示例状态机:
typedef enum { STATE_HEADER, STATE_LEN, STATE_DATA, STATE_CRC } ParserState;
ParserState state = STATE_HEADER; while (UART_DataAvailable()) {
uint8_t byte = UART_ReadByte();
switch (state) {
case STATE_HEADER:
if (byte == 0xAA) state = STATE_LEN;
break;
case STATE_LEN:
data_len = byte;
state = STATE_DATA;
break;
// ...其他状态处理
} }原理:结合定时器判断帧接收超时,避免半帧残留。
实现方式:
在中断或轮询中重置超时计时器。
超时后触发帧处理并清空缓冲区。
示例:
void TIM_ISR() {
if (timeout_cnt > 0 && --timeout_cnt == 0) {
process_frame(buffer, current_len); // 超时处理
current_len = 0;
} }低速简单场景:轮询/中断+环形缓冲区。
高速稳定数据:DMA+空闲中断。
复杂协议:状态机+超时管理。
资源紧张MCU:避免动态内存,使用静态缓冲区。
免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。