При считывании из последовательного порта буфер заполняется нулями
Программа на С++ считывает данные из последовательного порта. А в качестве тестового устройства - Arduino, которая периодически шлет NMEA стоку в порт.
Подключение и считываение стабильно происходит без ошибок, функция read(2) "рапортует" об успехе и возвращает ненулевое число. Но при попытке напечатать принятое оказывается что в буфере нули.
Причем(!), периодически, первые несколько секунд все работает как положено, но затем начинают приниматься нули.
Аналогичная программа на python с библиотекой pyserial работает отлично. Т.е. проблема не в Arduino а именно в коде на С++. Я заглялнул в исходникики pyserial и выставил у себя точно такие же настройки порта как и там.
int m_fd = ::open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NONBLOCK);
if (m_fd < 0) return false;
struct termios tty;
memset(&tty, 0, sizeof(tty));
if (tcgetattr(m_fd, &tty) != 0) {
printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
return false;
}
ioctl(m_fd, TCIFLUSH);
cfsetspeed(&tty, B9600);
#define CMSPAR 0b10000000000 // Use "stick" (mark/space) parity
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~(PARENB | PARODD | CMSPAR);
tty.c_cflag &=~ CSTOPB;
// Enable receiver (CREAD) and ignore modem control lines (CLOCAL)
tty.c_cflag |= (CREAD | CLOCAL);
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG | IEXTEN);
tty.c_iflag &= ~INPCK;
tty.c_iflag &= ~(INLCR | IGNCR | ICRNL | IGNBRK);
tty.c_oflag &= ~(OPOST | ONLCR | OCRNL);
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 0;
tcflush(m_fd, TCIFLUSH);
if (tcsetattr(m_fd, TCSANOW, &tty) != 0) {
printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
return false;
}
char buffer[4096];
pollfd fd;
fd.events = POLLIN;
fd.fd = m_fd;
while (true){
auto result = poll(&fd, 1, 1000);
if (!result) continue;
if (result < 0) break;
if(fd.revents & POLLIN){
int n_recv = read(m_fd,buffer,4096);
fd.revents = 0;
printf("read from serial %d\n", n_recv);
printf("%.*s", n_recv, buffer);
}
else{
printf("error\n");
}
}
В отрывке из вывода видно что сначала мы получаем валидные данные, затем получем нули, хотя количество считанных байт ненулевое и соответсвует тому объему, который действительно передается в порт. В половине случаев нули начинают приниматься сразу же при запуске программы.
!read from serial 32
AIVDM,1,1,,B,144fmig001Re4T4IUu6read from serial 32
h0:pp20Rn,0*40
!AIVDM,1,1,,B,144read from serial 32
bqI13002eQ0lIQhehq4tp0hA2,0*01
read from serial 1
read from serial 32
read from serial 32
read from serial 32
read from serial 32
read from serial 32
read from serial 32
read from serial 32
Проблема сохраняется как при неблокирующем чтении (как в листинге), так и при блокируюшем.