You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

高波特率下C语言串口read()丢字节问题排查求助

问题原因分析

1. 读取循环的错误退出逻辑

你在打开串口时使用了O_NDELAY标志,使串口处于非阻塞模式。此时read()返回0并不代表数据传输结束,仅说明当前内核缓冲区中无可用数据。你的代码在遇到read_num == 0时直接退出读取循环,导致后续延迟到达的字节被丢弃——高波特率下数据常分多批次到达,前几次读取后缓冲区暂时为空,就被误判为读取完成,实际仍有字节在传输途中。

2. 缺少发送完成的同步机制

write()返回成功仅表示数据已写入内核的串口发送缓冲区,不代表数据已全部通过硬件发送完毕。极高波特率下,发送缓冲区的数据可能还在持续传输,而读取端未等待足够时间就终止读取,导致部分字节未到达接收端就被停止。

3. 串口缓冲区大小限制(潜在因素)

默认的串口输入缓冲区可能无法应对高波特率下的突发数据流量,当数据到达速度超过读取速度时,缓冲区溢出会直接导致丢字节。

解决方法

1. 修复读取循环逻辑,添加超时机制

使用select()等待串口数据并设置合理超时,避免因单次read()返回0提前退出。修改后的读取循环示例:

int read_total = 0;
struct timeval timeout;
fd_set read_fds;

while (read_total < BUFFER_SIZE) {
    FD_ZERO(&read_fds);
    FD_SET(serial_fd2, &read_fds);
    
    // 设置100ms超时,可根据波特率调整
    timeout.tv_sec = 0;
    timeout.tv_usec = 100000;

    int select_ret = select(serial_fd2 + 1, &read_fds, NULL, NULL, &timeout);
    if (select_ret == -1) {
        perror("select error");
        continue;
    } else if (select_ret == 0) {
        fprintf(stderr, "Read timeout, total read: %d\n", read_total);
        break;
    }

    int read_num = read(serial_fd2, serial_buffer + read_total, BUFFER_SIZE - read_total);
    if (read_num == -1) {
        if (errno != EAGAIN && errno != EWOULDBLOCK) {
            perror("read error");
        }
        continue;
    } else if (read_num > 0) {
        read_total += read_num;
        printf("read num = %d | read total = %d \n", read_num, read_total);
    }
}

2. 写入后等待数据发送完成

在write()循环结束后,调用tcdrain(serial_fd)确保内核发送缓冲区的数据全部通过硬件发送,避免读取端提前开始读取:

// 原write循环完成后添加
if (tcdrain(serial_fd) == -1) {
    perror("tcdrain error");
}

3. 增大串口输入缓冲区

通过ioctl调整串口输入缓冲区大小,降低高波特率下的溢出风险:

struct serial_struct ser_info;
if (ioctl(serial_fd2, TIOCGSERIAL, &ser_info) == 0) {
    ser_info.xmit_fifo_size = 4096; // 设置为4096字节,可根据硬件调整
    if (ioctl(serial_fd2, TIOCSSERIAL, &ser_info) == -1) {
        perror("Failed to set serial buffer size");
    }
}

4. 调整串口阻塞模式(可选)

若无需非阻塞IO,可去掉O_NDELAY标志,让串口处于阻塞模式,此时read()会一直等待直到有数据可读,简化逻辑,但需注意添加超时机制避免无限等待。

内容的提问来源于stack exchange,提问作者callumQ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 11:54:57