目的是实现电脑端(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 <stdio.h> /* Standard input/output definitions */#include <string.h> /* String function definitions */#include <unistd.h> /* UNIX standard function definitions */#include <fcntl.h> /* File control definitions */#include <errno.h> /* Error number definitions */#include <termios.h> /* 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);}新闻热点
疑难解答