我有一个 USB 转串行适配器,基于CH340Gstty
芯片。它连接到一个定期以 9600 波特率发送字符串的设备。但是,无论我如何配置 UART (版本 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
?
答案1
stty
我认为......有些地方出错了
......
我在尝试使用 stty 配置 UART 波特率时是否遗漏了什么?
是的,您的测试有缺陷,所以您没有检测到波特率已经改变。
一些(可能不太明显的)事实:
- 当数据以相对于其配置来说非常慢的波特率发送时(例如,以 9600 波特发送并以 115200 波特接收),串行端口根本无法接收任何数据。
- 这猫命令有一个怪癖,它会导致它不刷新 stdio 缓冲区,除非它遇到行终止符。换句话说,连续猫命令可以在没有行终止的情况下显示相同的数据。这个问题暗指这个问题。
您的特定选择和 shell 命令序列共同导致您得出错误的结论。
# 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
重新配置波特率后,串口可能停止检测有效帧,并且不会收到任何新数据。
当您再次发出猫命令,您将看到显示之前收到的相同数据(即波特率改变之前)。
附录
你至少应该能够说服自己斯特蒂命令没有损坏,并且确实按预期更改了波特率。
要么:
A. 不要更改为非常快的波特率(无法检测到任何帧),而要更改为中等的 38400 波特率或较慢的 4800 波特率,这两种情况都会导致接收/显示垃圾字符(而不是有效数据或什么都没有)。
或者
B. 交换波特率的顺序。重置系统,然后使用斯特蒂最初配置快速、无效的波特率,导致接收/显示垃圾字符或不显示任何内容。
然后使用斯特蒂配置适当的波特率,并开始按预期接收数据。
答案2
是的,你说得对。我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]);
}