在Linux环境下开发串口通信程序是嵌入式系统、工业控制、物联网设备等领域常见的需求,串口作为一种基础且可靠的通信方式,其程序设计涉及硬件接口、驱动配置、通信协议等多个层面,本文将详细介绍Linux下串口程序的开发流程,包括串口设备文件、基本配置、数据收发、错误处理及高级应用等内容。

串口设备文件与权限管理
Linux系统将串口设备抽象为特殊文件,通常位于/dev目录下,常见的设备名包括/dev/ttyS0(COM1)、/ttyS1(COM2)等,对于USB转串口设备,则可能显示为/dev/ttyUSB0、/ttyACM0等,在访问串口设备前,需确保程序具有相应的操作权限,串口设备属于root用户或dialout用户组,普通用户可通过将用户加入dialout组获得权限(使用命令sudo usermod -aG dialout $USER,之后需重新登录生效),开发时也可通过临时修改设备权限(sudo chmod 666 /dev/ttyS0)进行测试,但生产环境中建议通过用户组管理权限。
串口基本配置参数
串口通信的核心在于正确配置通信参数,包括波特率、数据位、停止位、校验位和流控等,这些参数可通过termios结构体进行配置,具体步骤如下:
-
打开串口设备:使用
open()函数以读写方式打开串口设备,例如int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY),其中O_NOCTTY表示不将终端作为控制终端,O_NDELAY表示非阻塞模式(后续可通过fcntl()设置为阻塞模式)。 -
获取当前配置:通过
tcgetattr(fd, &oldtio)获取当前串口配置,保存原始设置以便恢复。 -
配置串口参数:

- 波特率:使用
cfsetispeed()和cfsetospeed()设置输入输出波特率,如cfsetispeed(&newtio, B115200)。 - 数据位:通过
newtio.c_cflag &= ~CSIZE清除数据位设置,再选择CS8(8位数据位)。 - 停止位:通过
newtio.c_cflag &= ~CSTOPB选择1位停止位,| CSTOPB选择2位。 - 校验位:禁用校验位使用
& ~PARENB,启用偶校验为| PARENB | PARODD。 - 流控:禁用硬件流控使用
& ~CRTSCTS,启用软件流控需设置| IXON | IXOFF。 - 其他设置:启用接收使能
CLOCAL和调制解调器使能CREAD,关闭XON/XOFF流控字符处理& ~IXANY。
- 波特率:使用
-
设置原始输入模式:通过
newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG)将串口设置为原始输入模式,避免终端对输入数据的处理(如回车换行)。 -
设置超时:
newtio.c_cc[VMIN] = 1表示至少读取1个字符,newtio.c_cc[VTIME] = 0表示无超时;若需超时控制,可设置VMIN=0和VTIME(单位为0.1秒)。 -
应用配置:使用
tcsetattr(fd, TCSANOW, &newtio)立即生效配置参数。
串口数据收发操作
配置完成后,可通过read()和write()函数进行数据收发:
- 发送数据:
ssize_t n = write(fd, "Hello", 5),返回成功发送的字节数,需处理部分发送的情况(通过循环调用write()直到所有数据发送完毕)。 - 接收数据:
ssize_t n = read(fd, buffer, sizeof(buffer)),返回读取的字节数,若为阻塞模式,read()会阻塞直到有数据到达或发生错误;非阻塞模式下需结合select()或poll()实现超时读取。
错误处理与状态监控
串口通信中常见的错误包括帧错误、 parity错误、溢出错误等,可通过tcgetattr()获取c_iflag和c_lflag中的错误标志位进行判断。tcflush(fd, TCIOFLUSH)可清空输入输出缓冲区,tcdrain(fd)等待所有数据发送完成。

高级应用:多路复用与异步通知
在复杂应用中,可能需要同时监控多个串口或文件描述符,此时可使用select()或poll()实现多路复用。
fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(fd, &read_fds);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
int ret = select(fd + 1, &read_fds, NULL, NULL, &timeout);
if (ret > 0 && FD_ISSET(fd, &read_fds)) {
// 数据可读
}
对于需要高实时性的场景,可通过signal()和sigaction()注册信号处理函数,结合fcntl(fd, F_SETFL, FNDELAY)和async_struct启用异步通知,当串口有数据到达时触发SIGIO信号。
常见配置参数表
| 参数类型 | 选项 | 说明 |
|---|---|---|
| 波特率 | B9600, B115200等 | 设置串口传输速率 |
| 数据位 | CS5, CS6, CS7, CS8 | 数据位长度(5-8位) |
| 停止位 | CSTOPB | 设置为2位停止位(默认1位) |
| 校验位 | PARENB, PARODD | 奇偶校验控制 |
| 流控 | CRTSCTS | 硬件流控(RTS/CTS) |
| IXON/IXOFF | 软件流控(XON/XOFF) | |
| 输入模式 | ICANON | 规范模式(行缓冲) |
| ECHO | 回显控制 | |
| 接收超时 | VMIN, VTIME | 设置最小读取字节数和超时时间 |
开发注意事项
- 资源释放:程序退出前需调用
tcsetattr(fd, TCSANOW, &oldtio)恢复串口原始配置,并使用close(fd)关闭设备文件。 - 线程安全:多线程环境下需避免同时对同一串口进行配置或收发操作,建议使用互斥锁保护。
- 性能优化:对于高频数据收发,建议使用非阻塞模式结合
poll()或epoll(),减少CPU空转。 - 跨平台兼容性:不同Linux发行版的串口驱动可能存在差异,需注意设备命名规则和驱动参数的兼容性。
通过以上步骤和配置,可完成Linux环境下稳定可靠的串口通信程序开发,实际应用中,还需根据具体硬件设备和通信协议需求,灵活调整参数并添加完善的错误处理机制,以确保程序的健壮性和可维护性。
















