【问题标题】:Can't read serial data unless port is opened by third party program除非第三方程序打开端口,否则无法读取串行数据
【发布时间】:2016-11-01 16:37:03
【问题描述】:

我正在尝试通过串行方式从 Xbee 读取数据。如果我通过调用 xbee_init() 来初始化端口,那么我会调用 xbee_read() 出于某种原因,我总是没有读取任何数据并得到 -1 的错误。然而,当我使用一些第三方程序(如 gtkterm 或 Arduino 串行监视器)查看端口时,我突然开始从我的程序中读取数据。然后它会正常工作,直到我结束我的程序并重新启动它,然后它又回到不读取数据的状态。

有人知道为什么会这样吗?我已经用 Xbee 和 Arduino 对此进行了测试,这是相同的行为。我从一个更大的 C++ 程序中调用这些函数。谢谢!

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <termios.h>
#include "../include/m545_wireless_communication/readXbee.h"

int xbee_init (char *port, struct termios *tty) {

    int fd=open(port,O_RDWR | O_NOCTTY | O_NONBLOCK);

    if(fd == -1){return 0;}
    else {
        if(tcgetattr(fd, tty)!=0){return 0;}
        else{
                cfsetospeed(tty, B57600);
                cfsetispeed(tty, B57600);

                tty->c_cflag &= ~PARENB;
                tty->c_cflag &= ~CSTOPB;
                tty->c_cflag &= ~CSIZE;
                tty->c_cflag |= CS8;
                tty->c_cflag &= ~CRTSCTS; 
                tty->c_cflag |= CLOCAL | CREAD;

                tty->c_iflag |= IGNPAR | IGNCR;
                tty->c_iflag &= ~(IXON | IXOFF | IXANY);
                tty->c_lflag |= ICANON;
                tty->c_oflag &= ~OPOST;
                tcsetattr(fd, TCSANOW, tty);

                }
            }

    return fd;
}


char* xbee_read (int fd, char *buffer) {

    if(fd){
        int n=read(fd,buffer,11);
        printf("%d\n", n);
        return buffer;
    }else{
        return NULL;
    }
}

void xbee_close(int fd){
    close(fd);
}

这是调用我的 xbee 函数的主要函数。这是 ROS 项目的一部分,该节点旨在通过串行方式简单地从 xbee 读取数据,并以 10Hz 的频率将其发布到 /xbee 主题。

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
#include <termios.h>
#include "m545_wireless_communication/readXbee.h"


int main(int argc, char **argv)
{

  ros::init(argc, argv, "Broadcaster");

  ros::NodeHandle broadcasterHandle;
  ros::Publisher broadPub = broadcasterHandle.advertise<std_msgs::String>("xbee", 1);

  char *port = "/dev/ttyUSB1";
  struct termios tty;
  char buffer[11];

  int fd = xbee_init(port,&tty);

  ros::Rate loop_rate(10);

  while (ros::ok())
  {
    char *message = xbee_read(fd, buffer);

    std_msgs::String msg;

    std::stringstream ss;
    ss << message;
    msg.data = ss.str();

    ROS_INFO("I heard: %s", msg.data.c_str());

    broadPub.publish(msg);

    ros::spinOnce();

    loop_rate.sleep();
  }

  ROS_INFO("Closing Port");
  xbee_close(fd);

  return 0;
}

【问题讨论】:

  • 1) 注意:如果代码的c_cflag 字段比unsigned 宽,那么&amp;= ~various_int_constants; 可能有问题。 tty-&gt;c_cflag |= PARENB; tty-&gt;c_cflag ^= PARENB; 避免了这个罕见的问题。 2)贴出调用xbee_read()和其他2个函数的代码。
  • 感谢@chux,你让我走上了仔细检查所有 c_cflags 的道路
  • "我总是读不到数据,得到-1的错误。" -- 那你需要访问全局变量errno来获取错误情况的详细信息。根本问题是您使用的是非阻塞模式。见stackoverflow.com/questions/1613916/…

标签: c++ c arduino serial-port xbee


【解决方案1】:

我发现问题在于我如何声明 c_cflags。 Xbee 需要以原始模式读取,因此我只使用了 cfmakeraw(),而不是自己设置标志。但是我仍然不确定我到底做错了什么,或者用第三方程序打开端口是如何帮助连接的。

int xbee_init (char *port, struct termios *tty) {

    int fd=open(port,O_RDWR | O_NOCTTY | O_NONBLOCK);

    if(fd == -1){return 0;}//should be something better
    else {
        if(tcgetattr(fd, tty)!=0){return 0;}
        else{
                // cfsetospeed(tty, B57600);
                // cfsetispeed(tty, B57600);

                // tty->c_cflag &= ~PARENB;
                // tty->c_cflag &= ~CSTOPB;
                // tty->c_cflag &= ~CSIZE;
                // tty->c_cflag |= CS8;
                // tty->c_cflag &= ~CRTSCTS; 
                // tty->c_cflag |= CLOCAL | CREAD;
                // // tty->c_cflag |= PARENB;
                // // tty->c_cflag ^= PARENB;

                // tty->c_iflag |= IGNPAR | IGNCR;
                // tty->c_iflag &= ~(IXON | IXOFF | IXANY);
                // tty->c_lflag |= ICANON;
                // tty->c_oflag &= ~OPOST;

                cfmakeraw(&tty);
                cfsetispeed(&tty, B57600);

                tcsetattr(fd, TCSANOW, &tty);

                }
            }

    return fd;
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-09
  • 2015-04-14
  • 1970-01-01
  • 2021-06-13
  • 2017-03-22
  • 1970-01-01
相关资源
最近更新 更多