Linux串口poll实现稳定读写 (linux串口poll读写)

在嵌入式开发中,串口是一种常用的通信方式,可以实现设备之间的数据传输。在Linux系统中,串口通信可以通过串口设备文件来实现。但是,在高速数据传输或大量数据读写的情况下,直接使用串口设备文件会出现延迟或数据丢失等问题。为了解决这些问题,可以使用串口poll技术来实现串口的稳定读写。

一、Linux串口通信

Linux系统将串口设备当作字符设备来进行管理,串口设备文件一般位于/dev/ttyS*,其中“*”代表串口号。例如,之一个串口设备文件为/dev/ttyS0,第二个串口设备文件为/dev/ttyS1。在使用串口之前,需要先打开串口设备文件以获取文件描述符,然后就可以进行串口读写操作。

串口读写操作一般使用系统调用 read() 和 write() 来实现。read() 函数用于从串口中读取数据,函数原型为:

ssize_t read(int fd, void *buf, size_t count);

其中,fd为打开的串口设备的文件描述符,buf为存储读取数据的缓冲区,count为希望读取的字节数。函数返回值为实际读取到的字节数。

write() 函数用于向串口中写入数据,函数原型为:

ssize_t write(int fd, const void *buf, size_t count);

其中,fd为打开的串口设备的文件描述符,buf为待写入数据的缓冲区,count为待写入数据的字节数。函数返回值为实际成功写入的字节数。

二、poll函数介绍

poll() 函数是Linux系统中用于多路复用I/O的函数之一,可以在多个文件描述符上进行监视,当其中的任意一个文件描述符就绪时,函数就可以返回。poll() 函数的功能类似于 select() 函数,但是 select() 函数有一些限制,例如文件描述符的大小限制、效率较低等问题。因此,在Linux系统中,poll() 函数被广泛应用。

poll() 函数的原型如下:

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

其中,fds是指向 struct pollfd 结构体数组的指针,nfds为数组中结构体的数量,timeout为等待时间。poll() 函数的返回值为就绪文件描述符的数量。

struct pollfd 结构体定义如下:

struct pollfd {

int fd; /* 文件描述符 */

short events; /* 监视事件 */

short revents; /* 实际发生的事件 */

};

其中,fd为文件描述符,events为监视事件,可以是以下事件的任意组合:

·POLLIN:有数据可读

·POLLOUT:写数据不会阻塞

·POLLPRI:有紧急数据可读

·POLLRDNORM:有数据可读

·POLLRDBAND:有优先数据可读

·POLLWRNORM:写数据不会阻塞

·POLLWRBAND:写优先数据可读

revents为实际发生的事件,与 events 中的事件相对应。

三、

在Linux系统中,使用 poll() 函数可以实现串口的稳定读写。具体实现方法如下:

1. 打开串口设备文件并设置相关参数,例如波特率、数据位、停止位等。

2. 创建 struct pollfd 结构体数组,并将串口设备文件的文件描述符和监视事件加入数组中。

3. 调用 poll() 函数进行监视,当串口设备有数据可读时,poll() 函数将返回1,此时可以使用 read() 函数从串口中读取数据。

4. 当需要向串口中写入数据时,可以使用 write() 函数进行写入,但需要先判断串口是否可写(即 POLLOUT 事件是否已经就绪),如果没有就绪则需要等待。

具体代码实现如下:

// 打开串口设备文件

int fd = open(“/dev/ttyS0”, O_RDWR | O_NOCTTY | O_NDELAY);

if (fd

perror(“Open ttyS0 error.”);

return -1;

}

// 设置串口参数

struct termios opt;

tcgetattr(fd, &opt);

cfsetispeed(&opt, B9600);

cfsetospeed(&opt, B9600);

opt.c_cflag &= ~PARENB; // 无奇偶校验

opt.c_cflag &= ~CSTOPB; // 1位停止位

opt.c_cflag &= ~CSIZE; // 8位数据位

opt.c_cflag |= CS8; // 8位数据位

opt.c_cc[VTIME] = 0; // 读取超时时间0s

opt.c_cc[VMIN] = 1; // 最少读取1个字符

tcsetattr(fd, TCSANOW, &opt);

// 创建 struct pollfd 结构体

struct pollfd fds[1];

fds[0].fd = fd;

fds[0].events = POLLIN;

// 监视串口设备

while (1) {

int ret = poll(fds, 1, 1000); // 等待1000ms

if (ret

perror(“Poll error.”);

break;

} else if (ret == 0) {

printf(“Poll timeout.\n”);

} else {

if (fds[0].revents & POLLIN) { // 串口可读

char data[1024] = {0};

int len = read(fd, data, 1024);

if (len > 0) {

printf(“Read data: %s\n”, data);

}

}

if (fds[0].revents & POLLOUT) { // 串口可写

char data[1024] = “Hello World!”;

int len = strlen(data);

int n = write(fd, data, len);

if (n != len) {

printf(“Write error.\n”);

}

}

}

}

在上述代码中,打开串口设备文件后,使用 tcgetattr() 和 tcsetattr() 函数设置串口参数,然后创建 struct pollfd 结构体并将监视事件添加到数组中。在 while 循环中,使用 poll() 函数等待串口设备就绪,当有数据可读时使用 read() 函数读取数据,当需要写入数据时则使用 write() 函数,但必须先判断 POLLOUT 事件是否已经就绪。

四、

通过使用 Linux 中的 poll() 函数,可以实现串口的稳定读写。poll() 函数可以同时监视多个文件描述符的就绪状态,并且可以指定等待时间。使用 poll() 函数实现串口读写时,需要先设置串口参数,然后创建 struct pollfd 结构体,并将监视事件加入数组中。在进行串口读写时,必须先判断相应的事件是否已经就绪,以避免出现延迟或数据丢失等问题。


数据运维技术 » Linux串口poll实现稳定读写 (linux串口poll读写)