linux ROS串口读取的问题

目的是实现电脑端(ubuntu系统)与STM32通过串口建立通讯,STM32解算与其连接的传感器并将数据传送至电脑端进行编程。我们知道,随便一个串口助手即可实现读取STM32串口数据并显示出来,关于串口的API也很多,ROS 就有现成的rosserial包可以调用,本来的想法是直接调用该包就可以取到数据了,谁知遇到一个意想不到的问题:读取的数据存在数据分段的情况,出现原因可能是电脑端读取数据的速度太快了。该程序如下:

#include <ros/ros.h> 
#include <serial/serial.h>  //ROS已经内置了的串口包 
#include <std_msgs/String.h> 
#include <std_msgs/Empty.h> 

serial::Serial ser; //声明串口对象 

//回调函数 
void write_callback(const std_msgs::String::ConstPtr& msg) 
{ 
    ROS_INFO_STREAM("Writing to serial port" <<msg->data); 
    ser.write(msg->data);   //发送串口数据 
} 

int main (int argc, char** argv) 
{ 
    //初始化节点 
    ros::init(argc, argv, "serial_example_node"); 
    //声明节点句柄 
    ros::NodeHandle nh; 

    //订阅主题,并配置回调函数 
    ros::Subscriber write_sub = nh.subscribe("write", 1000, write_callback); 
    //发布主题 
    ros::Publisher read_pub = nh.advertise<std_msgs::String>("read", 1000); 

    try 
    { 
    //设置串口属性,并打开串口 
        ser.setPort("/dev/ttyUSB0"); 
        ser.setBaudrate(115200); 
        serial::Timeout to = serial::Timeout::simpleTimeout(1000); 
        ser.setTimeout(to); 
        ser.open(); 
    } 
    catch (serial::IOException& e) 
    { 
        ROS_ERROR_STREAM("Unable to open port "); 
        return -1; 
    } 

    //检测串口是否已经打开,并给出提示信息 
    if(ser.isOpen()) 
    { 
        ROS_INFO_STREAM("Serial Port initialized"); 
    } 
    else 
    { 
        return -1; 
    } 

    //指定循环的频率 
    ros::Rate loop_rate(50); 
    while(ros::ok()) 
    { 

        if(ser.available()){ 
            ROS_INFO_STREAM("Reading from serial port\n"); 
            std_msgs::String result; 
            result.data = ser.read(ser.available()); 
            ROS_INFO_STREAM("Read: " << result.data); 
            read_pub.publish(result); 
        } 

        //处理ROS的信息,比如订阅消息,并调用回调函数 
        ros::spinOnce(); 
        loop_rate.sleep(); 

    } 
} 

网址:http://bbs.csdn.net/topics/110069436出现了这种情况以及大家给的分析和建议。按照建议改变了Timeout时间仍无效果。

索性找找关于linux串口的程序,多数代码都会出现数据分段的情况,庆幸的是找到一个没有分段的情况,程序没有好好阅读,能实现串口读数且无错误就行。代码如下:

#include  /* Standard input/output definitions */
#include  /* String function definitions */
#include  /* UNIX standard function definitions */
#include  /* File control definitions */
#include  /* Error number definitions */
#include  /* POSIX terminal control definitions */

/*
 * @brief Open serial port with the given device name
 *
 * @return The file descriptor on success or -1 on error.
 */
int open_port(char *port_device)
{
    int fd; /* File descriptor for the port */

    fd = open(port_device, O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1)
    {
        perror("open_port: Unable to open /dev/ttyS0 - ");
    }
    else
        fcntl(fd, F_SETFL, 0);

    return (fd);
}

int main()
{
    struct termios options;

    int fd=open_port("/dev/ttyACM0");
    if(fd==-1){
        return -1;
    }

    tcgetattr(fd, &options);


    //Set the baud rates to 38400...
    cfsetispeed(&options, B38400);
    cfsetospeed(&options, B38400);


    //Enable the receiver and set local mode...
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~CSIZE; /* Mask the character size bits */
    options.c_cflag |= CS8; /* Select 8 data bits */

    //No parity
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;


    //Set the new options for the port...
    tcsetattr(fd, TCSANOW, &options);

    int ax,ay,az,gx,gy,gz;
    char buf[1024];
    char* pos=buf;

    while(1){
        ssize_t n=read(fd, pos, 1);
        if(n==1){
            if(*pos=='\n' ){
                *(pos+1)=0;
                sscanf(buf,"%d,%d,%d,%d,%d,%d", &ax, &ay, &az, &gx, &gy, &gz);
                printf("acc/gyro: %d %d %d %d %d %d\n", ax, ay, az, gx, gy, gz);
                pos=buf;
            }else{
                pos++;
            }
        }
    }


    close(fd);
}

你可能感兴趣的:(linux,机器人导航)