新闻详情

新闻详情

首页 / 资讯中心 / 详情

STM32F407接入ROS2实战:micro_ros传输层选型与通信实现

发布时间:2026/9/28 13:57:32来源:尧图网络
STM32F407接入ROS2实战:micro_ros传输层选型与通信实现
ROS2 生态里最让人头疼的环节从来不是写节点逻辑而是怎么让那些跑在 MCU 上的传感器、执行器真正融入 DDS 的通信网络。STM32F407 这颗芯片在工业控制和机器人底层驱动里出镜率极高但它的资源跑不动完整的 ROS2 客户端库过去大家要么用串口自定义协议硬扛要么干脆把 MCU 当成一个哑设备。micro_ros 的出现改变了这个局面——它把 ROS2 的通信能力裁剪到能在几十 KB 内存里运行让 F407 这种级别的芯片也能直接发布话题、订阅指令、甚至提供 Service 服务。这篇内容面向的是已经有一定 STM32 开发基础、想把手里的板子接入 ROS2 网络的嵌入式工程师我会从传输层选型一路讲到实际跑通话题通信的完整过程把踩过的坑和验证过的配置都摊开来说。1. 为什么 F407 接入 ROS2 值得认真做传输层选型1.1 micro_ros 在 F407 上的资源账本STM32F407 的典型配置是 192KB SRAM、1MB Flash主频 168MHz带 FPU 和 DSP 指令集。这个资源放在裸机开发里相当宽裕但 micro_ros 的默认配置会吃掉不少内存。我实测过几个关键数字micro_ros 的 rcl 层加上 rmw_microxrcedds 中间件在只启用一个话题发布者的情况下静态内存占用大约在 12KB 到 18KB 之间具体取决于消息类型的大小和 XRCE-DDS 的会话缓冲区配置。如果再加上一个订阅者和一个 Service 服务端内存会逼近 30KB。这还没算上用户自己的应用逻辑和协议栈。所以第一件事就是算清楚你的内存预算。F407 的 192KB SRAM 分成了 112KB 16KB 64KB 三个区域其中 64KB 是 CCM RAM只能通过 CPU 内核总线访问DMA 用不了。micro_ros 的缓冲区如果放在 CCM 里网络外设的 DMA 就没法直接搬运数据这一点在配置链接脚本的时候必须注意。我的做法是把 micro_ros 的堆和会话缓冲区放在主 SRAM 区把用户自己的大数据缓冲区放到 CCM 里各取所需。另一个容易被忽略的是 Flash 占用。micro_ros 的静态库加上 XRCE-DDS 的代码编译出来大概在 80KB 到 120KB 之间取决于你启用了多少种消息类型。F407 的 1MB Flash 完全够用但如果你用的是 F407VET6 这种 512KB 的版本就要留意别把消息类型开得太杂。1.2 三种传输方式的真实对比micro_ros 支持多种传输层在 F407 上最常用的是串口UART、UDP over Ethernet 和 CAN。这三种方式我都在实际项目里用过各自的适用场景差别很大。传输方式典型延迟带宽硬件复杂度适用场景UART1-5ms115200-921600bps极低点对点、调试、低频率传感器UDP over Ethernet0.5-2ms10/100Mbps中需 PHY多节点、高频数据、图像传输CAN2-10ms1Mbps中需收发器工业现场、多节点总线、抗干扰串口方式最简单一根 USB-TTL 就能把 F407 和跑 ROS2 的上位机连起来。但串口的带宽是硬伤115200bps 下每秒最多传十几KB的有效载荷稍微大一点的消息类型就会堵。而且串口是点对点的一个 F407 只能连一个上位机多节点场景下需要多个串口或者用 USB Hub 扩展。以太网方式是我最推荐的。F407 自带 MAC 控制器配合 RMII 接口的 PHY 芯片比如 LAN8720 或 DP83848就能跑 100Mbps。UDP 传输的延迟低、带宽大而且天然支持多节点——每个 F407 分配一个 IP上位机通过同一个网段就能和所有节点通信。代价是硬件上要多画一个 PHY 电路RMII 的时钟线要走等长50MHz 的 REF_CLK 对布线有一定要求。CAN 方式适合工业现场。F407 有两个 CAN 控制器配合 6N137 或者 ADuM1201 隔离收发器就能组网。CAN 的抗干扰能力强总线长度可以到几十米甚至上百米但带宽只有 1Mbps而且 micro_ros 的 CAN 传输层实现相对复杂需要自己处理帧的分片和重组。1.3 选型决策的实际依据我的建议是如果你只是做单节点验证或者低频传感器采集串口足够如果你要做多节点协同或者有视频、点云这类大数据流直接上以太网如果现场环境电磁干扰严重、节点分散在几十米范围内选 CAN。这里有个实际经验很多人一开始图省事用串口结果项目做到一半发现带宽不够再换以太网就要重新画板、改代码。所以如果你对项目的最终形态有预期传输层选型要提前想清楚。我现在的习惯是只要板子上有以太网 PHY就优先用以太网串口只留作调试和固件升级用。2. 从零搭建 micro_ros 的交叉编译环境2.1 工具链的版本匹配问题micro_ros 的编译依赖 ROS2 的构建系统所以第一步是在 Ubuntu 上装好 ROS2。我用的版本是 Humble对应 Ubuntu 22.04。这里有个坑micro_ros 的各个版本和 ROS2 发行版有严格的对应关系Humble 对应的是 micro_ros 的 humble 分支如果你混用了 Foxy 的 micro_ros 和 Humble 的 ROS2编译能过但运行时会出各种奇怪的通信问题。安装 ROS2 Humble 的步骤网上很多这里只强调几个关键点。首先是 locale 设置如果locale命令输出的不是en_US.UTF-8ros2 的命令行工具会报编码错误。其次是源的选择用官方源还是国内镜像源会影响下载速度但不要混用。最后是rosdep的初始化这一步如果卡住后面编译 micro_ros 时会找不到依赖。# 检查 locale locale # 如果不是 en_US.UTF-8执行 sudo apt update sudo apt install locales sudo locale-gen en_US en_US.UTF-8 sudo update-locale LC_ALLen_US.UTF-8 LANGen_US.UTF-8 export LANGen_US.UTF-8装完 ROS2 之后还需要安装 micro_ros 的构建工具micro_ros_setup。这个工具提供了一系列脚本可以自动下载 micro_ros 的源码、配置工具链、编译静态库。# 创建工作空间 mkdir -p ~/microros_ws/src cd ~/microros_ws # 下载 micro_ros_setup git clone -b humble https://github.com/micro-ROS/micro_ros_setup.git src/micro_ros_setup # 安装依赖 rosdep update rosdep install --from-paths src --ignore-src -y # 编译 colcon build source install/local_setup.bash2.2 交叉编译工具链的配置F407 是 ARM Cortex-M4 内核需要 arm-none-eabi 工具链。Ubuntu 的 apt 源里有gcc-arm-none-eabi但版本可能比较老。我建议从 ARM 官网下载最新的工具链解压后把bin目录加到 PATH 里。# 下载工具链以 10.3-2021.10 为例 wget https://developer.arm.com/-/media/Files/downloads/gnu-rm/10.3-2021.10/gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2 tar -xjf gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2 export PATH$PATH:$(pwd)/gcc-arm-none-eabi-10.3-2021.10/bin # 验证 arm-none-eabi-gcc --version接下来用micro_ros_setup创建 F407 的固件工作空间。这里需要指定工具链文件micro_ros 提供了stm32f4的参考配置但实际项目中往往需要根据自己的板子调整。# 创建固件工作空间 ros2 run micro_ros_setup create_firmware_ws.sh # 配置工具链 ros2 run micro_ros_setup configure_firmware.sh # 编译 ros2 run micro_ros_setup build_firmware.shconfigure_firmware.sh会交互式地询问传输方式、消息类型等配置。如果你用的是自定义板子需要修改firmware/mcu_ws/下的colcon.meta文件调整各个包的编译选项。2.3 自定义消息类型的处理micro_ros 默认只编译了一部分标准消息类型如果你要用自定义的.msg文件需要把它们放到firmware/mcu_ws/下并在colcon.meta里启用对应的包。这里有个细节自定义消息的依赖关系必须完整如果 A.msg 里引用了 B.msg两个都要放进去否则编译时会报找不到类型。我遇到过一个典型问题自定义消息里用了std_msgs/Header但colcon.meta里没有启用std_msgs编译能过但链接时会报未定义符号。解决办法是在colcon.meta里把std_msgs的rosidl_generator_c和rosidl_typesupport_microxrcedds_c都打开。{ names: { std_msgs: { cmake-args: [ -DBUILD_TESTINGOFF, -DROSIDL_GENERATOR_C_BUILD_TESTINGOFF ] }, my_custom_msgs: { cmake-args: [ -DBUILD_TESTINGOFF ] } } }编译完成后firmware/mcu_ws/install/下会生成静态库文件包括libmicroros.a和各个消息类型的库。把这些库和头文件拷贝到你的 STM32 工程里就可以在裸机代码里调用 micro_ros 的 API 了。3. STM32CubeMX 里的底层外设配置要点3.1 以太网外设的 RMII 配置如果你选的是以太网传输CubeMX 里的 ETH 配置有几个关键点。首先是 PHY 地址LAN8720 的默认地址是 0DP83848 是 1这个在HAL_ETH_Init里要设对。其次是 RMII 的 REF_CLKF407 的 PA1 引脚可以输出 50MHz 时钟给 PHY也可以由 PHY 提供时钟给 MCU。两种方式在 CubeMX 里的配置不同如果 MCU 输出时钟PA1 要配置为RCC_MCO1并选择 HSE 或 PLL 作为时钟源如果 PHY 提供时钟PA1 要配置为ETH_RMII_REF_CLK输入。我实际用 LAN8720 的时候遇到过 REF_CLK 配置错误导致 PHY 无法通信的问题。现象是HAL_ETH_Init返回HAL_ERROR用示波器量 PA1 没有 50MHz 信号。后来发现是 CubeMX 里 PA1 的复用功能选错了应该选ETH_RMII_REF_CLK而不是RCC_MCO1。这个细节在 CubeMX 的图形界面里不太直观需要点开 PA1 的引脚配置仔细看。MDIO 和 MDC 是管理接口用来读写 PHY 的寄存器。MDC 的时钟不能超过 2.5MHzCubeMX 里可以配置分频系数。我一般设成 HCLK/42168MHz 下大约是 4MHz稍微超了一点但实测没问题。如果 PHY 对 MDC 时钟敏感可以再降一档。3.2 串口和 DMA 的配合串口传输方式下DMA 是必须的。micro_ros 的串口传输层会频繁地读写数据如果用中断方式CPU 会被大量的小数据包打断影响实时性。我一般给 UART 配两个 DMA 通道一个用于 TX一个用于 RX都设成循环模式。CubeMX 里配置 UART DMA 的时候要注意 DMA 请求的映射关系。F407 的 USART1_TX 对应 DMA2 Stream7 Channel4USART1_RX 对应 DMA2 Stream5 Channel4。这个映射在参考手册的 DMA 请求映射表里有CubeMX 会自动处理但如果你手动改过 DMA 配置要确认一下没搞错。还有一个细节micro_ros 的串口传输层需要知道 UART 的句柄和 DMA 句柄。在microros_transports.h里你需要实现几个回调函数把 HAL 的 UART 操作和 micro_ros 的传输接口对接起来。bool cubemx_transport_open(struct uxrCustomTransport * transport) { // 启动 UART DMA 接收 HAL_UART_Receive_DMA(huart1, rx_buffer, RX_BUFFER_SIZE); return true; } bool cubemx_transport_write(struct uxrCustomTransport * transport, const uint8_t * buf, size_t len, uint8_t * err) { HAL_UART_Transmit_DMA(huart1, (uint8_t *)buf, len); return true; }3.3 时钟树和中断优先级F407 的时钟树配置直接影响 micro_ros 的定时器精度。ROS2 的话题通信依赖时间戳如果 MCU 的时钟不准上位机收到的消息时间戳会漂移。我一般把 HSE 设成 8MHz 外部晶振PLL 倍频到 168MHz这样 SysTick 的精度足够。中断优先级方面以太网的 ETH 中断和串口的 DMA 中断要设得比 SysTick 高否则通信数据可能会丢。但也不能设得太高否则会影响用户任务的执行。我的经验是ETH 中断设成优先级 5UART DMA 设成 6SysTick 设成 15最低用户任务用 FreeRTOS 的话任务优先级根据实际需求分配。这里有个容易踩的坑如果你用了 FreeRTOSmicro_ros 的默认配置可能和 FreeRTOS 的内存管理冲突。micro_ros 有自己的内存分配器如果和 FreeRTOS 的heap_4同时使用可能会出现内存碎片。解决办法是在colcon.meta里把 micro_ros 的内存分配器设成malloc让 FreeRTOS 统一管理堆。4. 跑通第一个话题通信的完整过程4.1 编写 micro_ros 节点代码在 STM32 工程里创建一个app.c文件实现一个简单的发布者节点。这个节点每隔 100ms 发布一条std_msgs/Int32消息内容是一个递增的计数器。#include rcl/rcl.h #include rclc/rclc.h #include rclc/executor.h #include std_msgs/msg/int32.h rcl_publisher_t publisher; std_msgs__msg__Int32 msg; rclc_executor_t executor; rclc_support_t support; rcl_allocator_t allocator; rcl_node_t node; rcl_timer_t timer; void timer_callback(rcl_timer_t * timer, int64_t last_call_time) { (void) last_call_time; if (timer ! NULL) { msg.data; rcl_publish(publisher, msg, NULL); } } void appMain(void * argument) { allocator rcl_get_default_allocator(); // 初始化支持结构 rclc_support_init(support, 0, NULL, allocator); // 创建节点 rclc_node_init_default(node, stm32f407_node, , support); // 创建发布者 rclc_publisher_init_default( publisher, node, ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32), stm32_counter); // 创建定时器 rclc_timer_init_default( timer, support, RCL_MS_TO_NS(100), timer_callback); // 创建执行器 rclc_executor_init(executor, support.context, 1, allocator); rclc_executor_add_timer(executor, timer); msg.data 0; // 主循环 while (1) { rclc_executor_spin_some(executor, RCL_MS_TO_NS(100)); // 这里可以加入用户自己的任务 } }这段代码的结构和 ROS2 的 C 节点很像只是 API 换成了 C 版本。rclc_executor_spin_some是非阻塞的每次调用处理一次执行器里的事件然后返回。这样用户可以在主循环里插入自己的逻辑不会因为 spin 阻塞而影响其他任务。4.2 上位机的 agent 配置micro_ros 的通信需要一个 agent 在上位机运行负责把 XRCE-DDS 协议转换成标准的 DDS 通信。agent 的安装很简单# 安装 micro_ros_agent sudo apt install ros-humble-micro-ros-agent # 串口方式启动 ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyUSB0 -b 115200 # 以太网方式启动 ros2 run micro_ros_agent micro_ros_agent udp4 --port 8888串口方式下--dev指定设备节点-b指定波特率。以太网方式下--port指定监听的 UDP 端口默认是 8888。agent 启动后会等待 MCU 的连接请求。这里有个实际经验agent 的启动顺序很重要。如果 MCU 先上电、agent 后启动MCU 会一直重连直到 agent 就绪。但如果 agent 先启动、MCU 后上电MCU 第一次连接就能成功。我一般先启动 agent再给 MCU 上电这样调试信息更清晰。4.3 验证通信是否正常agent 启动后另开一个终端用ros2 topic list查看话题列表。如果一切正常应该能看到/stm32_counter这个话题。然后用ros2 topic echo /stm32_counter查看消息内容应该能看到递增的整数。# 查看话题列表 ros2 topic list # 输出 # /parameter_events # /rosout # /stm32_counter # 查看消息内容 ros2 topic echo /stm32_counter # 输出 # data: 1 # --- # data: 2 # ---如果ros2 topic list看不到话题先检查 agent 的日志输出。agent 会打印连接状态和错误信息常见的错误包括波特率不匹配、串口设备权限不足、UDP 端口被占用等。串口权限问题可以用sudo usermod -aG dialout $USER解决然后重新登录。以太网方式下如果 agent 收不到数据先ping一下 MCU 的 IP确认网络层是通的。然后检查防火墙有没有挡住 UDP 8888 端口。我遇到过 Ubuntu 的 ufw 默认规则挡住了 UDP 包sudo ufw allow 8888/udp就好了。5. 实际项目中绕不开的几个坑5.1 内存溢出导致的随机崩溃micro_ros 的内存分配失败不会立刻崩溃而是会在某个不确定的时刻触发 HardFault。这种问题最难查因为崩溃点往往和真正的内存耗尽点隔了很远。我的排查方法是在colcon.meta里打开 micro_ros 的内存调试选项让它在分配失败时打印日志。{ names: { rmw_microxrcedds: { cmake-args: [ -DRMW_MICROXRCEDDS_DEBUGON ] } } }打开调试后如果内存分配失败串口会打印类似Failed to allocate memory的日志。这时候就要检查你的缓冲区配置了。micro_ros 的几个关键缓冲区大小在microros_allocators.h里定义包括XRCE_BUFFER_SIZE、XRCE_HISTORY_SIZE等。默认值偏小如果消息类型比较大或者发布频率高需要适当调大。我的一般配置是XRCE_BUFFER_SIZE设成 2048XRCE_HISTORY_SIZE设成 4XRCE_MAX_TOPICS设成 8。这样在 F407 上跑两三个话题的发布订阅没问题。如果还要加 ServiceXRCE_MAX_SERVICES也要相应调大。5.2 时间同步的精度问题ROS2 的消息时间戳默认来自 MCU 的 SysTick但 SysTick 的精度受晶振影响。如果 MCU 用的是内部 RC 振荡器时间戳漂移会很明显上位机做数据融合时会出问题。解决办法是外接晶振并且在 micro_ros 里启用时间同步。micro_ros 支持从 agent 同步时间需要在rclc_support_init之后调用rmw_uros_sync_session。这个函数会向 agent 请求当前时间然后计算 MCU 时间和 agent 时间的偏移量。之后发布的消息时间戳会自动加上这个偏移量。// 同步时间超时 1000ms rmw_uros_sync_session(1000);实测下来同步一次之后时间戳的误差可以控制在几毫秒以内。如果 MCU 的晶振精度高同步一次可以管很久如果晶振精度差建议每隔几分钟重新同步一次。5.3 以太网 PHY 的硬件调试以太网方式下PHY 的硬件调试是最容易卡住的地方。我遇到过几种典型问题PHY 的复位引脚没接对、RMII 的差分线走线太长导致信号质量差、PHY 的地址配置错误。排查 PHY 问题的第一步是量时钟。用示波器看 REF_CLK 引脚有没有 50MHz 信号如果没有检查 MCU 的时钟配置和 PHY 的时钟输入选择。第二步是量 MDC 和 MDIO看 MCU 有没有在读写 PHY 寄存器。如果 MDC 没有波形说明 ETH 外设没有正确初始化。如果时钟和 MDIO 都正常但HAL_ETH_Init还是失败可以用HAL_ETH_ReadPHYRegister读一下 PHY 的 ID 寄存器。LAN8720 的 ID 是 0x0007C0F1DP83848 是 0x20005C90。如果读出来的 ID 不对说明 PHY 地址配错了或者 PHY 没工作。还有一个隐蔽的问题RMII 的 REF_CLK 如果由 PHY 提供MCU 的 PA1 要配置成输入模式并且要在 CubeMX 里把 ETH 的时钟源设成ETH_RMII_REF_CLK。如果设成了RCC_MCO1MCU 会试图输出时钟和 PHY 的输出冲突导致 PHY 不工作。6. 从单节点到多节点扩展时的架构考虑6.1 多节点通信的 IP 规划以太网方式下每个 F407 节点需要一个独立的 IP。如果直接用 DHCP节点多了之后 IP 不固定上位机的配置会很麻烦。我的做法是给每个节点分配静态 IP在代码里写死或者通过拨码开关选择预设的 IP 配置。IP 规划要考虑网段和子网掩码。如果节点数量少用一个 C 类网段就够了比如 192.168.1.0/24MCU 节点从 192.168.1.100 开始分配上位机用 192.168.1.10。如果节点数量多可以划分子网但 micro_ros 的 agent 默认只监听一个网段跨网段需要配置路由。还有一个细节micro_ros 的 UDP 传输层默认使用 8888 端口如果多个 agent 在同一台机器上运行端口会冲突。解决办法是给每个 agent 指定不同的端口MCU 端也要相应修改目标端口。6.2 话题命名和 QoS 配置多节点场景下话题命名要有统一的规范。我一般用/robot_name/sensor_name的格式比如/arm/joint1_position、/base/ultrasonic。这样在 rviz2 或者 ros2 topic list 里看起来清晰也方便用通配符过滤。QoS 配置是另一个容易忽略的点。micro_ros 默认使用rmw_qos_profile_default可靠性是RELIABLE历史深度是 10。如果 MCU 的内存有限可以把历史深度降到 1 或者 2减少缓冲区占用。如果数据可以容忍丢包把可靠性改成BEST_EFFORT也能省内存。// 自定义 QoS 配置 rmw_qos_profile_t qos_profile rmw_qos_profile_default; qos_profile.reliability RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT; qos_profile.depth 2; rclc_publisher_init( publisher, node, ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32), stm32_counter, qos_profile);6.3 固件升级的考虑项目部署之后固件升级是个绕不开的问题。F407 支持通过 UART 或者 USB 进行 ISP 升级也支持通过以太网进行 IAP 升级。如果节点安装在难以触及的位置以太网 IAP 是最方便的。实现以太网 IAP 的思路是在 Flash 里划分两个区域一个放 bootloader一个放应用程序。bootloader 负责接收上位机发来的固件包写入应用程序区然后跳转执行。micro_ros 的 agent 可以配合一个自定义的 ROS2 节点把固件包通过话题发给 MCU。这里有个实际经验IAP 升级过程中要确保通信不中断所以 bootloader 里的网络协议栈要尽量简单不要依赖 micro_ros。我一般用裸机的 lwIP 加上一个简单的 UDP 协议来传输固件升级完成后再跳转到 micro_ros 应用。7. 调试工具和日常维护的实用技巧7.1 用 ros2 topic hz 和 bw 做性能评估ros2 topic hz可以查看话题的发布频率ros2 topic bw可以查看带宽占用。这两个命令在调试通信性能时非常有用。比如你设定了 100ms 的定时器但ros2 topic hz显示只有 5Hz说明有消息丢失或者 MCU 的处理速度跟不上。# 查看发布频率 ros2 topic hz /stm32_counter # 查看带宽 ros2 topic bw /stm32_counter如果频率不稳定先检查 MCU 的定时器配置。micro_ros 的定时器精度受 SysTick 影响如果 SysTick 被其他中断打断定时器回调会延迟。解决办法是把 SysTick 的优先级设到最低让通信中断优先处理。7.2 串口调试的日志输出micro_ros 支持通过串口输出调试日志但如果你用串口做通信传输日志和通信数据会混在一起。解决办法是用一个独立的串口做日志输出或者用 SWOSerial Wire Output输出日志。SWO 需要 ST-Link 支持在 CubeMX 里启用TRACESWO引脚然后在代码里用ITM_SendChar输出日志。我一般用 SWO 输出 micro_ros 的内部日志用 UART 做通信。这样调试信息不会干扰通信数据而且 SWO 的速度比 UART 快适合输出大量日志。7.3 长期运行的稳定性观察micro_ros 在 F407 上长期运行最常见的问题是内存泄漏和连接断开。内存泄漏通常是因为消息分配后没有释放或者执行器的回调里创建了新的对象但没有销毁。连接断开可能是因为网络抖动或者 agent 重启。我的做法是在主循环里加一个心跳检测定期检查rmw_uros_ping_agent的返回值。如果连续几次 ping 不通就重新初始化 micro_ros 的连接。// 心跳检测 if (rmw_uros_ping_agent(100, 3) ! RMW_RET_OK) { // 重新初始化 rclc_executor_fini(executor); rcl_node_fini(node); rclc_support_fini(support); // 重新初始化... }这个机制在实际项目中救过我好几次。有一次 agent 因为系统更新重启了MCU 端没有重连导致数据中断了几个小时。加了心跳检测之后agent 恢复后 MCU 会自动重连不需要人工干预。7.4 关于消息类型选择的经验最后说一个关于消息类型的经验。micro_ros 支持的消息类型越多编译出来的固件越大内存占用也越高。我建议只启用实际用到的消息类型不要图省事把整个std_msgs和sensor_msgs都打开。如果标准消息类型不够用可以自定义精简的消息类型。比如你只需要传一个浮点数组用std_msgs/Float32MultiArray会带上很多额外的字段不如自己定义一个MyFloatArray.msg只包含float32[] data。这样消息的序列化开销小内存占用也低。我在一个机械臂项目里把关节角度、速度、电流三个数据合并成一个自定义消息比用三个标准消息分别发布节省了将近 40% 的带宽。这个优化在节点数量多的时候效果很明显。7.5 关于硬件选型的一点补充F407 的以太网 PHY 选型上LAN8720 和 DP83848 是最常见的两个。LAN8720 便宜、外围电路简单但它的 REF_CLK 输出精度一般长时间运行可能会有频偏。DP83848 贵一些但时钟精度高、抗干扰能力强工业项目里更推荐。如果板子空间允许建议给 PHY 单独用一个 25MHz 晶振而不是用 MCU 的 MCO 输出。独立晶振的抖动更小以太网的误码率更低。我对比过两种方案用独立晶振的时候ros2 topic bw显示的带宽更稳定丢包率也更低。STM32F407 的 CAN 控制器有两个CAN1 是主控制器CAN2 是从控制器两者共享 512 字节的 SRAM。如果两个 CAN 同时使用滤波器的配置要注意CAN2 的滤波器编号从 14 开始不能和 CAN1 的冲突。这个细节在参考手册里有说明但很容易被忽略。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

AI智能体L1-L5分级安全框架:从模型安全到行为安全 2026/9/28 14:48:27

AI智能体L1-L5分级安全框架:从模型安全到行为安全

AI 安全最近在圈子里真的是高频词,尤其是那份“通用型 AI 智能体 L1-L5 分级安全框架白皮书”出来之后,很多做模型、做 Agent、做 RAG 的朋友都在转。我也把这份东西从头到尾啃了一遍,结合自己实际在项目里踩过的坑,发现这个分级框…

阅读更多 →
嵌入式通信协议详解:I2C、SPI、UART、I2S对比与选型实战 2026/9/28 14:48:27

嵌入式通信协议详解:I2C、SPI、UART、I2S对比与选型实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
AI能替代三维建模吗?从可编辑性与工作流看真实边界 2026/9/28 14:48:27

AI能替代三维建模吗?从可编辑性与工作流看真实边界

上午的例会上,实习生把一张写满建模需求的需求单直接黏进AI对话框,三分钟不到,屏幕上弹出一个“完成”的草模。我盯着那个模型看了半分钟,然后让他把文件存进“废弃方案”文件夹——不是AI做错了什么,而是它生成的这坨…

阅读更多 →
银河麒麟v10下VSCode与Qt 5.15.2开发环境配置指南 2026/9/28 14:48:27

银河麒麟v10下VSCode与Qt 5.15.2开发环境配置指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
连锁洗衣店管理系统开发:基于SSM框架的Java Web实践 2026/9/28 14:48:27

连锁洗衣店管理系统开发:基于SSM框架的Java Web实践

做连锁洗衣店的业务管理系统,是不是听起来很简单?不就是把送来的衣服登记一下、洗完了再登记一下取走吗?真要把这个项目从零写出来,你会发现里面藏着一整套业务逻辑:会员储值、订单流转、衣物状态跟踪、门店对账、员工…

阅读更多 →
C语言超级玛丽源码毕业设计:从编译运行到二次开发与答辩全攻略 2026/9/28 14:48:21

C语言超级玛丽源码毕业设计:从编译运行到二次开发与答辩全攻略

简介:这份资源是面向高校计算机相关专业学生与C语言进阶学习者的毕业设计级项目源码,以经典超级玛丽游戏为载体,帮助读者在真实可运行的工程中理解C语言在游戏开发中的落地方式。压缩包共33个文件,约5.65MB,包含cpp与h…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉