gpt4 book ai didi

C - 串行设备未接收到数据

转载 作者:行者123 更新时间:2023-11-30 14:49:02 25 4
gpt4 key购买 nike

我正在使用 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 )。

最佳答案

嗯嗯,恐怕您没有按照正确的步骤设置 termios 参数。首先,您必须使用 tcgetattrs(3) 来获取实际配置的参数(并初始化 termios 结构,否则未初始化的代码将成为垃圾,因为您已将其声明为自动变量),然后更改您想要的内容,最后设置所需的配置。

正确的程序是:

 struct termios param;
res = tcgetattrs(fd, &param); /* VERY IMPORTANT: first get the actual parameters */
if (res < 0) {
perror("tegetattrs");
exit(EXIT_FAILURE);
}
cfsetispeed(&param, B38400);
cfsetospeed(&param, B38400);
param.c_cflag &= ~PARENB;
/* ... all the needed configuration. */
/* and finally. */
res = tcsetattrs(fd, &param);
if (res < 0) { /* error */
perror("tcsetattrs");
exit(EXIT_FAILURE);
}

(此外,检查返回值 res 是否有错误是很常见的)

正如手册页 termios(3) 中有关设置线速度的说明:

Line speed

The baud rate functions are provided for getting and setting the values of the input and output baud rates in the termios structure. The new values do not take effect until tcsetattr() is successfully called.

Setting the speed to B0 instructs the modem to "hang up". The actual bit rate corresponding to B38400 may be altered with setserial(8).

The input and output baud rates are stored in the termios structure.

(引文是我的)

关于C - 串行设备未接收到数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50056136/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com