1

I have a USB to serial adapter, based on CH340G chip. It is connected to a device which periodically sends a string at 9600 baud. However, I seem to be able to receive the data regardless of how I configure the UART with stty (version 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

I suppose there's something wrong with stty, since screen works as expected. screen /dev/ttyUSB0 9600 shows the data, while screen /dev/ttyUSB0 115200 produces no output.

Is there something I'm missing in the attempt to configure UART baudrate with stty?

2 Answers2

1

I suppose there's something wrong with stty ...
...
Is there something I'm missing in the attempt to configure UART baudrate with stty?

Yes, your test is flawed, so that you do not detect that the baudrate has been changed.

Some (possibly obscure) facts:

  • A serial port could receive no data at all when the data is sent at a baudrate grossly slower relative to its configuration (e.g. sent at 9600 baud and receiving at 115200 baud).
  • The cat command has a quirk that can cause it to not flush stdio buffers unless it encounters a line termination character. IOW successive cat commands could display the same data when there has been no line termination. The accepted answer to this question alludes to this issue.

Your particular choice and sequence of shell commands work together to help lead you to your incorrect conclusion.

# stty -F /dev/ttyUSB0 9600
# stty -F /dev/ttyUSB0
# cat /dev/ttyUSB0
data data data
^C

So you configure the serial terminal with the proper baudrate, and receive some data.

# stty -F /dev/ttyUSB0 115200
# stty -F /dev/ttyUSB0
# cat /dev/ttyUSB0
data data data
^C

After you reconfigure with a much faster baudrate, the serial port probably ceases to detect valid frames, and no new data is received.
When you issue another cat command, you see a display of the same data that was received previously (i.e. before the baudrate change).


Addendum

You should be able to at least convince yourself that the stty command is not broken, and does change the baudrate as expected.
Either:

A. Instead of changing to a very fast baudrate (that cannot detect any framing), change to a moderate 38400 baud or a slower 4800 baud, either of which should cause reception/display of garbage characters (instead of valid data or nothing).

Or

B. Swap the order of baudrates. Reset the systems, and use stty to configure the fast, invalid baudrate initially to cause either reception/display of garbage characters or nothing.
Then use stty to configure the proper baudrate, and begin to receive the data as expected.

sawdust
  • 18,591
0

Yes, you're right. I ran strace on screen, and came up with this, which works:

#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(&quot;%s device speed\n\nSet speed for a serial device.\nFor instance:\n    %s /dev/ttyUSB0 75000\n&quot;, 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, &amp;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(&quot;Set %s Baudrate to %s.\n&quot;,argv[1],argv[2]);

}

Dagelf
  • 1,060