ROS和STM32实现串口通信

2023-05-16

前言

        实现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; //接收状态标志清零
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ROS和STM32实现串口通信 的相关文章

  • qt-5串口与通讯

    文章目录 文章目录 一 串口通讯 二 实现串口通讯 1 在头文件中引入 QtSerialPort 类的两个头文件 xff08 必须引入 xff09 2 在工程文件中添加以下代码 3 在头文件中定义全局的串口对象 4 相关配置 5 通过一个按
  • qt-5数据库使用

    文章目录 目录 前言 一 所需要的头文件 二 数据库操作 1 addDatabase的函数原型如下 2 连接数据库 3 创建数据库表 4 插入数据到表中 5 更新表中的数据 总结 前言 例如 xff1a qt 5 创建数据库 xff0c 创
  • 利用MapReduce算法实现统计分析(单词统计,或者关键词统计)实验报告

    本文相关idea的代码出自 xff1a https blog csdn net weixin 38468167 article details 108658531 实验内容 xff1a 开发MapReduce算法 xff0c 实现统计分析
  • linux chomd 有何作用

    96 chmod 96 是 Linux 用来更改文件或目录权限的命令 它允许你控制文件和目录的访问权限 xff0c 决定文件 目录能否被用户读取 写入 执行的权限 具体说 xff0c chmod 可以更改 owner group 和 oth
  • 缓存同步-Canal

    目录 安装Canal 监听Canal 项目中对于canal的应用 应用场景 项目测试 场景 xff1a 缓存不是设置了有效期吗 xff0c 说明在有效期范围内数据是一直在的 xff0c 那么当数据库中的数据发送改变 xff0c 那么缓存还是
  • 对Redis布隆过滤器的实现

    目录 实现思路 首先最重要的自定义hash 然后就是将key放入bitSet 然后就是判断布隆过滤器bitSet数组中是否含有对应的key 代码 实现思路 39条消息 Redis布隆过滤器 Fairy要carry的博客 CSDN博客 首先最
  • fork()函数详解

    目录 1 基本了解 xff1a 2 fork函数的了解 xff1a 3 僵死进程 xff1a 4 fork和多线程 xff1a 1 多线程中某个线程调用 fork xff0c 子进程会有和父进程相同数量的线程吗 xff1f 2 父进程被加锁
  • 一阶线性自抗扰控制的整定

    摘要 线性自抗扰控制 linear active disturbance rejection control LADRC 是解决系统外部不可测扰动和内部未知不确定性的一种新型控制方法 其精髓是将系统的不确定性转化为一个可观测的状态 利用扩张
  • 单目视觉SLAM综述

    摘要 单目视觉SLAM因单目相机体积小 功耗低 信息获取丰富受到了广泛使用 为了深入分析单目视觉SLAM的优势 首先 简述单目视觉SLAM的基本原理 从特征点检测 相机姿态估计 选取关键帧 创建地图 地图及相机姿态优化 闭环检测等方面总结S
  • idea 修改 JDK 版本

    idea 修改 JDK 版本 第一步 xff1a 修改环境变量 xff08 修改成你需要的 JDK 版本 xff09 第二步 xff1a IDEA中的修改 导入Jdk进IDEA 第三步 xff1a 修改项目的sdk 第四步 xff1a 修改
  • Jmeter性能测试(13)--常见问题及解决方法

    jmeter作为一个开源的纯Java性能测试工具 xff0c 工作中极大的方便了我们进行接口 性能测试 xff0c 但使用过程中也遇到了很多的问题 xff0c 下面就记录一下自己遇到的问题 xff0c 后续会不断更新 1 获取日志 在使用j
  • C++的基础语法知识

    目录 一 认识C 43 43 1 如C语言 C 43 43 C Python等语言 xff0c 为什么会有这么多语言存在 xff1f 2 C 43 43 解决了什么问题 xff1f 3 什么是面向对象 xff1f 4 C 43 43 的特性
  • 基于遗传算法车辆路径问题(VRP)

    一 车辆路径问题简介与求解要求 交通运输是国民经济的动脉 xff0c 各种运输方式在日常运输营运管理工作中都要面对这样一个共同的问题 xff1a 如何为载运工具 汽车 xff0c 列车 xff0c 轮船和飞机 xff0c 统称为车辆 确定行
  • docker 安装(centos7虚拟机)

    Docker xff0c 翻译过来就是码头工人 Docker是一个开源的应用容器引擎 xff0c 让开发者可以打包他们的应用以及依赖包到一个可抑制的容器中 xff0c 然后发布到任何流行的Linux机器上 xff0c 也可以实现虚拟化 容器
  • java 死锁产生的四个必要条件

    1 互斥使用 xff0c 即当资源被一个线程使用 占有 时 xff0c 别的线程不能使用 2 不可抢占 xff0c 资源请求者不能强制从资源占有者手中夺取资源 xff0c 资源只能由资源占有者主动释放 3 请求和保持 xff0c 即当资源请
  • JS-数组和函数冒泡排序递归函数

    数组和函数 数组 计算数组中所有元素的和 span class token comment 定义数组 span span class token keyword var span nums span class token operator
  • Redis的Java客户端

    1 快速入门 Jedis使用的基本步骤 xff1a 1 引入依赖 2 创建Jedis对象 xff0c 建立连接 3 使用Jedis xff0c 方法名与Redis命令一致 4 释放资源 lt jedis依赖 gt lt dependency
  • Winform

    自适应窗口布局 OnLayout 窗口在尺寸变化时 会调用OnLayout方法 所以 在form1 cs文件里重写OnLayout方法即可实现自适应 在OnLayout方法中 我们获取一下窗口的宽度和高度 根据窗口的宽度和高度重新设定控件的
  • STM32读取串口传感器数据(颗粒物传感器,主动上传)

    文章目录 1 开发板选择 用到的资源 2 串口通信 xff08 个人理解 xff09 3 代码分析 xff08 注释比较详细 xff09 1 主函数2 串口1配置3 串口2配置以及中断函数 4 注意问题5 源码链接 1 开发板选择 我用的是
  • STM32+Zigbee模块实现串口通信获取传感器数据

    文章目录 1 所用的资源2 Zigbee模块简介3 STM32板上用到的资源4 代码部分 1 所用的资源 1 两个Zigbee透传模块 2 两块32板 xff08 我手上的是VET6和RCT6的两块板子 xff09 xff0c 其它的板子也

随机推荐