ROS与STM32串口通信实现指南

前言

        实现ubuntu系统下的ROS和STM32完成串口数据收发。

硬件

一、硬件设备

        STM32F103ZE

        ubuntu18.04

二、硬件连接

        STM32串口 + TTL转USB模块(CH340)+ ubuntu18.04

        说明:TTL转USB模块连接:RX接串口TX,TX接串口RX,GND接GND

三、驱动安装

        1. 查看ubuntu对USB转串口设备的支持,看是否有ch340或ch34x

# lsmod | grep usbserial

        2. 查看当前串口

# ls -l /dev/ttyUSB*

        3. 给对应串口权限

sudo chmod 777 /dev/ttyUSB0(这里串口根据自己串口修改)

ROS

一、在ROS工作空间下创建功能包

catkin_ws/src# catkin_create_pkg serial_port roscpp std_msgs geometry_msgs

二、添加串口通信程序

        1. serial_port.cpp

#include <ros/ros.h>
#include <ros/time.h>
#include <geometry_msgs/TransformStamped.h>
#include <tf/transform_broadcaster.h>
#include <nav_msgs/Odometry.h>
#include <boost/asio.hpp>
#include <geometry_msgs/Twist.h>
#include "../include/serial_port.h"

using namespace std;
using namespace boost::asio;
//串口相关对象
boost::asio::io_service iosev;
boost::asio::serial_port sp(iosev, "/dev/ttyUSB0");     //串口号
boost::system::error_code err;

/********************************************************
            串口发送接收相关常量、变量、共用体对象
********************************************************/
const unsigned char ender[2] = {0x0d, 0x0a};           //尾部
const unsigned char header[2] = {0x55, 0xaa};          //头部

/**
 * 函数功能:串口参数初始化
 * 入口参数:无
 * 出口参数:void
*/

void serialInit()
{
    sp.set_option(serial_port::baud_rate(115200));      //串口波特率
    sp.set_option(serial_port::flow_control(serial_port::flow_control::none));
    sp.set_option(serial_port::parity(serial_port::parity::none));
    sp.set_option(serial_port::stop_bits(serial_port::stop_bits::one));
    sp.set_option(serial_port::character_size(8));    
}

/**
 * 函数功能:串口发送数据
 * 入口参数:unsigned char类型数组(以0x7b开头,以0x7d,0x0d,0x0a结尾)
 * 出口函数:bool类型 
*/
bool writeData()
{
    //测试数据
    unsigned char buff[15] = {0x7b, 0xaa, 0x11, 0x12, 0x11, 0x11, 0x11, 0x0d, 0x0a}; 
    // 通过串口下发数据
    boost::asio::write(sp, boost::asio::buffer(buff));
    return true;
}

/**
 * 函数功能:串口接收数据
 * 入口参数:void
 * 出口参数:bool类型
*/
bool readData()
{
    unsigned char buff[11]={0};
    uint8_t buffer[11]={0};
    //此段代码可以读数据的结尾,进而来进行读取数据的头部
    try
    {
        boost::asio::streambuf response;
        boost::asio::read_until(sp, response, "",err);   
        copy(istream_iterator<unsigned char>(istream(&response)>>noskipws),
        istream_iterator<unsigned char>(),
        buff); 
    }  
    catch(boost::system::system_error &err)
    {
        ROS_INFO("read_until error");
    }
    //buffer = buff[0];
    for(int i = 0; i < sizeof(buffer); i++)
    {
        buffer[i] = buff[i];
        ROS_INFO("buffer[%d]: %d", i, buffer[i]);
    }
    return true; 
}

        2. serial_node.cpp

#include "ros/ros.h"
#include "std_msgs/String.h"  
#include "../include/serial_port.h"

int main(int agrc,char **argv)
{
    ros::init(agrc,argv,"public_node");
    ros::NodeHandle nh;

    ros::Rate loop_rate(10);
    
    //串口初始化
    serialInit();

    while(ros::ok())
    {
        ros::spinOnce();
        //向STM32端发送数据
        writeData();
        //从STM32接收数据
        readData();
        
    }
    return 0;
}

STM32

        1. 通过串口中断来接收数据

        usart.c文件

uint8_t STR_RX[200];        //定义接收数据数组
u16 STR_RX_NUM;
//接收以0x0d 0x0a结尾的数据
void USART1_IRQHandler(void)                	//串口1中断服务函数
	{
	u8 Res;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
		{
		Res =USART_ReceiveData(USART1);	    //读取接收到的数据
		
		if((USART_RX_STA&0x8000)==0)    //接收未完成
			{
			if(USART_RX_STA&0x4000) //接收到0x0d
				{
				if(Res!=0x0a)USART_RX_STA=0; //接收不是0x0a表示接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成
				}
			else //还没收到oxod
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
					{
						USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
						STR_RX[STR_RX_NUM] = Res;    //消息存入数组
						USART_RX_STA++;
						STR_RX_NUM++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误重新接收
					}		 
				}
			}   		 
     } 
} 

        2. 串口发送数据

        main.c

if(USART_RX_STR&0x8000)
{
    for(t=0; t <STR_RX_NUM; t++)
    {
        USART_SendData(USART1, STR_RX[t]);
	    while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET); //等待数据发送完成
    }
    STR_RX_NUM = 0; //接收字符串大小清零
    USART_RX_STR = 0; //接收状态标志清零
}

作者:夜酱ovo

物联沃分享整理
物联沃-IOTWORD物联网 » ROS与STM32串口通信实现指南

发表评论