Linux 串口编程
Linux 串口编程主要包含以下几步:
- 打开串口
- 配置串口
- 读写串口
- 关闭串口
打开串口
由于串口在 Linux 中被认为是一个文件,所以在操作之前应该先打开它。
#include <fcntl.h>
int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
说明:
- 在 Linux 中,通过串口终端设备文件访问串口设备,比如 /dev/ttyS0、/dev/ttyUSB0、/dev/ttyACM0;
- 调用 open() 函数打开设备,open 是系统函数,负责打开某个节点。上面代码以可读可写的方式,尝试打开
/dev/ttyS0
这个串口,如果打开成功,返回一个非负值,这个值表示串口描述符,若失败,返回一个负数,即错误码。
open 标志
标志 | 描述 |
---|---|
O_RDWR | 可读可写 |
O_NOCTTY | This means that a terminal device is opened and the program will not become the control terminal of the port. If this flag is not used, a task input (eg: keyboard stop signal, etc.) will affect the process. |
O_NDELAY | Indicates that you do not care about the state of the DCD signa l line (whether the other end of the port is activated or stopped). |
打开串行模块有那个和一些组件。
1 > 调用open()函数打开串口,获取串口的设备文件描述符
2 > 获取串口状态并判断是否被阻塞
3 > 测试打开的文件描述符是终端设备吗?
示例:
/*****************************************************************
* Name: * UART0_Open
* Function: Open the serial port and return the description of the serial device file
* Entry parameter: fd File descriptor port: serial password (ttyS0,ttyS1,ttyS2)
* Export parameter: * Correct return to 1, error return to 0
*****************************************************************/
int UART0_Open(int fd, char* port)
{
fd = open( port, O_RDWR|O_NOCTTY|O_NDELAY);
if (FALSE == fd) {
perror("Can't Open Serial Port");
return(FASLE);
}
// Determine whether the state of the serial port is blocked or not.
if(fcntl(fd, F_SETFL, 0) < 0) {
printf("fcntl failed!\n");
return(FALSE);
}
else {
printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
}
//test Is it a terminal device?
if(0 == isatty(STDIN_FILENO)) {
printf("standard input is not a terminal device\n");
return(FALSE);
}
else {
printf("isatty success!\n");
}
printf("fd->open=%d\n",fd);
return fd;
}
配置串口
成功打开串口后,还需要配置串口,设置波特率等参数。
int openUart()
{
int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
struct termios oldtio = { 0 };
struct termios newtio = { 0 };
tcgetattr(fd, &oldtio);
// 设置波特率为115200
newtio.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
newtio.c_iflag = 0; // IGNPAR | ICRNL
newtio.c_oflag = 0;
newtio.c_lflag = 0; // ICANON
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 1;
tcflush(fd, TCIOFLUSH);
tcsetattr(fd, TCSANOW, &newtio);
// 设置为非阻塞模式,这个在读串口的时候会用到
fcntl(fd, F_SETFL, O_NONBLOCK);
return fd;
}