对非阻塞串行使用select()
Using select() for nonblocking serial
本文关键字:select 更新时间:2023-10-16
我正在做一个项目,在这个项目中,我需要从串行端口读取和写入数据,这需要是非阻塞的,因为我不会深入讨论。select()函数看起来像我想要使用的,但我正在努力获得一个有效的实现。
在open_port()中,我定义了端口的设置,并且它是非阻塞的。在otherselect()中,我将描述符分配给open_port()并尝试读取。在函数结束时,我还有一个1秒的睡眠调用,以避免硬件读取速度过快。
运行时,在发送消息之前,我会每秒打印一条"无可用数据"的消息,发送消息后,它会打印出来,但它通常是带有二进制字符的碎片。例如,当发送单词"buffer"时,它会先打印"ffer",然后再打印一个二进制字符。
我几乎没有白蚁或选择的经验,所以任何建议都将不胜感激。
#include <iostream>
#include "stdio.h"
#include "termios.h"
#include "errno.h"
#include "fcntl.h"
#include "string.h"
#include "time.h"
#include "sys/select.h"
using namespace std;
int open_port(){
struct termios oldtio,newtio;
int serial_fd;
if ((serial_fd = open("/dev/ttyS0", O_RDWR | O_EXCL | O_NDELAY)) == -1) {
cout << "unable to open" << endl;
return -1;
}
if (tcgetattr(serial_fd, &oldtio) == -1) {
cout << "tcgetattr failed" << endl;
return -1;
}
cfmakeraw(&newtio); // Clean all settings
newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS8 | B115200; // 8 databits
newtio.c_cflag |= (CLOCAL | CREAD);
newtio.c_cflag &= ~(PARENB | PARODD); // No parity
newtio.c_cflag &= ~CRTSCTS; // No hardware handshake
newtio.c_cflag &= ~CSTOPB; // 1 stopbit
newtio.c_iflag = IGNBRK;
newtio.c_iflag &= ~(IXON | IXOFF | IXANY); // No software handshake
newtio.c_lflag = 0;
newtio.c_oflag = 0;
newtio.c_cc[VTIME] = 1;
newtio.c_cc[VMIN] = 60;
if (tcsetattr(serial_fd, TCSANOW, &newtio) == -1) {
cout << "tcsetattr failed" << endl;
return -1;
}
tcflush(serial_fd, TCIOFLUSH); // Clear IO buffer
return serial_fd;
}
void otherselect(){
fd_set readfs;
timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
char * buffer = new char[15];
int _fd = open_port();
FD_ZERO(&readfs);
FD_SET(_fd, &readfs);
select(_fd+1, &readfs, NULL, NULL, &tv /* no timeout */);
if (FD_ISSET(_fd, &readfs))
{
int r = read(_fd, buffer, 15);
if(r == -1){
cout << strerror(errno) << endl;
}
cout << buffer << endl;
}
else{
cout << "data not available" << endl;
}
close(_fd);
sleep(1);
}
int main() {
while(1){
otherselect();
}
}
当你使用read()时,你不会得到一个以null结尾的字符串,所以
cout<<buffer<<endl
显然是个坏主意。做一个,
buffer[r]=' ' #(provided r<15)
在打印出来之前。
相关文章:
- SQLite3 在 c++ 中输出 SELECT 上的空列表
- 如何在 sys/select.h 中正确使用
- 获取具有字段名称的 SELECT 字段类型,并带有 MariaDB C++连接器
- UDP 套接字 select() 在某些情况下无延迟(超时)返回 1
- Winsock2 select():同一个套接字上可能有多个事件吗?
- Winsock2 select() 返回 WSAEINVAL(错误 10022)
- 将 select() 与非基于文件描述符的输入一起使用
- Winsock2 select() 函数:传递 {0, 0} 作为超时参数
- 如何在C++应用程序中设置"Select Precision"光标?
- C++11 中对超载'ref(Select::Expressions::Code&)'的调用模棱两可
- 使用 select() 管理多个套接字
- 如何应用注册表模式使"select class depend on input"遵守开放封闭原则?
- 使用 Select 多路复用未命名的管道和其他文件描述符
- 为什么在使用 select() 时连接到带有第二个套接字的服务器"break"第一次连接?
- read() 在 select() 阻塞之后,当从生成的进程从管道读取时
- win32 select()报告插入()套接字上的例外;wsagetlasterror()= 0
- 使用SEND()之前,请使用Select()检查套接字
- 使用 select() 和大量文件描述符的外部代码
- MinGW64和"conflicting declaration of C function int select(...)"
- 是否可以使用 select(2) 来监视 SDL 文本输入事件