Программирование последовательного порта Linux, ttyS0

Я пытаюсь научиться программировать последовательный порт ttyS0 в Linux с помощью C. У меня есть другой компьютер, подключенный к моему последовательному порту, который отправляет чередующиеся шестнадцатеричные значения 5f и 6f примерно каждые две секунды. Я проверил с помощью других приложений для мониторинга портов, что эти значения появляются в порту. В моем коде я использую блокирующий read () в буфере длиной 10 символов. Хотя другая моя машина все еще отправляет данные, read () блокируется навсегда. Если я включу строку fcntl (fd, F_SETFL, FNDELAY);, которая устанавливает для read () неблокирующий режим, read () всегда возвращает значение -1, что означает, что в буфере UART нет данных. , а мой код цикла for просто выводит случайные значения, находящиеся в буфере. Короче говоря, я предполагаю, что мой код не читает ttyS0, и я понятия не имею, почему. Ниже мой код, надеюсь, кто-то увидит, что вызывает мою проблему, и исправит меня. Кстати, я использую Scientific Linux и считаю, что ttyS0 - это com-порт 1, как в RedHat и Fedora. Ниже приведен результат, когда я запускаю код. Вроде пишет в COM-порт без проблем, но при чтении пишет, что недоступен. Также ясно, что распечатываемый мной буфер - это просто случайные значения, а не считанные данные. Спасибо

консольный вывод

hello world
hi again
write error: : Success
 wrote 4 bytes
number of bytes read is -1
read error:: Resource temporarily unavailable
4  8  120  -99  -73  -65  41  -120  4  8  
should of put something out

Код

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

int main()
{
    printf("hello world\n");
    int n;
    int fd;
    char c;
    int bytes;

    char buffer[10];
    char *bufptr;
    int nbytes;
    int tries;
    int x;
    struct termios options;


    fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
    if(fd == -1)
    {
        perror("open_port: Unable to open:");
    }
    else
    {
        fcntl(fd, F_SETFL, 0);
        printf("hi again\n");
    }

    tcgetattr(fd, &options);

    cfsetispeed(&options, B115200);
    cfsetospeed(&options, B115200);
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    options.c_cflag &= ~( ICANON | ECHO | ECHOE |ISIG );
    options.c_iflag &= ~(IXON | IXOFF | IXANY );
    options.c_oflag &= ~OPOST;

    tcsetattr(fd, TCSANOW, &options);


    write(fd, "ATZ\r",4);
    printf(" wrote\n");
    bufptr = buffer;


    fcntl(fd, F_SETFL, FNDELAY);
     bytes = read(fd, bufptr, sizeof(buffer));
    printf("number of bytes read is %d\n", bytes);
    perror ("read error:");

    for (x = 0; x < 10 ; x++)
    {
        c = buffer[x];
        printf("%d  ",c);
    }
    close(fd);

    //puts(buffer[0]);
    printf("\nshould of put something out \n");

    return (0);
}

person Frank Dejay    schedule 20.04.2012    source источник
comment
Если вы сделаете файловый дескриптор неблокирующим, read возврат -1 может означать и другие вещи. Вы должны проверить errno, чтобы увидеть, что это на самом деле означает.   -  person Some programmer dude    schedule 20.04.2012
comment
@JoachimPileborg ОК. Я добавил строки perrer () после read () и write (). Похоже, он пишет нормально, но нет доступа к порту для чтения.   -  person Frank Dejay    schedule 20.04.2012
comment
@FrankDejay В строке options.c_cflag &= ~( ICANON | ECHO | ECHOE |ISIG ); вы имели в виду установить options.c_lflag, а не options.c_cflag?   -  person Vilhelm Gray    schedule 26.09.2013
comment
Три основных проблемы с вашим кодом: (1) Ваша программа использует неблокирующий режим для ввода. Было бы намного лучше использовать режим блокировки. (2) Ваша программа использует неканонический режим. Поскольку вывод и ввод представляют собой строки текста, вместо этого вы можете настроить терминал для канонического режима. См. stackoverflow. com / questions / 25996171 / (3) Неправильная конфигурация termios, о чем упоминал @VilhelmGray.   -  person sawdust    schedule 18.01.2018


Ответы (1)


Следующая строка вызовет проблемы:

options.c_cflag &= CSTOPB;

Он сбросит все остальные биты c_cflag.

Если вы хотите использовать 1 стоповый бит, используйте:

options.c_cflag &= ~CSTOPB;

Если вы хотите использовать 2 стоповых бита, используйте:

options.c_cflag |= CSTOPB;

РЕДАКТИРОВАТЬ:

Также проблемы вызывает следующая строка:

fcntl(fd, F_SETFL, 0);

Это сбросит несколько важных флагов.

person SKi    schedule 20.04.2012
comment
Спасибо, я внес эти изменения. Но все равно не работает. Я отредактировал свой код в сообщении, чтобы отразить изменения. Я также добавил строки perror (). Похоже, он пишет нормально, но не может получить доступ к порту для чтения. Как вы думаете, почему это так? - person Frank Dejay; 20.04.2012
comment
@Frank Dejay Также есть некоторые странности в установке флагов. Я обновил свой ответ. - person SKi; 23.04.2012
comment
Также следующая строка вызывает проблемы: fcntl(fd, F_SETFL, 0); Он сбрасывает несколько важных флагов. - На самом деле это не вызовет проблем; системный вызов может изменять только задокументированный и ограниченный набор параметров файлового дескриптора. В этом случае будет сброшен только флаг O_NDELAY (но позже он снова будет включен и вызовет проблемы для OP). - person sawdust; 18.01.2018