2015-11-19 3 views
0

Я новичок в программировании Linux, так что будьте добры. Мне нужно считывать данные с последовательного порта (/ dev/ttyX) со скоростью передачи 921600 в режиме 8N1 без контроля четности через RS-422. Штифты выводят, что эта скорость поддерживается. Итак, я решил назвать эпос. Проблема в том, что epoll возвращает неверные байты. Поскольку я указал формат сообщений, я пытаюсь отлаживать, проверяя входящие данные руками. Поэтому я нарисовал это: enter image description hereEpoll читает неправильные байты

Все сообщения имеют 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; 
} 
+0

Функция 'openSerial()', которую вы представляете, не принимает никаких аргументов, но вы вызываете ее с аргументом. Полученное поведение не определено. –

+1

Вы не проверяете возвращаемые значения вызовов функций для условий ошибки. Если возникла ошибка, вы наверняка получите неожиданные результаты, как если бы все было так, как ожидалось. –

+0

Это был упрощенный список для лучшего обзора, но когда вы указали, что я должен проверить возвращенные значения, я решил снова проверить, проверяю ли все возвращаемые значения из funcs. Обнаружено, что cfsetispeed терпит неудачу. Я постараюсь это исправить. Также я обновил список кодов. –

ответ

0

Ваша проблема в том, что read() возвращает байт, которые не соответствуют вашим ожиданиям. Я не вижу оснований полагать, что epoll имеет к этому какое-то отношение.

Я также не вижу оснований полагать, что read() предоставляет разные байты, чем система, принятая с устройства /dev/ttyUSB0. Если они отличаются от ожидаемых, то я склонен полагать, что либо устройство работает неправильно, либо ваши ожидания неверны (или, по крайней мере, неполные).