【发布时间】:2018-04-27 05:59:40
【问题描述】:
我正在使用 C 打开一个串行设备并向其发送/接收数据。接收没有问题,但我发送的任何数据都没有到达设备。我这样打开设备:
int open_tty() {
int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_CLOEXEC);
struct termios config;
cfsetispeed(&config, B38400);
cfsetospeed(&config, B38400);
config.c_cflag &= ~PARENB;
config.c_cflag &= ~CSTOPB;
config.c_cflag &= ~CSIZE;
config.c_cflag |= CS8;
tcsetattr(fd, TCSANOW, &config);
return fd;
}
...
write(fd, data, length)
...
根据 strace,一切正常:
openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_CLOEXEC) = 3
ioctl(3, TCGETS, {B38400 -opost isig icanon echo ...}) = 0
ioctl(3, SNDCTL_TMR_START or TCSETS, {B38400 -opost isig icanon echo ...}) = 0
ioctl(3, TCGETS, {B38400 -opost isig icanon echo ...}) = 0
write(3, "some data.......", 16) = 16
但是,设备没有收到任何数据(它应该发送一个 ACK 数据包)。如果我在 python 中做同样的事情,一切正常:
s=serial.Serial('/dev/ttyUSB0', baudrate=9600*4)
s.write('some data.......')
追踪:
openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NONBLOCK|O_CLOEXEC) = 3
ioctl(3, TCGETS, {B38400 -opost isig icanon echo ...}) = 0
ioctl(3, TCGETS, {B38400 -opost isig icanon echo ...}) = 0
ioctl(3, TCGETS, {B38400 -opost isig icanon echo ...}) = 0
ioctl(3, SNDCTL_TMR_START or TCSETS, {B38400 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCGETS, {B38400 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TIOCMBIS, [TIOCM_DTR]) = 0
ioctl(3, TIOCMBIS, [TIOCM_RTS]) = 0
ioctl(3, TCFLSH, TCIFLUSH) = 0
write(3, "some data.......", 16) = 16
任何帮助将不胜感激。
编辑: 正如@abarnert 建议的那样,我设置了 DTR 和 RTS 位并刷新了缓冲区:
char rts = TIOCM_RTS;
char dtr = TIOCM_DTR;
ioctl(fd, TIOCMBIS, &dtr);
ioctl(fd, TIOCMBIS, &rts);
tcflush(fd, TCIFLUSH);
这导致在write 调用之前直接调度以下额外的系统调用:
ioctl(3, TIOCMBIS, [TIOCM_DTR|TIOCM_DSR|0x200]) = 0
ioctl(3, TIOCMBIS, [[TIOCM_RTS|0x30200}) = 0
ioctl(3, TCFLSH, TCIFLUSH) = 0
但是,我仍然没有从设备收到任何 ACK 数据包。
该设备是使用 USB 转串口转换器连接的 VirtualRobotix GPS uBlox 8 (http://www.virtualrobotix.it/index.php/en/shop/gps/3dr-gps-ublox-8-542015-11-30-13-35-34_-detail)。
【问题讨论】:
-
你怎么知道“设备”没有收到数据?您是否检查过另一边的一切是否正常?
-
@Someprogrammerdude 正如我所说,设备应该发送一个 ACK,当我使用 python 时它会这样做
-
那么也许考虑对
strace输出的差异进行更深入的研究?尤其是DTR和RTS部分? -
从 strace 来看,Python
serial模块显然做了三件你没有做的事情——设置 DTR 和 RTS 位,然后刷新。你试过用 C 做同样的事情吗? -
同时,除了“串行设备”之外,没有告诉我们更多关于您正在与什么通信的信息,很难告诉您确切您应该 i> 正在做……但是在调制解调器上,您在会话开始时使用 DTR(数据终端就绪)和 RTS(请求发送)来启用发送流,在打印机上,您使用 DTR 来启用发送流等,所以一般来说,这些都非常重要。
标签: c serial-port