本文主要是介绍Linux下利用select实现串口数据读取过程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设...
在 linux 系统里,我们可以借助 select
、poll
或者 epoll
这些 I/O 多路复用机制达成串口数据读取的触发方式。
这些机制能够让程序在特定文件描述符(像串口设备文件描述符)有数据可读时得到通知,进而进行数据读取操作,而不是像轮询方式那样持续调用 read
函数。
示例代码(使用select实现)
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <termIOS.h> #include <unistd.h> #include <sys/select.h> // 设置串口波特率 void SetSpeed(int fd, int speed) { struct termios options; tcgetattr(fd, &options); switch (speed) { case 115200: cfsetispeed(&options, B115200); cfsetospeed(&options, B115200); break; // 可以添加更多波特率设置 default: cfsetispeed(&options, B115200); cfsetospeed(&options, B115200); break; } tcsetattr(fd, TCSANOW, &options); } // 设置串口参数 void SetParity(int fd, int databits, int stopbits, char parity) { struct termios options; tcgetattr(fd, &options); // 设置数据位 options.c_cflag &= ~CSIZE; switch (databits) { case 7: options.c_cflag |= CS7; break; case 8: options.c_cflag |= CS8; break; default: options.c_cflag |= CS8; break; } // 设置奇偶校验位 switch (parity) { case 'n': case 'N': options.c_cflag &= ~PARENB; options.c_cflag &= ~PARODD; break; case 'o': case 'O': options.c_cflag |= (PARODD | PARENB); break; China编程 case 'e': case 'E': options.c_cflag |= PARENB; options.c_cflag &= ~PARODD; break; default: options.c_cflag &= ~PARENB; options.c_cflag &= ~PARODD; break; } // 设置停止位 switch (stopbits) { case 1: options.c_cflag &= ~CSTOPB; break; case nhVqZVTH2: options.c_cflag |= CSTOPB; break; default: options.c_cflag &= ~CSTOPB; break; } tcsetattr(fd, TCSANOW, &options); } int main(void) { int fd; unsigned char buf[300]; unsigned short len; fd = open("/dev/ttyS1", O_RdwR); if (fd == -1) { perror("can't open serial\n"); return -1; } SetParity(fd, 8, 1, 'n'); SetSpeed(fd, 115200); fd_set readfds; struct timeval timeout; while (1) { // 清空文件描述符集 FD_ZERO(&readfds); // 将串口文件描述符加入读文件描述符集 FD_SET(fd, &readfds); // 设置超时时间 timeout.tv_sec = 0; timeout.tv_usec = 20000; // 调用 select 函数等待事件发生 int activity = select(fd + 1, &readfds, NULL, NULL, &timeout); if (activityjavascript < 0) { perror("select error"); break; www.chinasem.cn} else if (activity > 0) { // 检查是否是串口文件描述符有数据可读 if (FD_ISSET(fd, &readfds)) { len = read(fd, buf, 100); if (len > 0) { python write(fd, buf, len); } } } } close(fd); return 0; }
代码解释
SetSpeed
函数:
- 此函数用于设置串口的波特率,
- 它借助
tcsetattr
函数来配置串口的输入和输出波特率
SetParity
函数:
- 该函数用于设置串口的数据位、停止位和奇偶校验位
- 同样是通过
tcsetattr
函数来完成串口参数的配置
main
函数:
- 打开串口设备文件
/dev/ttyS1
,并且设置串口参数。 - 构建一个
fd_set
类型的文件描述符集readfds
,把串口文件描述符fd
添加到该集合中。 - 设定一个超时时间
timeout
,防止select
函数一直阻塞。 - 调用
select
函数等待事件发生,若有数据可读,select
函数会返回大于 0 的值。 - 利用
FD_ISSET
宏检查是否是串口文件描述符有数据可读,若有则调用read
函数读取数据,然后将数据回写到串口。
通过这种方式,程序就无需持续轮询 read
函数,而是在有数据到达时才进行读取操作。
总结
这篇关于Linux下利用select实现串口数据读取过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!