news 2026/6/6 8:27:03

保姆级教程:用STM32精英板和ROS Kinetic搞定串口通信(附完整工程文件)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
保姆级教程:用STM32精英板和ROS Kinetic搞定串口通信(附完整工程文件)

从零开始搭建STM32与ROS串口通信系统:30分钟实战指南

在机器人开发领域,嵌入式系统与上层控制系统的通信是核心技术难点之一。本文将手把手教你如何用正点原子STM32精英板ROS Kinetic建立稳定的串口通信链路,即使你从未接触过ROS或嵌入式开发,也能在30分钟内完成第一个通信demo。

1. 硬件准备与环境搭建

1.1 所需硬件清单

  • 主控板:正点原子STM32精英板(兼容F103系列)
  • 通信模块:CH340G芯片的USB转TTL模块(PL2303等兼容)
  • 连接线材:杜邦线若干(建议使用不同颜色区分)
  • 开发环境
    • Windows端:Keil MDK-ARM 5.x
    • Linux端:Ubuntu 16.04 + ROS Kinetic

注意:购买USB转TTL模块时,务必确认其支持3.3V电平,避免损坏STM32芯片。

1.2 硬件连接示意图

正确的接线方式是通信成功的前提,以下是典型连接方案:

STM32引脚TTL模块接口连接说明
PA9(TX)RX交叉连接
PA10(RX)TX交叉连接
GNDGND共地连接
# Linux下检测设备是否识别成功 ls /dev/ttyUSB* # 预期输出:/dev/ttyUSB0

若未出现设备节点,可能需要安装CH340驱动:

sudo apt-get install build-essential sudo apt-get install linux-headers-$(uname -r) sudo modprobe usbserial sudo modprobe ch341

2. 软件环境配置

2.1 STM32工程配置

在Keil中新建工程时,关键配置如下:

  1. 选择正确的芯片型号:STM32F103ZET6
  2. 启用USART1外设:
    • 波特率:115200
    • 数据位:8位
    • 停止位:1位
    • 无校验位
// 串口初始化代码片段 void uart_init(u32 bound){ // GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); USART_InitStructure.USART_BaudRate = bound; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); }

2.2 ROS功能包创建

在Ubuntu终端中执行以下命令序列:

# 创建工作空间 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/ catkin_make # 创建功能包 cd src catkin_create_pkg stm32_comm roscpp std_msgs # 安装依赖 sudo apt-get install ros-kinetic-serial

3. 通信协议设计

3.1 帧结构定义

一个健壮的通信协议需要包含以下要素:

| 帧头(2B) | 长度(1B) | 数据(NB) | 校验(1B) | 帧尾(2B) |

典型实现方案:

// STM32端协议定义 #pragma pack(1) typedef struct { uint8_t header[2]; // 0x55 0xAA uint8_t length; // 数据域长度 int16_t left_vel; // 左轮速度 int16_t right_vel; // 右轮速度 uint8_t ctrl_flag; // 控制标志位 uint8_t checksum; // CRC8校验 uint8_t ender[2]; // 0x0D 0x0A } CommFrame; #pragma pack()

3.2 CRC校验实现

// ROS端的CRC8校验函数 unsigned char getCrc8(unsigned char *ptr, unsigned short len) { unsigned char crc = 0; while(len--) { crc ^= *ptr++; for(unsigned char i = 0; i < 8; i++) { if(crc & 0x01) crc = (crc >> 1) ^ 0x8C; else crc >>= 1; } } return crc; }

4. 双向通信实现

4.1 STM32数据收发

在STM32中实现中断接收和主动发送:

// 接收中断服务函数 void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { uint8_t ch = USART_ReceiveData(USART1); // 协议解析处理... USART_ClearITPendingBit(USART1, USART_IT_RXNE); } } // 数据发送函数 void send_to_ros(int16_t v1, int16_t v2, uint8_t flag) { CommFrame frame; frame.header[0] = 0x55; frame.header[1] = 0xAA; frame.length = 5; // 2+2+1 frame.left_vel = v1; frame.right_vel = v2; frame.ctrl_flag = flag; frame.ender[0] = 0x0D; frame.ender[1] = 0x0A; uint8_t *p = (uint8_t*)&frame; frame.checksum = getCrc8(p+2, frame.length+1); // 计算校验 for(int i=0; i<sizeof(CommFrame); i++) { while(!(USART1->SR & USART_SR_TXE)); USART_SendData(USART1, p[i]); } }

4.2 ROS节点实现

创建serial_node.cpp实现与STM32的通信:

#include <ros/ros.h> #include <serial/serial.h> serial::Serial ser; void callback(const std_msgs::String::ConstPtr& msg) { ROS_INFO("Sending: %s", msg->data.c_str()); ser.write(msg->data); } int main(int argc, char** argv) { ros::init(argc, argv, "serial_node"); ros::NodeHandle nh; 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("Unable to open port"); return -1; } ros::Subscriber sub = nh.subscribe("stm32_command", 1000, callback); ros::Publisher pub = nh.advertise<std_msgs::String>("stm32_feedback", 1000); while(ros::ok()) { if(ser.available()) { std_msgs::String result; result.data = ser.read(ser.available()); pub.publish(result); } ros::spinOnce(); } }

5. 调试技巧与常见问题

5.1 权限问题解决方案

每次重新插拔USB设备后都需要重新设置权限:

# 永久解决方案(创建udev规则) echo 'KERNEL=="ttyUSB*", MODE="0666"' | sudo tee /etc/udev/rules.d/50-stm32.rules sudo service udev restart

5.2 通信故障排查步骤

  1. 物理层检查

    • 确认TX-RX交叉连接
    • 测量USB转TTL模块供电电压(3.3V)
  2. 端口检测

    # 查看端口信息 dmesg | grep tty # 测试端口通信 cat /dev/ttyUSB0
  3. 协议分析

    • 使用逻辑分析仪抓取波形
    • 在STM32端添加LED指示灯辅助调试

5.3 性能优化建议

  • 增加超时重传机制
  • 实现数据分包处理
  • 添加心跳包检测连接状态
  • 使用DMA传输减轻CPU负担

在完成所有步骤后,你应该能在ROS中看到来自STM32的实时数据流,同时可以通过ROS话题向STM32发送控制指令。这种通信框架可扩展应用于机器人运动控制、传感器数据采集等多种场景。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/6 8:22:26

汽车网络安全中的后量子密码技术应用与挑战

1. 汽车网络安全中的后量子密码技术概述 量子计算的发展正在重塑整个网络安全格局。传统公钥加密算法如RSA和ECC&#xff08;椭圆曲线加密&#xff09;的安全性建立在特定数学难题&#xff08;如大整数分解和离散对数问题&#xff09;的复杂性基础上。然而&#xff0c;量子计算…

作者头像 李华
网站建设 2026/6/6 8:21:59

工业平行宇宙:06 品牌大乱斗:Siemens、ABB、PTC、国产

06 品牌大乱斗:Siemens、ABB、PTC、国产 前五篇咱们从虚拟老哥的“出生证”聊到“怎么预测优化共舞”,今天直接上擂台——四大品牌甩开膀子比,谁家的数字孪生最接地气、最省钱、最能让咱们啤酒厂的虚拟版“咕嘟咕嘟”跑得欢?Siemens老大哥严谨靠谱、ABB机器人王实操猛、PT…

作者头像 李华
网站建设 2026/6/6 8:20:33

别再为USB发愁了!手把手教你用沁恒CH9350将刷卡机数据‘变’成串口

用CH9350实现刷卡机数据到串口的无缝转换&#xff1a;从硬件连接到数据解析全指南在嵌入式开发中&#xff0c;USB设备集成常常让开发者头疼不已——驱动程序兼容性问题、协议栈的复杂性、不同操作系统的差异&#xff0c;这些都可能成为项目推进的绊脚石。而当我们面对刷卡机这类…

作者头像 李华
网站建设 2026/6/6 8:15:14

GitHub Actions与Jenkins在2025 DevOps流水线中的本质差异与选型逻辑

1. 这不是选工具&#xff0c;而是选“呼吸节奏”&#xff1a;2025年DevOps流水线的真实生存状态 你打开CI/CD配置文件时&#xff0c;第一反应是写 workflow_dispatch 还是 pipeline { agent any } &#xff1f;不是在纠结语法&#xff0c;而是在下意识匹配自己团队的“呼吸…

作者头像 李华