Я новичок в программировании Linux, так что будьте добры. Мне нужно считывать данные с последовательного порта (/ dev/ttyX) со скоростью передачи 921600 в режиме 8N1 без контроля четности через RS-422. Штифты выводят, что эта скорость поддерживается. Итак, я решил назвать эпос. Проблема в том, что epoll возвращает неверные байты. Поскольку я указал формат сообщений, я пытаюсь отлаживать, проверяя входящие данные руками. Поэтому я нарисовал это: Epoll читает неправильные байты
Все сообщения имеют 2 байта crc на хвосте. 11 b5 означает начало сообщения. Длина сообщения должна быть 36 байт. 72 b5 - еще один маркер начала сообщения. 112 байт len. 73 b5 - маркер сообщений. 36 байт. Пожалуйста, найдите синюю подсветку: это хорошее сообщение. Крошечный красный + жирный красный плохой. Это 37 байт. У меня есть один лишний байт и несоответствие crc. Следующий хороший идет (зеленый). И следующий плохой. Это 114 байт вместо 112 байт и несоответствие crc, конечно.
Вот мой код:
... All necessary includes
#define SERIAL_BAUD 921600
#define MAXEVENTS 1024
int openSerial()
{
struct termios options;
int fd;
if ((fd = open("/dev/ttyUSB0", O_RDWR)) == -1)
{
return -1;
}
if (tcgetattr(fd, &options) < 0)
{
printf("Unable to get options with tcgetattr\n");
return -1;
}
if (cfsetispeed(&options, SERIAL_BAUD) < 0)
{
printf("Unable to set input speed with cfsetispeed\n");
return -1;
}
if (cfsetospeed(&options, SERIAL_BAUD) < 0)
{
printf("Unable to set output speed with cfsetispeed\n");
return -1;
}
cfmakeraw(&options);
//options.c_cflag |= SERIAL_BAUD; // Set Baudrate first time
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~CRTSCTS;
options.c_cflag &= ~ECHO; // Disable echoing of input characters
options.c_cflag &= ~ECHOE;
// set to 8N1
options.c_cflag &= ~PARENB; // no parity
options.c_cflag &= ~CSTOPB; // 1 stop bit
options.c_cflag &= ~CSIZE; // Mask the character size bits
options.c_cflag |= CS8; // 8 data bits
options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
options.c_oflag = 0;
options.c_cc[VTIME] = 2; // inter-character timer
options.c_cc[VMIN] = 1; // blocking read until
if (tcflush(fd, TCIFLUSH) < 0)
{
printf("Unable to flush fd with tcflush\n");
return -1;
}
if (tcsetattr(fd, TCSANOW, &options) != 0)
{
printf("Unable to set options with tcsetattr\n");
return -1;
}
return fd;
}
int main(void)
{
int fd;
int efd;
struct epoll_event event;
struct epoll_event* events;
int length;
unsigned char buff[512];
if ((fd = openSerial()) < 0)
{
printf("Exiting because of openSerial failure\n");
return 1;
}
efd = epoll_create1(0);
event.data.fd = fd;
event.events = EPOLLIN;
if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event) < 0)
{
printf("Epoll_ctl error occured\n");
return 1;
}
events = (epoll_event*) calloc(MAXEVENTS, sizeof(event));
for(;;)
{
int n = epoll_wait(efd, events, MAXEVENTS, 5000);
if (n < 0)
{
// No ready descriptors, so wait a bit longer
continue;
}
if(events[0].events & EPOLLIN)
{
length = read(events[0].data.fd, buff, sizeof(buff)/2);
if(length > 0)
{
printf("\n------MESSAGE START-------\n");
for (int i = 0 ; i < length ; ++i)
{
if (i && i % 16 == 0)
{
printf("\n");
}
printf("%02x ", buff[i]);
}
printf("\n------MESSAGE FINISH-------\n");
}
}
else if(events[0].events & EPOLLOUT)
{
// TODO Write here to serial
}
else if(events[0].events & EPOLLHUP || events[0].events & EPOLLERR)
{
printf("Error occured on serial port\n");
}
else
{
printf("No data whthin 5 seconds.\n");
}
}
free(events);
close(fd);
return 0;
}
Функция 'openSerial()', которую вы представляете, не принимает никаких аргументов, но вы вызываете ее с аргументом. Полученное поведение не определено. –
Вы не проверяете возвращаемые значения вызовов функций для условий ошибки. Если возникла ошибка, вы наверняка получите неожиданные результаты, как если бы все было так, как ожидалось. –
Это был упрощенный список для лучшего обзора, но когда вы указали, что я должен проверить возвращенные значения, я решил снова проверить, проверяю ли все возвращаемые значения из funcs. Обнаружено, что cfsetispeed терпит неудачу. Я постараюсь это исправить. Также я обновил список кодов. –