Как я использую termios.h настроить последовательный порт для передачи необработанных байт?

Как я использую termios.h настроить последовательный порт для передачи необработанных байт?

22.01.2020 08:54:48 Просмотров 30 Источник

Мне нужно связаться с аппаратной частью через виртуальное последовательное устройство USB. Все, что мне нужно, это передавать необработанные байты вперед и назад на скорости с правильными настройками UART, я никогда не хочу использовать терминал. Доказательство концепции программного обеспечения с помощью termios не настраивает правильные биты и не работает, если я не передаю строку Magic config через stty перед запуском.

Я попытался скопировать все настройки из stty, которые появляются в справочной странице POSIX для termios.h и он все еще не работает, и теперь имеет экран, полный шаблонного кода установки флага.

Какой должна быть минимальная конфигурация с использованием termios.h, чтобы получить последовательный порт без терминала? И если есть какие-то дополнения для Linux, мне нужно будет их знать.

У вопроса есть решение - Посмотреть?

Ответы - Как я использую termios.h настроить последовательный порт для передачи необработанных байт? / How do I use termios.h to configure a serial port to pass raw bytes?

at77

22.01.2020 09:59:40

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>

int serial_open(char *port, int baud)
{
    int fd;
    struct termios tty;
    if((fd = open(port, O_RDWR | O_NOCTTY | O_SYNC)) < 0)
    {
        return -1;
    }

    if(tcgetattr(fd, &tty) < 0)
    {
        return -1;
    }

    cfsetospeed(&tty, (speed_t)baud);
    cfsetispeed(&tty, (speed_t)baud);
    tty.c_cflag |= (CLOCAL | CREAD);
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;
    tty.c_cflag &= ~PARENB;
    tty.c_cflag |= CSTOPB;
    tty.c_cflag &= ~CRTSCTS;
    tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
    tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    tty.c_oflag &= ~OPOST;
    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 1;
    if(tcsetattr(fd, TCSANOW, &tty))
    {
        return -1;
    }

    return fd;
}

/* example usage */
int fd = serial_open("/dev/ttyUSB0", B9600);
https://stackoverflow.com/questions/59865656/how-do-i-use-termios-h-to-configure-a-serial-port-to-pass-raw-bytes/59866574#comment105867321_59866574
Мой код все еще не работает, так что, очевидно, есть что-то важное, чего я не понимаю. stty не сообщает о тех же настройках, даже когда программа активна (она показывает 0 БОД и CS6, например, которые не могут быть правильными). Я понятия не имею, видят ли разные процессы разные настройки или мой двоичный файл просто не может установить порт во время работы под root. Я вернусь к этому после того, как разделю некоторые переменные. Хотя спасибо. Я постараюсь, чтобы вопрос и ответы были общими.
https://stackoverflow.com/questions/59865656/how-do-i-use-termios-h-to-configure-a-serial-port-to-pass-raw-bytes/59866574#comment105993681_59866574
В итоге мне пришлось использовать cfmakeraw(), и тогда это сработало.
davolfman

27.01.2020 08:20:18

В Linux по крайней мере функция cfmakeraw()установит флаги в struct termiosserial settings blob для raw IO. В этом случае рабочий процесс с удаленной проверкой ошибок выглядит следующим образом:

int fd = open(portname, O_RDWR | O_NOCTTY);
struct termios portSettings;
tcgetattr(fd, &portSettings);
cfsetispeed(&portSettings, B115200);
cfsetospeed(&portSettings, B115200);
cfmakeraw(&portSettings);
tcsetattr(fd, TCSANOW, &portSettings);
Закрыть X