Linux上的串口编程
Linux串口
Linux下的传统硬件串口命名为ttyS ,其中可以是1,2,3 …等,例如ttyS1,ttyS2,ttyS23 …等等。它们类似于Windows下的COM1,COM2等。
在Linux中,串行端口等硬件组件被视为文件,并在文件系统的/ dev文件夹中组合在一起。如果导航到/ dev文件夹并使用ls命令列出文件,则可以看到与各种硬件对应的文件设备。
输入命令
dmesg|grep ttyS
如果有
[ 37.531286] serial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
则表示ttyS0已连接
现在检查任何USB转串口转换器使用dmesg | grep tty命令。
可以看到FTDI转换器连接到ttyUSB0.
另一个可以看到连接的串行设备的地方是/ dev / serial / by-id文件夹。
配置串口
要在linux下执行串行I/O,需要使用termios API。termios API支持两种访问串口的模式。即
* Cannonical Mode
* NonCannonical Mode
Cannonical 模式是默认的模式,用于访问终端等。我们用后面的一种模式
打开关闭串口
函数
open()打开
close()关闭
open()系统调用需要两个参数,要打开的文件的名称(这里串行端口),并与it.It相关的各种参数返回-1失败和成功的正整数。
int fd;
fd = open( “ / dev /ttyUSB0 ”,O_RDWR | O_NOCTTY ) ;
O_RDWR :打开端口进行读写操作
O_NOCTTY :没有终端控制打开串口的进程
打开串口后,应该使用close()系统调用关闭 .close()接受一个参数,我们之前使用open()系统调用打开串口的文件描述符fd。就像close(fd)
c代码
#include <stdio.h>
#include <fcntl.h> /* File Control Definitions */
#include <termios.h>/* POSIX Terminal Control Definitions*/
#include <unistd.h> /* UNIX Standard Definitions */
#include <errno.h> /* ERROR Number Definitions */
void main()
{
int fd;
fd = open("/dev/ttyUSB0",O_RDWR | O_NOCTTY);
if(fd == 1)
printf("\n Error! in Opening ttyUSB0\n");
else
printf("\n ttyUSB0 Opened Successfully\n");
close(fd);
结果(需要使用硬件连接)
配置termios结构体
成功打开和关闭串口后,可以配置正确的模式,波特率,数据格式,启动/停止位数等。在Linux中,它由一个名为termios的结构体完成。如下:
struct termios
{
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
};
声明结构体,并使用两个函数配置它,tcgetattr() 和tcsetattr().tcsetattr()用于设置终端参数。函数在成功时返回0,失败时为-1,并设置errnod的值。tcgetattr()用于将串口的当前设置获取到我们刚刚声明的结构。它有两个参数,一个是文件描述符fd,对应于我们打开的串口,另一个是我们刚刚声明的结构的地址。
tcgetattr(fd, &SerialPortSettings);
在得到当前的设置后,我们要改变它适合我们的需要。我们将配置串行端口以9600波特率传输,8位,无奇偶校验,1个停止位,8-N-1配置。百科
设置波特率
波特率设置有两个函数
1.cfsetispeed()用于设置读或者输入的波特率
2.cfsetospeed()用于设置输出和写的波特率
cfsetispeed(&SerialPortSettings,B9600);
cfsetospeed(&SerialPortSettings,B9600);
波特率的设定需要根据连接的硬件来设定。
配置数据格式,开始/停止位,奇偶校验
termios结构的控制标志(c_cflag)配置数据格式(数据的8位或7位)、奇偶校验(偶数、奇数、None)和通信时使用的启动位和停止位的数量。配置这些信息涉及设置和清除控件标志的各个位
如:
//校验位设置
SerialPortSettings.c_cflag &= ~PARENB; /*CLEAR Parity Bit PARENB*/
SerialPortSettings.c_cflag |= PARENB; /*SET Parity Bit PARENB*/
//奇偶校验位
SerialPortSettings.c_cflag &= ~PARENB; // No Parity
//设置停止位
SerialPortSettings.c_cflag &= ~CSTOPB; //Stop bits = 1
//数据位8位
SerialPortSettings.c_cflag &= ~CSIZE; /* Clears the Mask */
SerialPortSettings.c_cflag |= CS8; /* Set the data bits = 8 */
配置其他选项
关闭基于硬件的流控制(RTS/CTS)。
SerialPortSettings.c_cflag &= ~CRTSCTS;
打开串口(CREAD)的接收器,从串口读取其他数据将不起作用。
SerialPortSettings.c_cflag |= CREAD | CLOCAL;
关闭软件流控制
SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY);
在设置操作方式时,Linux中串口的默认操作方式是Cannonical模式。对于与外部设备的串行通信,如串行调制解调器、鼠标等。
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);
有关上面讨论的函数和常量的更多信息,可以在termios手册页面中找到。
接下来我们可以使用tcsetattr()函数来设置它们。tcsetattr()接受三个参数,第一个和最后一个参数与tcgetattr()函数中相同。第二个参数optional_actions用于控制修改起作用的时间,而结构体termios_p中保存了要修改的参数。optional_actions可以取如下的值。
TCSANOW:不等数据传输完毕就立即改变属性。
TCSADRAIN:等待所有数据传输结束才改变属性。
TCSAFLUSH:清空输入输出缓冲区才改变属性。
我们不等数据传输完毕就立即改变属性,即
tcsetattr(fd,TCSANOW,&SerialPortSettings)
软件设置就完成了,硬件连接后续……