Linux - чтение последовательного порта, возвращающее EAGAIN - PullRequest
9 голосов
/ 23 октября 2009

У меня проблемы с чтением данных с последовательного порта, который я открыл следующим образом. Я использовал этот экземпляр кода много раз, и все работало нормально, но сейчас, по какой-то причине, которую я не могу понять, я совершенно не могу прочитать что-либо из последовательного порта.

Я могу написать, и все правильно получено на другом конце, но ответы (которые отправлены правильно) никогда не принимаются (Нет, все кабели в порядке;))

Код, который я использовал для открытия последовательного порта, следующий:

fd = open("/dev/ttyUSB0", O_RDWR | O_NONBLOCK | O_NOCTTY);
if (fd == -1)
{
    Aviso("Unable to open port");
    return (fd);
}
else
{
    //Get the current options for the port...
    bzero(&options, sizeof(options)); /* clear struct for new port settings */
    tcgetattr(fd, &options);

    /*-- Set baud rate -------------------------------------------------------*/
    if (cfsetispeed(&options, SerialBaudInterp(BaudRate))==-1)
        perror("On cfsetispeed:");
    if (cfsetospeed(&options, SerialBaudInterp(BaudRate))==-1)
        perror("On cfsetospeed:");

    //Enable the receiver and set local mode...
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB; /* Parity disabled */
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;  /* Mask the character size bits */
    options.c_cflag |= SerialDataBitsInterp(8);           /* CS8 - Selects 8 data bits */
    options.c_cflag &= ~CRTSCTS;                            // disable hardware flow control
    options.c_iflag &= ~(IXON | IXOFF | IXANY);           // disable XON XOFF (for transmit and receive)
    options.c_cflag |= CRTSCTS;                         /* enable hardware flow control */

    options.c_cc[VMIN] = 0;     //min carachters to be read
    options.c_cc[VTIME] = 0;    //Time to wait for data (tenths of seconds)

    //Set the new options for the port...
    tcflush(fd, TCIFLUSH);
    if (tcsetattr(fd, TCSANOW, &options)==-1)
    {
        perror("On tcsetattr:");
    }

    PortOpen[ComPort] = fd;
}

return PortOpen[ComPort];

После инициализации порта я записываю в него некоторые вещи с помощью простой команды записи ...

int nc = write(hCom, txchar, n);

где hCom - дескриптор файла (и это нормально), и (как я уже сказал) это работает. Но ... когда я делаю чтение после этого, я получаю ошибку "Resource временно недоступен" из errno.

Я проверил select, чтобы увидеть, когда в дескрипторе файла что-то прочиталось ... но время ожидания истекло!

Я читаю данные так:

ret = read(hCom, rxchar, n);

и я всегда получаю EAGAIN, и я понятия не имею, почему.

Обновление:

HW работает нормально! Я вижу, что на последовательном порту есть входящие данные, потому что я сделал отладочный кабель для чтения того, что происходит на другом терминале. Итак ...

Я знаю, что должен делать неблокирующий. Мой вопрос ... почему ничего не читают! Та же настройка отлично работает на Windows, поэтому все оборудование работает нормально ...

Это сводит меня с ума! Я уверен, что это что-то простое, как ад! Я даже пытался избавиться от O_NONBLOCK, чтобы увидеть, когда я получу что-то ... но ничего ...

Ответы [ 5 ]

11 голосов
/ 23 октября 2009

Читать это .

EAGAIN Неблокирующий ввод / вывод был выбран с помощью O_NONBLOCK и без данных был немедленно доступен для чтения.

2 голосов
/ 29 октября 2012

Сначала необходимо проверить настройки последовательного терминала.

использовать команду - stty -F /dev/ttyUSB0 -a

Убедитесь, что ctsrts выбрано как -ctsrts и выполните другие необходимые настройки с помощью утилиты stty, и все готово.

0 голосов
/ 27 марта 2010

У меня такая же проблема. Я могу передавать, но не получать (через кабель-адаптер USB-RS232). Я попробовал на другой коробке Linux, который имел порт RS232, и он работал просто отлично. Единственное изменение, которое я сделал, было от /dev/ttyUSB0 до /dev/ttyS0. Первый компьютер был Fedora, второй - Debian. Кроме этого, идунно.

Еще одна вещь. Когда я закрываю программу com и перезапускаю ее, данные читаются моей программой! Данные являются входным буфером, но моя программа этого не знает. Кроме того, gtkterm работает нормально, так что все в порядке. Моя программа не видит прерывание UART.

Этот уровень абстракции linux h / w довольно поддельный. Это не должно быть проблемой.

0 голосов
/ 23 октября 2009

посмотрите мои примеры кода, если EAGAIN, вы попытаетесь прочитать снова:

...
options.c_cflag &= ~PARENB; 
options.c_iflag &= ~INPCK; 
...
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // input
options.c_oflag &= ~OPOST; // output
...
fd = open("/dev/ttyUSB0", O_RDWR | O_NDELY | O_NOCTTY);
fcntl(fd, F_SETFL, 0);
...
int nc = write(hCom, txchar, n);
msleep(500); // wait 500ms
fcntl(hCom, F_SETFL, FNDELAY); // don't block serial read
ret = read(hCom, rxchar, n);
if (ret > 0) {
    here had read n bytes or just partial data, read again if partial.
} 
if (ret < 0) {
    if (EAGAIN == errno) {
        not a real error, just read again.
    } else {
        oops, errors.
    }
}
...
0 голосов
/ 23 октября 2009

EAGAIN с O_NONBLOCK означает, что данные не были получены по порту. Убедитесь, что порт и кабель работают правильно (с помощью minicom или другой заведомо исправной программы) и что пульт действительно отправляет некоторые данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...