Linux C 配置串口
配置串口需要包含头文件
#include <termios.h>
#include <unistd.h>
其中最核心的配置结构体为:
typedef unsigned int tcflag_t;
struct termios {
tcflag_t c_cflag; /* 控制标志 */
tcflag_t c_iflag; /* 输入标志 */
tcflag_t c_oflag; /* 输出标志 */
tcflag_t c_lflag; /* 本地标志 */
tcflag_t c_cc[NCCS]; /* 控制字符 */
};
如何获取该结构呢?我们操作串口跟操作文件一样,也是调用 open()
函数来打开串口,
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);
这样我们就能够得到一个文件描述符 fd
,然后就可以调用 tcgetattr()
函数来获取上述配置结构体了。
struct termios opt;
tcgetattr(fd, &opt);
Linux 串口默认的配置为:波特率 9600,数据位 8 位,无奇偶校验,停止位 1 位,无 CTS/RTS 。
以下介绍一些常用的配置项:波特率、奇偶校验、数据位、停止位、硬件控制流。
设置波特率
相关接口:
speed_t cfgetispeed(const struct termios *termios_p);
speed_t cfgetospeed(const struct termios *termios_p);
int cfsetispeed(struct termios *termios_p, speed_t speed);
int cfsetospeed(struct termios *termios_p, speed_t speed);
int cfsetspeed(struct termios *termios_p, speed_t speed);
Linux 将串口的波特率分为了输入波特率和输出波特率,不过最常用的场景是将两者设置成一样。
cfgetispeed()
函数获取输入波特率,cfgetospeed()
函数获取输出波特率。cfsetispeed()
函数设置输入波特率,cfsetospeed()
函数用于设置输出波特率,当然 cfsetspeed()
函数扩展为同时设置输入和输出波特率。
上述接口中的 speed_t
是一系列波特率的标志位,例如常用的 115200 波特率就为 B115200,参考下述选项:
B0
B50
B75
B110
B134
B150
B200
B300
B600
B1200
B1800
B2400
B4800
B9600
B19200
B38400
B57600
B115200
B230400
设置奇偶校验
设置奇偶校验位可以通过修改 termios
结构体中的 c_cflag
成员来实现,若无校验,则将 PARENB
位设为 0;若有校验,则 PARENB
为 1。之后再根据 PARODD
来区分奇偶校验,PARODD
为 1 表示奇校验,PARODD
为 0 表示偶校验。例如设置无奇偶校验位:
opt.c_cflag &= ~PARENB;
设置数据位
设置数据位可以通过修改 termios
结构体中的 c_cflag
成员来实现,CS5、CS6、CS7 和 CS8 分别代表数据位 5、6、7 和 8。不过在设置数据位之前,需要先用 CSIZE
来做屏蔽字段,清楚这几个标志位,例如设置数据位为 8 位:
opt.c_cflag &= ~CSIZE;
opt.c_cflag |= CS8;
设置停止位
设置停止位可以通过修改 termios
结构体中的 c_cflag
成员来实现,CSTOPB
位为 1 表示 2 位停止位,CSTOPB
位为 0 标志 1 位停止位。例如设置停止位为 1 位:
opt.c_cflag &= ~CSTOPB;
设置硬件控制流
设置硬件控制流可以通过修改 termios
结构体中的 c_cflag
成员来实现,CRTSCTS
为 1 表示使用硬件控制流,为 0 表示不使用硬件控制流。例如使能硬件控制流:
opt.c_cflag |= CRTSCTS;
当然,最后还需要用 tcflush()
抛弃存储在 fd
里的未接收的数据。
tcflush(fd, TCIFLUSH);
再利用接口 tcsetattr()
函数将配置信息写入文件描述符 fd
:
tcsetattr(fd, TCSANOW, &opt);
这样整个串口最常用的用法就配置完成了。
具体的配置使用可以参考我的项目 HCI-Middleware 里的 hci_transport_uart_linux.c 文件。
参考: