Чтение последовательных данных без высокой загрузки ЦП - PullRequest
5 голосов
/ 12 августа 2011

Я хочу читать сообщения, отправленные с Arduino через интерфейс FTDI (последовательный) в простой программе на C или C ++ под Linux. Arduino отправляет двухсимвольный заголовок - командный байт, за которым следуют несколько байтов данных в зависимости от команды.

Моя первая попытка состояла в том, чтобы просто опрашивать данные с помощью open () и read (), но это вызывает примерно 12% использования ЦП. Похоже, что это не тот способ ведения дел.

Во-вторых, я прочитал в libevent о реализованном цикле событий, который запускает событие, когда данные присутствуют в дескрипторе файла. Я почти ничего не использовал, но я не мог прочитать все сообщение до того, как было вызвано другое событие. События не срабатывали при получении всего сообщения, но как только какие-либо / некоторые данные были доступны в дескрипторе файла. Глядя на это больше, было очевидно, что это не сработает так, как я этого хотел. Это мой код события: http://pastebin.com/b9W0jHjb

В-третьих, я реализовал буферизованное событие с libevent. Казалось, что он работает несколько лучше, но все же разделил некоторые сообщения. Мой код события: http://pastebin.com/PQNriUCN

В-четвертых, я выбросил libevent и опробовал класс Boost ASIO. Пример, которому я следовал, был http://www.webalice.it/fede.tft/serial_port/serial_port.html. Казалось, что он работал нормально, но «цикл обработки событий» был «while (1) {}», что привело к увеличению загрузки ЦП. Цикл просто проверяет состояние ошибки, в то время как последовательное чтение происходит в обратном вызове в другом потоке. Я добавил usleep (1) в цикл while, и он увеличил загрузку моего процессора до 2%, что нормально, но все же кажется тяжелым для такой легкой программы.

В большинстве примеров libevent и даже базового epoll используются сокеты TCP, которые, похоже, не ведут себя так же, как данные последовательного порта.

Итак, мой главный вопрос: что является хорошим облегченным способом чтения сообщений с последовательного порта без интенсивного опроса? (в Linux, используя C или C ++)

1 Ответ

13 голосов
/ 12 января 2012

ОП, вероятно, уже давно решил эту проблему, но ради любого, кто попадет сюда через google:

#include <sys/poll.h>

struct pollfd fds[1];
fds[0].fd = serial_fd;
fds[0].events = POLLIN ;
int pollrc = poll( fds, 1, 1000);
if (pollrc < 0)
{
    perror("poll");
}
else if( pollrc > 0)
{
    if( fds[0].revents & POLLIN )
    {
        char buff[1024];
        ssize_t rc = read(serial_fd, buff, sizeof(buff) );
        if (rc > 0)
        {
            /* You've got rc characters. do something with buff */
        }
    }
}    

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

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