Linux串行读取阻止minicom
Linux serial read blocks minicom
我正试图从BeagleBone Black上的串行端口(/dev/ttyS4
)读取,但我认为(?)这应该适用于所有Linux设备。
目前,我可以设置波特率为9600的minicom
和8N1数据,以便正确地从串行端口读取。但是,如果我尝试直接cat /dev/ttyS4
,则在我的终端中不会显示任何内容。我的代码也这样做,并返回一个Resource temporarily unavailable
错误,我怀疑这就是cat
命令所发生的情况。
如果我运行stty -F /dev/ttyS4
,我会得到以下输出(据我所知,这与我的minicom
设置一致):
speed 9600 baud; line = 0;
intr = <undef>; quit = <undef>; erase = <undef>; kill = <undef>; eof = <undef>; start = <undef>; stop = <undef>; susp = <undef>; rprnt = <undef>; werase = <undef>; lnext = <undef>; flush = <undef>;
-brkint -imaxbel
-opost -onclr
-isig -iexten -echo -echoe -echok -echoctl -echoke
一个有趣的注意事项是,当我打开minicom
时,如果我启动程序,minicom将停止打印任何内容,即使我停止程序,也会保持这种状态。我需要再次打开串行设置(Ctrl-A
、P
)并关闭它,以便minicom
恢复工作(看起来什么都没有改变)。
我的代码如下:
int main() {
std::cout << "Starting..." << std::endl;
std::cout << "Connecting..." << std::endl;
int tty4 = open("/dev/ttyS4", O_RDWR | O_NOCTTY | O_NDELAY);
if (tty4 < 0) {
std::cout << "Error opening serial terminal." << std::endl;
}
std::cout << "Configuring..." << std::endl;
struct termios oldtio, newtio;
tcgetattr(tty4, &oldtio); // save current serial port settings
bzero(&newtio, sizeof(newtio)); // clear struct for new settings
newtio.c_cflag = B9600 | CS8 | CREAD | CLOCAL;
newtio.c_iflag = IGNPAR | ICRNL;
newtio.c_oflag = 0;
newtio.c_lflag = ICANON;
tcflush(tty4, TCIFLUSH);
tcsetattr(tty4, TCSANOW, &newtio);
std::cout << "Reading..." << std::endl;
while (true) {
uint8_t byte;
int status = read(tty4, &byte, 1);
if (status > 0) {
std::cout << (char)byte;
} else if (status == -1) {
std::cout << "tERROR: " << strerror(errno) << std::endl;
}
}
tcsetattr(tty4, TCSANOW, &oldtio);
close(tty4);
}
编辑:我已经按照Adafruit的教程将python与BeagleBone一起使用,使串行端口正确工作(在python中)。在这一点上,我确信我做错了什么;问题是什么。我更喜欢使用C++而不是python,所以能做到这一点会很好。
您的程序以非阻塞模式打开串行终端。
int tty4 = open("/dev/ttyS4", O_RDWR | O_NOCTTY | O_NDELAY);
非阻塞I/O,尤其是读操作,需要在程序中进行额外的特殊处理。由于您忽略了提及此模式,并且您的程序无法正确处理此模式,因此这可能被认为是一个错误。
从open()调用中删除O_NDELAY选项,或者插入fcntl(tty4, F_SETFL, 0)
语句以恢复到阻塞模式。
我的代码也这样做,并返回
Resource temporarily unavailable
错误,
这是一个EAGAIN错误,与非阻塞的read()一致
手册页描述了当";文件描述符。。。已经被标记为非阻塞(O_NONBLOCK),并且读取将阻塞">
read()系统调用"将阻止";因为没有数据来满足读取请求。
如果您坚持使用非阻塞模式,那么您的程序必须能够处理这种情况,这不是错误,而是临时/瞬态状态
但是,对于多任务系统中的典型程序,阻塞模式是更简单且首选的操作模式
您的程序应该按照前面提到的进行修改。
串行终端的初始化存在许多问题。
tcgetattr(tty4, &oldtio); // save current serial port settings
从不检查tcgetattr()和tcpetattr()系统调用的返回值是否存在错误。
bzero(&newtio, sizeof(newtio)); // clear struct for new settings
从一个空的白蚁结构开始几乎总是一个坏主意。它可能在某些系统上运行,但它不是可移植的代码
初始化termios结构的正确方法是使用tcgetattr()中的值
请参阅正确设置终端模式
由于它已经被调用,您只需要newtio = oldtio
来复制结构。
改这些标志的正确方法不是指定常量,而是启用或禁用各个属性newtio.c_cflag = B9600 | CS8 | CREAD | CLOCAL;
以下内容应足以满足规范模式:newtio.c_cflag |= CLOCAL | CREAD; newtio.c_cflag &= ~CSIZE; newtio.c_cflag |= CS8; /* 8-bit characters */ newtio.c_cflag &= ~PARENB; /* no parity bit */ newtio.c_cflag &= ~CSTOPB; /* only need 1 stop bit */ newtio.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */ newtio.c_lflag |= ICANON | ISIG; /* canonical input */ newtio.c_lflag &= ~(ECHO | ECHOE | ECHONL | IEXTEN); newtio.c_iflag &= ~INPCK; newtio.c_iflag |= ICRNL; newtio.c_iflag &= ~(INLCR | IGNCR | IUCLC | IMAXBEL); newtio.c_iflag &= ~(IXON | IXOFF | IXANY); /* no SW flowcontrol */ newtio.c_oflag &= ~OPOST;
以下是设置波特率的首选方法:
cfsetospeed(&newtio, B9600); cfsetispeed(&newtio, B9600);
如果未指定任何显著属性,则使用现有设置
这可能会导致程序行为不稳定,例如有时它工作,有时它不工作。一个有趣的注意事项是,当我打开minicom时,如果我启动程序,minicom将停止打印任何内容,即使我停止程序,也会保持这种状态。我需要再次打开串行设置(Ctrl-A,P)并关闭它,以便minicom恢复工作(看起来什么都没有改变)。
串行终端不用于在多个进程之间共享
一些termios属性必须在串行设备驱动程序中实现,该驱动程序没有共享端口的概念。最新的termios属性对设备有效
当您在minicom启动后执行程序时,您正在破坏minicom望使用的termios属性
您正在使用minicom的菜单将termios属性恢复到其要求。
- 理解boost::asio-async_read在无需读取内容时的行为
- 使用新行和不使用新行读取文件
- 读取文件并输入到矢量中
- 用c++从输入文件中读取另一行
- 读取文件的最后一行并输入到链接列表时出错
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 无法找到/读取配置文件.conf-FileIOException
- 如何使用Luacneneneba API正确读取字符串和表参数
- C++将文本文件中的数据读取到结构数组中
- 正在将csv文件读取为双精度矢量
- 为什么 sscanf 无法从一个字符串中读取uint64_t和字符?
- 为什么在读取文件大小时文件IO速度会发生变化
- 正在读取二进制文件(is_open)
- 如何在c++中从文本文件中逐行读取整数
- SSH通过/sbin/SSH无法读取RSA密钥文件(从控制台运行)
- 独立读取-修改-写入顺序
- 从文本文件中读取时钟时间和事件时间并进行处理
- 如何从文本文件中读取值和数组
- 为什么文件名被设置为一个点,而不是在读取矢量中的文件名时
- Linux串行读取阻止minicom