Скорость передачи UART настраивается с помощью `screen`, но не с помощью`stty`

У меня есть адаптер USB-последовательный, на основе чипа CH340G. Он подключен к устройству, которое периодически отправляет строку со скоростью 9600 бод. Тем не менее, я, кажется, могу получать данные независимо от того, как я настраиваю UART с stty (версия 8.13):

# stty -F /dev/ttyUSB0 9600  
# stty -F /dev/ttyUSB0     
speed 9600 baud; line = 0;
kill = ^H; min = 100; time = 2;
-icrnl -imaxbel
-opost -onlcr
-isig -icanon -echo
# stdbuf -i0 -o0 cat /dev/ttyUSB0
data data data
^C
# stty -F /dev/ttyUSB0 115200
# stty -F /dev/ttyUSB0       
speed 115200 baud; line = 0;
kill = ^H; min = 100; time = 2;
-icrnl -imaxbel
-opost -onlcr
-isig -icanon -echo
# stdbuf -i0 -o0 cat /dev/ttyUSB0         
data data data
^C

Я полагаю, что-то не так с stty, поскольку screen работает как положено. screen /dev/ttyUSB0 9600 показывает данные, в то время как screen /dev/ttyUSB0 115200 не производит никакого вывода.

Есть ли что-то, чего мне не хватает при попытке настроить скорость передачи UART stty?

2 ответа

Я полагаю, что-то не так с stty...
...
Что-то мне не хватает в попытке настроить скорость UART с помощью stty?

Да, ваш тест некорректен, так что вы не обнаружите, что скорость передачи была изменена.

Некоторые (возможно, неясные) факты:

  • Последовательный порт может вообще не принимать данные, когда данные отправляются со скоростью передачи данных, значительно меньшей по сравнению с его конфигурацией (например, отправляются со скоростью 9600 бод и получают со скоростью 115200 бод).
  • Команда cat имеет причуду, которая может привести к тому, что она не сбрасывает буферы stdio, если не встретит символ завершения строки. IOW последовательные команды cat могут отображать одни и те же данные, когда нет завершения строки. Принятый ответ на этот вопрос намекает на эту проблему.

Ваш конкретный выбор и последовательность команд оболочки работают вместе, чтобы помочь вам сделать неверный вывод.

# stty -F / dev / ttyUSB0 9600
# stty -F / dev / ttyUSB0
# cat / dev / ttyUSB0
данные данные данные
^C

Таким образом, вы настраиваете последовательный терминал с правильной скоростью передачи данных и получаете некоторые данные.

# stty -F / dev / ttyUSB0 115200
# stty -F / dev / ttyUSB0
# cat / dev / ttyUSB0
данные данные данные
^C

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


добавление

Вы должны быть в состоянии, по крайней мере, убедить себя, что команда stty не нарушена и действительно изменяет скорость передачи данных, как и ожидалось.
Или:

О. Вместо того, чтобы переключаться на очень быструю скорость передачи (которая не может обнаружить кадрирование), измените ее на умеренную 38400 бод или более медленную 4800 бод, каждая из которых должна вызывать прием / отображение мусорных символов (вместо действительных данных или ничего).

Или же

Б. Поменяйте местами порядок скорости передачи. Сбросьте системы и используйте stty для первоначальной настройки быстрой недопустимой скорости передачи данных, чтобы вызвать либо прием / отображение мусорных символов, либо ничего.
Затем используйте stty для настройки правильной скорости передачи и начните получать данные, как и ожидалось.

Да, ты прав. я побежалstraceна экране и придумал это, которое работает:

      #include <stdint.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <asm/termbits.h>

int main(int argc, char* argv[]) {

    if (argc != 3) {
        printf("%s device speed\n\nSet speed for a serial device.\nFor instance:\n    %s /dev/ttyUSB0 75000\n", argv[0], argv[0]);                   
        return -1;
    }

    int fd = open(argv[1], O_RDWR|O_NOCTTY|O_NONBLOCK);

    int speed = atoi(argv[2]);

    int tiocm; 
    struct termios2 tio;
    ioctl(fd, TCGETS2, &tio);
//    tio.c_cflag = CS8 | CREAD | CLOCAL | B2000000;
    tio.c_cflag &= ~CBAUD | CS8 | CREAD | CLOCAL | BOTHER;
    tio.c_ispeed = speed;
    tio.c_ospeed = speed;
    tio.c_cc[VMIN]=1;
    tio.c_cc[VTIME]=-1;
    int r = ioctl(fd, TCSETS2, &tio);

     printf("Set %s Baudrate to %s.\n",argv[1],argv[2]);
}
        
 
Другие вопросы по тегам