Arduino发送二进制串口数据,C语言读取时丢失字节的问题
问题分析与解决方案
兄弟,你这问题一眼就能看出是串口数据里的0x04字节被C语言代码“吃掉”了——从你给出的输出看,原本每个帧里的04都消失了,剩下的24 85 ab 47 43循环,核心原因是0x04被当成特殊字符处理了。
为什么会出现这种情况?
0x04对应ASCII里的EOT(传输结束)字符,如果你用C语言的文本模式打开串口(比如fopen用"r"而不是"rb"),标准库会把这个字符识别为“文件结束”信号,要么直接终止读取,要么跳过这个字节,导致你看不到它。
另外,如果你用了fgetc、fscanf这类文本处理函数,它们也会对控制字符做特殊处理,进一步加剧这个问题。
解决步骤
1. 强制用二进制模式打开串口
不管是Windows还是Linux,打开串口时都要指定二进制模式:
- Linux下:虽然系统本身不区分文本/二进制,但加上
O_BINARY标志(或者fopen用"rb")更稳妥; - Windows下:必须用
"rb"(fopen)或者O_BINARY(open),否则控制字符会被篡改。
2. 使用原始字节读取函数
别用fgetc、fgets这类文本函数,改用read()(系统调用)或者fread()(标准库)直接读取原始字节,这样就能完整获取所有二进制数据。
示例代码(Linux平台)
#include <stdio.h> #include <fcntl.h> #include <termios.h> #include <unistd.h> int main() { // 打开串口,指定二进制模式 int serial_fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY | O_BINARY); if (serial_fd == -1) { perror("Failed to open serial port"); return 1; } // 配置串口参数(必须和Arduino的设置一致,比如波特率9600、8N1) struct termios serial_opts; tcgetattr(serial_fd, &serial_opts); // 设置波特率 cfsetispeed(&serial_opts, B9600); cfsetospeed(&serial_opts, B9600); // 配置数据位、停止位、奇偶校验:8位数据,无校验,1位停止位 serial_opts.c_cflag |= (CLOCAL | CREAD); serial_opts.c_cflag &= ~PARENB; serial_opts.c_cflag &= ~CSTOPB; serial_opts.c_cflag &= ~CSIZE; serial_opts.c_cflag |= CS8; // 应用配置 tcsetattr(serial_fd, TCSANOW, &serial_opts); unsigned char buffer[128]; ssize_t bytes_read; // 循环读取串口数据 while ((bytes_read = read(serial_fd, buffer, sizeof(buffer))) > 0) { // 以十六进制打印所有读取到的字节 for (ssize_t i = 0; i < bytes_read; i++) { printf("%02X ", buffer[i]); } fflush(stdout); // 强制刷新输出缓冲区 } close(serial_fd); return 0; }
如果你习惯用标准库的fopen
也可以这样写,核心是用"rb"模式:
#include <stdio.h> int main() { FILE *serial_fp = fopen("/dev/ttyUSB0", "rb"); if (!serial_fp) { perror("Failed to open serial port"); return 1; } unsigned char buffer[128]; size_t bytes_read; while ((bytes_read = fread(buffer, 1, sizeof(buffer), serial_fp)) > 0) { for (size_t i = 0; i < bytes_read; i++) { printf("%02X ", buffer[i]); } fflush(stdout); } fclose(serial_fp); return 0; }
额外提醒
一定要确保C语言代码里的串口参数(波特率、数据位、停止位、奇偶校验)和Arduino完全一致,参数不匹配也可能导致数据乱码或者丢失。
内容的提问来源于stack exchange,提问作者Noel
相关产品推荐
相关产品推荐

