2009-11-18 3 views
6

У меня есть следующая программа C:Чтение из последовательного порта не удается

#include <fcntl.h> 
#include <termios.h> 
#include <stdio.h> 

int main() 
{ 
    int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NONBLOCK); 
    if(fd < 0) 
    { 
     perror("Could not open device"); 
    } 
    printf("Device opened\n"); 

    struct termios options; 
    tcgetattr(fd, &options); 
    cfmakeraw(&options); 
    cfsetispeed(&options, B19200); 
    cfsetospeed(&options, B19200); 
    tcsetattr(fd, TCSANOW, &options); 

    char txpacket[] = {0x23, 0x06, 0x00, 0x00, 0xdd, 0xf9}; 
    ssize_t written = write(fd, txpacket, sizeof(txpacket)); 
    printf("Written %d bytes\n", written); 

    printf("Starting to wait for target to respond\n"); 
    while(1) 
    { 
     fd_set readset; 
     FD_ZERO(&readset); 
     FD_SET(fd, &readset); 
     int nCount = select(fd + 1, &readset, NULL, NULL, NULL); 
     if(nCount > 0) 
     { 
      if(FD_ISSET(fd, &readset)) 
      { 
       int i; 
       char buffer[128]; 
       ssize_t bytesread = read(fd, buffer, sizeof(buffer)); 
       printf("Received %d bytes\n", bytesread); 
       for(i = 0; i < bytesread; i++) 
       { 
        printf(" %02x", buffer[i]); 
       } 
      } 
     } 
    } 
} 

Эта программа открывает последовательное устройство/DEV/ttyS0, записывает последовательность данных к нему и начинает прослушивание ответа. Я получаю следующий результат:

Device opened 
Written 6 bytes 
Starting to wait for target to respond 
Received 0 bytes 
Received 0 bytes 
Received 0 bytes 
Received 0 bytes 
Received 0 bytes 
Received 0 bytes 
... 

И приложение потребляет 100% процессор. Я не могу получить никаких данных, даже если целевое оборудование фактически передает его.

Что не так?

ответ

7

read() return 0 указывает состояние конца файла. Вы должны проверить это и выйти из цикла, если это произойдет.

Что касается того, что вызывает это - конец файла на последовательном порту указывает, что он обнаружил зависание, что означает, что линия DCD была удалена.

Вы можете установить флаг CLOCAL в options.c_cflag, чтобы игнорировать линии управления модемом, если ваше устройство не установило их правильно.

+0

Спасибо! Именно это и вызывало проблему. – anorm

+0

Черт, не видел CLOCAL! – shodanex

+0

Была такая же проблема, спасибо за подсказку. Не понимал, что cfmakeraw не видит этих двух очевидных флагов. – RishiD

1

Вы должны попробовать без флага O_NONBLOCK. в нестандартном режиме, если в настройках c_cc[VMIN] и c_cc[VTIME] является 0, последовательный порт ведут себя таким образом (в соответствии с человека cfmakeraw):

Если данные доступны, прочитать возвращается немедленно, с меньшим из числа доступных байтов или количество запрошенных байтов. Если данные не доступен, чтения возвращает 0

Так что вы должны попробовать это:

options->c_cc[VMIN]=1; 
+0

Действительно хорошая заметка в странном угловом корпусе. – Joe

Смежные вопросы