在 Raspberry PI 3 上的 C++ 中达到超时后如何清除 select() 状态
How can I clear select() state after reaching timeout in c++ on Raspberry PI 3
我目前正在研究Raspberry PI 3. 为了循环串口通信,我在 GPIO 端口连接了 TXD 和 RXD。所以我收到了我刚刚发送的字节。在我的程序中,我需要使用超时限制来读取端口。为此,我使用了以下命令 select(fd + 1, &read_fds, NULL, NULL, &timeout)
。如果第一个字节超时(即我什么都没发送),我无法读取下一个字节 - 读取状态仍然是 "Timeout"。
我的问题是:我怎样才能清除这个状态,或者我必须为端口参数设置什么来接收在上一次端口读取期间达到超时后发送的第二个字节。我的代码如下:
#include <stdio.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>
int main ()
{
struct termios RSopt;
char byte = 0;
char str[2] = {0,0};
int fd;
fd = open( "/dev/ttyS0", O_RDWR| O_NOCTTY );
// Parameters setting for serial communication
tcgetattr(fd, &RSopt);
cfsetospeed (&RSopt, (speed_t)B300);
cfsetispeed (&RSopt, (speed_t)B300);
RSopt.c_cflag &= ~CSIZE; // Mask out size
RSopt.c_cflag |= CS8; // Or in 7-bits
RSopt.c_cflag |= PARODD; // Enable Parity - even by default
tcsetattr (fd, TCSANOW, &RSopt); // Set new options
// Timeout setting
struct timeval timeout;
timeout.tv_sec = 2;
timeout.tv_usec = 0;
// File descriptor initialization
fd_set read_fds;
//-----------------------------------------------------------------
FD_ZERO(&read_fds);
FD_SET(fd, &read_fds);
str[0] = 0xFA;
//write(fd, str, 1);
//printf("Send.\n");
//printf("Wait...\n");
if (select(fd + 1, &read_fds, NULL, NULL, &timeout) == 1) {
read(fd, &byte, 1);
printf("Recive: %x\n", byte);
} else {
printf("Timeout.\n");
}
//-----------------------------------------------------------------
FD_ZERO(&read_fds);
FD_SET(fd, &read_fds);
str[0] = 0xFB;
write(fd, str, 1);
printf("Send.\n");
printf("Wait...\n");
if (select(fd + 1, &read_fds, NULL, NULL, &timeout) == 1) {
read(fd, &byte, 1);
printf("Recive: %x\n", byte);
} else {
printf("Timeout.\n");
}
}
您需要设置
timeout.tv_sec = 2;
timeout.tv_usec = 0;
在每个 select
之前,因为某些内核会减少您的 timeout
以及在 select
中花费的时间,如果您已经超时一次,则超时值为零.
编辑:您可以通过在直接超时的 select
之前打印 timeout
值来确认这就是您正在发生的事情。
我目前正在研究Raspberry PI 3. 为了循环串口通信,我在 GPIO 端口连接了 TXD 和 RXD。所以我收到了我刚刚发送的字节。在我的程序中,我需要使用超时限制来读取端口。为此,我使用了以下命令 select(fd + 1, &read_fds, NULL, NULL, &timeout)
。如果第一个字节超时(即我什么都没发送),我无法读取下一个字节 - 读取状态仍然是 "Timeout"。
我的问题是:我怎样才能清除这个状态,或者我必须为端口参数设置什么来接收在上一次端口读取期间达到超时后发送的第二个字节。我的代码如下:
#include <stdio.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>
int main ()
{
struct termios RSopt;
char byte = 0;
char str[2] = {0,0};
int fd;
fd = open( "/dev/ttyS0", O_RDWR| O_NOCTTY );
// Parameters setting for serial communication
tcgetattr(fd, &RSopt);
cfsetospeed (&RSopt, (speed_t)B300);
cfsetispeed (&RSopt, (speed_t)B300);
RSopt.c_cflag &= ~CSIZE; // Mask out size
RSopt.c_cflag |= CS8; // Or in 7-bits
RSopt.c_cflag |= PARODD; // Enable Parity - even by default
tcsetattr (fd, TCSANOW, &RSopt); // Set new options
// Timeout setting
struct timeval timeout;
timeout.tv_sec = 2;
timeout.tv_usec = 0;
// File descriptor initialization
fd_set read_fds;
//-----------------------------------------------------------------
FD_ZERO(&read_fds);
FD_SET(fd, &read_fds);
str[0] = 0xFA;
//write(fd, str, 1);
//printf("Send.\n");
//printf("Wait...\n");
if (select(fd + 1, &read_fds, NULL, NULL, &timeout) == 1) {
read(fd, &byte, 1);
printf("Recive: %x\n", byte);
} else {
printf("Timeout.\n");
}
//-----------------------------------------------------------------
FD_ZERO(&read_fds);
FD_SET(fd, &read_fds);
str[0] = 0xFB;
write(fd, str, 1);
printf("Send.\n");
printf("Wait...\n");
if (select(fd + 1, &read_fds, NULL, NULL, &timeout) == 1) {
read(fd, &byte, 1);
printf("Recive: %x\n", byte);
} else {
printf("Timeout.\n");
}
}
您需要设置
timeout.tv_sec = 2;
timeout.tv_usec = 0;
在每个 select
之前,因为某些内核会减少您的 timeout
以及在 select
中花费的时间,如果您已经超时一次,则超时值为零.
编辑:您可以通过在直接超时的 select
之前打印 timeout
值来确认这就是您正在发生的事情。