Windows下打开串口须用CreateFile且路径为"\.COMx",COM10以上必须加前缀;Linux用open()需注意权限、O_NOCTTY/O_NDELAY标志及termios配置;波特率、停止位、校验位三参数必须与设备手册严格一致。

Windows 下用 CreateFile 打开串口,但路径名容易写错
Windows 不把串口当普通文件,COM1 这类名字不能直接传给 fopen;必须用 CreateFile,且路径要加 \\.\ 前缀。漏掉这个前缀会返回 INVALID_HANDLE_VALUE,GetLastError() 报 ERROR_FILE_NOT_FOUND。
-
COM1→ 正确写法是\\.\COM1(注意四个反斜杠:前两个是转义,后两个是字面量) - 串口号大于 9(如
COM10)时,必须加前缀,否则系统识别失败 - 打开后记得调用
SetCommTimeouts和SetCommState配置波特率、数据位等,否则默认参数可能不匹配设备 - 不要用
FILE_SHARE_WRITE打开已占用的串口——多数硬件只允许单个句柄独占访问
Linux 下串口就是文件,但权限和阻塞模式常被忽略
Linux 把串口映射成 /dev/ttyS0 或 /dev/ttyUSB0,可用 open() 直接打开,但默认权限通常不允许普通用户读写。
- 先确认设备存在:
ls -l /dev/tty*,常见错误是误连成/dev/tty(当前控制台)而非真实串口 - 权限问题:要么加用户到
dialout组(sudo usermod -a -G dialout $USER),要么临时sudo chmod 666 /dev/ttyUSB0 -
open()一定要带O_NOCTTY | O_NDELAY,否则可能被内核抢占控制终端,或阻塞在read()上 - 配置用
tcsetattr(),别漏设c_cflag中的CREAD | CLOCAL,否则无法接收数据
跨平台读写逻辑差异大,别硬套一套代码
Windows 用 ReadFile/WriteFile,Linux 用 read/write,表面相似,底层行为完全不同:Windows 默认同步阻塞,Linux 默认非阻塞需手动设 termios。
- Windows 下
ReadFile返回 0 字节 ≠ 错误,可能是超时或无数据;检查GetLastError()是否为ERROR_IO_PENDING或WAIT_TIMEOUT - Linux 下
read()返回 -1 且errno == EAGAIN表示无数据可读,不是错误;而 Windows 的超时由COMMTIMEOUTS控制 - 换行处理不同:Windows 串口驱动可能自动转换
,Linux 完全透传,应用层要自己处理粘包或分隔符 - 别在循环里反复
open/close串口——硬件初始化耗时,且某些 USB 转串口芯片(如 CH340)会重置状态
调试时最该盯住的三个信号量
串口通信出问题,80% 是参数没对齐,而不是代码逻辑错。重点比对设备手册和你设的值是否一致,尤其这三个:
立即学习“C++免费学习笔记(深入)”;
-
baudrate:Windows 用DCB.BaudRate,Linux 用cfsetispeed()/cfsetospeed();常见坑是设了 115200 却收到乱码,其实是设备实际只支持 9600 -
stop bits:Windows 用DCB.StopBits = ONESTOPBIT,Linux 对应c_cflag & CSTOPB(清零=1位,置位=2位);设错会导致帧校验失败 -
parity:Windows 用DCB.Parity(NOPARITY/ODDPARITY),Linux 用IGNPAR | PARMRK等组合;奇偶校验开启后,数据长度要对应调整(如 8N1 → 7E1)
这些值一旦错一个,就可能收不到完整字节,或者每个字节高位总为 1 —— 不是程序 bug,是物理层握手失败。


















