目的是實現電腦端(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);
|
新聞熱點
疑難解答