Я пытался настроить его в конфигурации блокировки, но если я это сделаю, код просто зависает на неопределенное время при первом чтении ().
Результаты, которые вы описываете, аналогичны блокированию канонического режима (когда вы действительно хотите (блокирование) необработанного режима).
read () должен блокироваться, пока не будет получен символ EOL (конец строки).
Однако, когда я пытаюсь читать с последовательного порта, read () возвращает -1 почти все время, пока внезапно в кажущейся случайной точке я не получаю массивный дамп сообщений одновременно.
Результаты, которые вы описываете, аналогичны неблокирующему каноническому режиму (когда вам действительно нужен (блокирующий) необработанный режим).
Если в буфере нет данных (т. Е. Полной строки), read () вернет -1 и errno (что вам не нужно проверить) установлено на -EAGAIN.
Но когда двоичные данные совпадают по совпадению с символом EOL (конец строки), условие канонического read () удовлетворяется, и буферизованные данные возвращаются.
Причина, по которой последовательный терминал фактически не настроен на неканонический режим, заключается в том, что ICANON и связанные с ним флаги очищаются от неправильного члена.
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);//Non-canonical mode
ICANON является членом c_lflag
, а не c_iflag
.
Таким образом, заявление должно быть
SerialPortSettings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // Non-canonical mode
Предположительно, что последовательный терминал по умолчанию перешел в канонический режим, и ваша программа никогда не меняла режим на что-либо другое.
Кроме того, для необработанного режима необходимо определить элементы VMIN и VTIME.
Например:
SerialPortSettings.c_cc[VMIN] = 1;
SerialPortSettings.c_cc[VTIME] = 1;
Другая ошибка в вашем коде - это использование указателя на адрес массива (т.е. адрес адреса), когда адреса массива будет достаточно.
bytes_read = read(fd,&buf,1024);
должно быть просто
bytes_read = read(fd, buf, 1024);
ДОПОЛНЕНИЕ
Код OP замечательно похож на этот вопрос , в котором есть то же неверное утверждение termios.
Этот плакат в конечном итоге решил свою собственную проблему, но по ошибке приписал исправление добавлению (не относящемуся к делу) флага ECHONL и не осознавая, что он на самом деле исправляет имя члена структуры.
ADDENDUM 2
Источником этой c_iflag и ICANON , по-видимому, является это руководство по последовательному порту от xanthium.in . Автор был уведомлен более двух лет назад об ошибке, но не исправил ее.