Программа C, устанавливающая параметры порта перед сбоем открытия порта

#c #linux #serial-port

#c #linux #последовательный порт

Вопрос:

Я пытаюсь написать код на c в системе Linux, где я устанавливаю параметры последовательного порта, затем открываю последовательный порт, затем я обнаружил, что, хотя код компилируется и запускается, я не могу читать и записывать с этого последовательного порта (поэтому последовательный порт не был успешно открыт)!

Работающий код (не требуется):

 int fd;
char *portname;
portname = "/dev/ttyUSB0";
struct termios tty;

fd = open(portname, O_RDWR | O_NOCTYY | O_SYNC );

memset(amp;tty,0,sizeof tty);
tty.c_cflag amp;= ~PARENB;
tty.c_cflag amp;= ~CSTOP;
tty.c_cflag amp;= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag amp;= ~CRTSCTS;
tcsetattr(fd,TCSANOW,amp;tty);
  

Код, который не работает (необходим)

 int fd;
char *portname;
portname = "/dev/ttyUSB0";
struct termios tty;

memset(amp;tty,0,sizeof tty);
tty.c_cflag amp;= ~PARENB;
tty.c_cflag amp;= ~CSTOP;
tty.c_cflag amp;= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag amp;= ~CRTSCTS;
tcsetattr(fd,TCSANOW,amp;tty);

fd = open(portname, O_RDWR | O_NOCTYY | O_SYNC );
  

Серьезный вопрос: моя последовательность приложений требует, чтобы я установил параметры последовательного порта, а затем открыл последовательный порт. Есть ли способ сделать это? если да, то как?

Я ценю вашу помощь.

Комментарии:

1. Разрешено ли вашей программе открывать последовательный порт?

2. Поскольку у вас еще нет файлового дескриптора, вы не можете установить какие-либо параметры для подключения. Почему вашему приложению требуется такой дизайн?

3. -alk: да, я просто вставил фрагменты своего кода. -значение имеет значение: да, я добавил себя в группу удаленного доступа. -Лукаш: Моему приложению требуется такой дизайн, потому что программа была перенесена из Windows и должна была поддерживать ту же структуру. Спасибо всем за ваши комментарии. Теперь я понимаю проблему.

Ответ №1:

Обновление: удален код C , замеченный @Alter Mann.
Обновление: удалено обнуление termios структуры, замеченной @sawdust.

В первом случае вы получаете фактический дескриптор файла fd и после его использования. Во втором случае вы пытаетесь настроить неинициализированный дескриптор файла fd (возможно 0 , если он объявлен в глобальной области видимости) и после получения его фактического значения.

Ниже приведен обходной путь, который работает для меня:

 #include <fcntl.h>
#include <termios.h>
#include <strings.h>
#include <stdlib.h>

int main (int argc, char * argv [])
{
    struct termios tty;
    const char * portname = "/dev/ttyUSB0";
    const int fd = open (portname, O_RDONLY);
    if (-1 == fd) {
        // Problem...
        return EXIT_FAILURE;
    }

    if (tcgetattr (fd, amp;tty) < 0) {
        // Problem...
        return EXIT_FAILURE;
    }

    cfsetospeed (amp;tty, (speed_t) B9600);
    cfsetispeed (amp;tty, (speed_t) B9600);

    tty.c_cflag |= B9600;
    tty.c_cflag |= (tty.c_cflag amp; ~CSIZE) | CS8;
    tty.c_cflag |= (CLOCAL | CREAD);
    tty.c_cflag amp;= ~(PARENB | PARODD);
    tty.c_cflag |= IGNPAR;
    tty.c_cflag amp;= ~(CRTSCTS);
    tty.c_cflag amp;= ~(CSTOPB);
    tty.c_iflag |= IGNBRK;
    tty.c_iflag amp;= ~(IXON | IXOFF | IXANY);
    tty.c_lflag  = 0;
    tty.c_oflag  = 0;

    tcflush (fd, TCIFLUSH);
    if (tcsetattr (fd, TCSANOW, amp;tty) ) {
        // Problem...
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
  

Комментарии:

1. Обнуление структуры termios является плохой практикой кодирования. Предпочтительным / правильным методом является использование системного вызова tcgetattr(). См. раздел Правильная настройка режимов терминала

2. @sawdust, спасибо за полезный совет! Я исправил свой ответ.