【问题标题】:C - Data not received by serial deviceC - 串行设备未接收到数据
【发布时间】: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 输出的差异进行更深入的研究?尤其是DTRRTS 部分?
  • 从 strace 来看,Python serial 模块显然做了三件你没有做的事情——设置 DTR 和 RTS 位,然后刷新。你试过用 C 做同样的事情吗?
  • 同时,除了“串行设备”之外,没有告诉我们更多关于您正在与什么通信的信息,很难告诉您确切应该 i> 正在做……但是在调制解调器上,您在会话开始时使用 DTR(数据终端就绪)和 RTS(请求发送)来启用发送流,在打印机上,您使用 DTR 来启用发送流等,所以一般来说,这些都非常重要。

标签: c serial-port


【解决方案1】:

嗯,恐怕你在设置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) 所说的关于设置线速度:

线速度

提供波特率函数用于获取和设置值 termios 结构中的输入和输出波特率。这 新值直到tcsetattr() 成功后才生效 调用

将速度设置为B0 会指示调制解调器“挂断”。实际上 B38400对应的比特率可以用setserial(8)改变。

输入和输出波特率存储在termios结构中

(引用是我的)

【讨论】:

    猜你喜欢
    • 2011-02-28
    • 2013-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-28
    相关资源
    最近更新 更多