Не может прочитать последовательные данные, если порт не открыт сторонней программой

Я пытаюсь прочитать данные с 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 через последовательный порт и публикации их в теме /xbee с частотой 10 Гц.

#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_cflags. Xbee нужно читать в режиме raw, поэтому вместо того, чтобы устанавливать флаги самостоятельно, я просто использовал 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;
}
Другие вопросы по тегам