↑
用户看到的串口和用户空间的串口编程 ?
和其他设备一样,Linux也是通过设备文件来提供访问串口的功能。当需要访问串口的时候,你只需要open相应的文件。
↑
串口的设备文件 ?
Linux系统上一般有一个或者多个串口,而这些串口设备文件名字比较奇怪,如比下面这样
串口设备文件名
操作系统
串口1
串口2 COM2
USB/RS-232转换器 -
Windows COM1 Linux
/dev/ttyS0 /dev/ttyS1 /dev/ttyUSB0
↑
打开串口 ?
因为串口和其他设备一样,在类Unix系统中都是以设备文件的形式存在的,所以,理所当然得你可以使用open(2)系统调用/函数来访问它。但Linux系统中却有一个稍微不方便的地方,那就是普通用户一般不能直接访问设备文件。你可以选择以下方式做一些调整,以便你编写的程序可以访问串口。
? ? ?
改变设备文件的访问权限设置 [#cd9bd1e0] 以root超级用户的身份运行程序 [#kdd0e577]
将你的程序编写位setuid程序,以串口设备所有者的身份运行程序 [#s7b703ff]
OK.假如你已经准备好了让串口设备文件可以被所有用户访问,你可以在Linux系统中实验一下下面这个程序,它可以打开计算机的串口1。
#include
#include
#include
/*
* 'open_port()' - Open serial port 1
* Returns the file descriptor on success or -1 on error. */
int open_port(void) {
int fd; /* File descriptor for the port */
fd = open(\O_NDELAY);
if (fd == -1) { /* * Could not open the port. */ perror(\/dev/ttyS0 -\ } else { fcntl(fd, F_SETFL, 0); return (fd); } }
↑
打开文件的选项 ?
打开串口连接的时候,程序在open函数中除了Read+Write模式以外还指定了两个选项;
fd = open(\O_NDELAY);
标志O_NOCTTY可以告诉UNIX这个程序不会成为这个端口上的“控制终端”。如果不这样做的话,所有的输入,比如键盘上过来的Ctrl+C中止信号等等,会影响到你的进程。而有些程序比如getty(1M/8)则会在打开登录进程的时候使用这个特性,但是通常情况下,用户程序不会使用这个行为。
O_NDELAY标志则是告诉UNIX,这个程序并不关心DCD信号线的状态——也就是不关心端口另一端是否已经连接。如果不指定这个标志的话,除非DCD信号线上有space电压否则这个程序会一直睡眠。
↑
给端口上写数据 ?
给端口上写入数据也很简单,使用write(2)系统调用就可以发送数据了:
n = write(fd, \if (n < 0)
fputs(\stderr);
和写入其他设备文件的方式相同,write函数也会返回发送数据的字节数或者在发生错误的时候返回-1。通常,发送数据最常见的错误就是EIO,当调制解调器或者数据链路将Data Carrier Detect(DCD)信号线弄掉了,就会发生这个错误。而且,直至关闭端口这个情况会一直持续。
↑
从端口上读取数据 ?
从串口上读取数据的时候就得耍花招了。因为,如果你在原数据模式(raw data mode)操作端口的话,每个read(2)系统调用都会返回从串口输入缓冲区中实际得到的字符的个数。在不能得到数据的情况下,read(2)系统调用就会一直等着,只到有端口上新的字符可以读取或者发生超时或者错误的情况发生。如果需要read(2)函数迅速返回的话,你可以使用下面这个方式:
fcntl(fd, F_SETFL, FNDELAY);
标志FNDELAY可以保证read(2)函数在端口上读不到字符的时候返回0。需要回到正常(阻塞)模式的时候,需要再次在不带FNDELAY标志的情况下调用fcntl(2)函数:
fcntl(fd, F_SETFL, 0);
当然,如果你最初就是以O_NDELAY标志打开串口的,你也可在之后使用这个方法改变读取的行为方式。
↑
关闭串口 ?
可以使用close(2)系统调用关闭串口:
close(fd);
关闭串口会将DTR信号线设置成low,这会导致很多调制解调器挂起。
↑
配置串口 ?
↑
POSIX终端接口 ?
很多系统都支持POSIX终端(串口)接口。程序可以利用这个接口来改变终端的参数,比如,波特率,字符大小等等。要使用这个端口的话,你必须将
与串口操作相关的最重要的两个POSIX函数可能就是tcgetattr(3)和tcsetattr(3)。顾名思义,这两个函数分别用来取得设设置终端的属性。调用这两个函数的时候,你需要提供一个包含着所有串口选项的termios结构体: termios结构体成员
成员 c_cflag c_lflag c_iflag c_oflag c_cc c_ispeed
描述 控制选项 行选项 输入选项 输出选项 控制字符
输入波特率(NEW)
c_ospeed 输出波特率(NEW)
↑
控制选项 ?
通过termios结构体的c_cflag成员可以控制波特率,数据的比特数,parity,停止位和硬件流控制。下面这张表列出了所有可以使用的常数。 c_cflag常数
常量 CBAUD
描述
Bit mask for baud rate
B0 B50 B75 B110 B134 B150 B200 B300 B600 B1200 B1800 B2400 B4800 B9600 B19200 B38400 B57600 B76800 B115200 EXTA EXTB CSIZE CS5 CS6 CS7 CS8 CSTOPB
0 baud (drop DTR) 50 baud 75 baud 110 baud 134.5 baud 150 baud 200 baud 300 baud 600 baud 1200 baud 1800 baud 2400 baud 4800 baud 9600 baud 19200 baud 38400 baud 57,600 baud 76,800 baud 115,200 baud External rate clock External rate clock Bit mask for data bits 5 data bits 6 data bits 7 data bits 8 data bits
2 stop bits (1 otherwise)
Linux串口编程详解
![](/skin/haowen/images/icon_star.png)
![](/skin/haowen/images/icon_star.png)
![](/skin/haowen/images/icon_star.png)
![](/skin/haowen/images/icon_star.png)