Lazy loaded image
🌉 开发框架搭建
常用接口协议-CANopen 通信
Words 5395Read Time≈ 14 min
2026-9-21
2026-9-21
🧭
学习主线
先理解 CAN 与 CANopen 的分层关系,再掌握对象字典和 NMT/PDO/SDO,随后搭建最小网络,最后分别完成 STM32 与 Linux 端验证。每一步都以前一步的可验证结果为前提。

阅读顺序

  1. 基础概念:CAN 负责传输,CANopen 规定设备如何组织数据、管理节点和交换业务数据。
  1. 对象字典:先理解索引、子索引、数据类型、访问权限和 PDO 映射。
  1. 通信机制:再区分 NMT、Heartbeat、SDO、PDO、SYNC、EMCY 的职责。
  1. 网络搭建:明确主从节点、Node-ID、波特率、终端电阻和物理连线。
  1. 平台实现:先完成 STM32 移植,再完成 Linux SocketCAN 与 canopend 验证。
  1. 验收闭环:以抓包、对象读写、心跳和 PDO 收发作为成功标准。

0. 现有流程图与资料入口

以下流程图先作为整体预览;后文会按“概念 → 配置 → 实现 → 测试”的顺序逐项展开。
通讯连接
通讯连接
上电
上电
模式
模式
运动模式
运动模式
电机使能
电机使能
 

1. 基础概念:CAN 与 CANopen

1.1 CAN 与 CANopen 的关系

CAN(Controller Area Network)是一种底层通信协议,用于实现设备之间的高效数据传输。它定义了如何在网络上发送和接收数据帧,但不规定数据帧的具体内容或应用层协议。
CANopen 是建立在 CAN 之上的应用层通信协议,主要用于工业自动化和嵌入式系统。它保留 CAN 可靠、实时的总线传输能力,同时补充设备配置、网络管理和过程数据交换规则。CANopen 主要定义了:
  1. 设备配置:通过对象字典(Object Dictionary)来管理设备参数。
  1. 网络管理:提供节点启动、停止和监控功能。
  1. 通信服务:包括过程数据对象(PDO)、服务数据对象(SDO)等,用于实时数据传输和参数配置。
总结来说,CAN 是“运输通道”,CANopen 是“通信规则”。CAN 负责把一帧数据可靠地送到总线上;CANopen 则规定节点状态、报文用途、参数地址以及设备之间如何协作。

分层理解

层次
关注点
典型问题
CAN 物理层
电气连接与信号质量
CAN_H/CAN_L 是否接反?终端电阻是否正确?
CAN 数据链路层
仲裁、帧格式、错误检测
波特率是否一致?总线是否进入 Bus-Off?
CANopen 通信层
COB-ID、NMT、SDO、PDO、Heartbeat
这帧报文属于哪种服务?节点处于什么状态?
设备应用层
对象字典和设备行为
0x6040、0x6041 等对象在设备中代表什么?
💡
判断是否真正理解
看到一帧 CAN 数据时,应能依次回答:谁发送、报文类型是什么、访问哪个对象、数据如何解释、为什么在此时触发。

1.2 配套资料与实现入口

CAN 通讯配置 STM32
  • CANopenNode (this project): CANopen protocol stack, base for CANopen device. It contains no device specific code (drivers), which must be added separately for each target system. An example shows the basic principles, compiles on any system, but does not connect to any CAN hardware.
  • CANopenDemo: Demo device with CANopenNode and different target systems, tutorial and testing tools.
  • CANopenEditor: Object Dictionary editor, external GUI tool for editing CANopen Object Dictionary for custom device. It generates C source code, electronic data sheet and documentation for the device. It is a fork from libedssharp.
  • CANopenLinux: CANopenNode on Linux devices. It can be a basic CANopen device or more advanced with commander functionalities.
  • CANopenPIC: CANopenNode on PIC microcontrollers from Microchip. Works with 16-bit and 32 bit devices. Includes example for Arduino style Max32 board.
Complete generated documentation is also available online: https://canopennode.github.io

2. CANopen 协议:对象字典与通信机制

🎯
本章目标
能够回答三个问题:设备参数放在哪里、参数如何读写、实时数据如何交换。

2.1 对象字典查看工具 CANopenEditor

软件点击这里下载使用,也可以从Github仓库下载。
功能介绍
Insert Profile | DS301 profile.xpd 这里可以导入其他支持的文件 xpd、xdd、xdc 等文件。

2.2 对象字典说明

notion image
对象字典是设备规范中重要的部分,它是一组参数和变量的有序集合,包含了设备描述及设备网络状态的所有参数。每个对象包含索引、子索引、名称、描述、数据类型、数据范围、可访问性、能否映射、出厂设定、单位、生效方式。
其中含义如下:
  1. 索引:指定同一类对象在对象字典中的位置;
  1. 子索引:指示同一索引下,包含多个对象,对象在该类下的偏置;
  1. 数据类型和范围:比如常见的基础数据 Int8、 Int16、 Int32、 Uint8、Uint16、Uint32、String;
  1. 可访问性:可读写 RW、只读RO、只写WO;
  1. 能否映射:
    1. 能否映射
      说明
      NO
      不可映射到 PDO
      RPDO
      可映射到接收过程数据对象
      TPDO
      可映射到发送过程数据对象
      • RPDO(Receive Process Data Object,接收过程数据对象):表示当前节点接收的实时数据。报文到达后,协议栈按照映射关系将数据写入对象字典。例如,控制器向电机发送目标速度;对电机而言,目标速度通过 RPDO 接收。
      • TPDO(Transmit Process Data Object,发送过程数据对象):表示当前节点发送的实时数据。协议栈从对象字典读取已映射变量并组成 PDO 报文。例如,电机向控制器上报实际速度和状态字;对电机而言,这些数据通过 TPDO 发送。
      ↔️
      方向始终以当前节点为参照
      电机的 TPDO 可以成为控制器的 RPDO;控制器的 TPDO 也可以成为电机的 RPDO。两端只有 COB-ID、数据长度和映射顺序一致,数据才能被正确解释。
  1. 生效方式:
    1. 生效方式
      说明
      立即生效
      参数设置完成后,设定值立即生效
      停机生效
      参数设置完成后,等到驱动器不处于运行状态,设定值生效
      再次通电
      参数设置完成后,重新接通驱动器电源,设定值生效

2.3 对象字典分区

标准化配置区域

索引范围
用途
0001h–001Fh
基础数据类型
0020h–003Fh
复杂数据类型
1000h–1FFFh
通信配置区域,例如设备类型、Heartbeat、SDO、PDO 参数
2000h–5FFFh
制造商自定义参数
6000h–9FFFh
标准化设备配置区域,由设备规范定义
A000h–BFFFh
标准化接口配置区域
C000h–FFFFh
保留区域
对象字典不是“参数列表”这么简单,它同时是 设备能力说明、网络访问接口和运行状态入口。调试时应先确认索引和子索引存在,再确认数据类型与访问权限,最后确认写入后的生效条件。

通讯配置区域:1000h 组

1000h 对象组包含 CANopen 通讯所需的参数,通讯参数均不可映射到 PDO。
1000h-1FFFh细分不同索引范围。见下图
索引
对象
调试用途
1000h
Device type
确认设备类型与设备规范
1001h
Error register
快速判断设备是否存在错误
1017h
Producer heartbeat time
配置节点 Heartbeat 周期
1018h
Identity object
读取厂商、产品、版本和序列号
1200h 起
SDO server parameter
确认 SDO 请求与响应 COB-ID
1400h 起
RPDO communication parameter
配置 RPDO 的 COB-ID 和传输类型
1600h 起
RPDO mapping parameter
配置 RPDO 携带哪些对象
1800h 起
TPDO communication parameter
配置 TPDO 的 COB-ID、传输类型和定时参数
1A00h 起
TPDO mapping parameter
配置 TPDO 携带哪些对象
notion image
notion image

制造商特定配置区域:2000h组

制造商定义参数 2000h组

2.4 核心通信对象速查

对象
解决的问题
建议学习顺序
最小验证方式
NMT
节点如何启动、停止和切换状态
1
观察节点状态变化
Heartbeat
节点是否在线
2
修改 0x1017 后观察周期变化
SDO
如何可靠读写对象字典
3
读取并写入一个参数
PDO
如何低开销传输实时过程数据
4
映射一个变量并周期收发
SYNC
多节点如何按统一节拍动作
5
观察同步 PDO 行为
EMCY
设备如何上报紧急故障
6
触发故障并检查报文
SDO 适合配置和诊断,PDO 适合实时数据。先用 SDO 把对象读写跑通,再做 PDO 映射,排错成本最低。

SDO 与 PDO 的区别

对比项
SDO
PDO
主要用途
参数配置、诊断、对象读写
实时过程数据交换
是否包含索引信息
请求中携带索引和子索引
报文中通常不携带索引,含义由映射预先确定
通信方式
请求—响应
生产者—消费者
数据开销
较高
较低
实时性
一般
高
典型阶段
初始化、维护、故障诊断
正常运行
简单判断:偶尔读写一个明确参数,用 SDO;周期或事件触发地交换状态、位置、速度等实时变量,用 PDO。

2.5 常用 COB-ID 速查

COB-ID 是 CANopen 对 CAN 标识符的用途约定。默认预定义连接集通常按“功能码 + Node-ID”生成报文标识符。
服务
默认 COB-ID
方向或用途
NMT
000h
主站向节点发送状态控制命令
SYNC
080h
广播同步节拍
EMCY
080h + Node-ID
节点上报紧急故障
TIME
100h
广播时间信息
TPDO1
180h + Node-ID
节点发送实时过程数据
RPDO1
200h + Node-ID
节点接收实时过程数据
SDO 响应
580h + Node-ID
SDO 服务端向客户端响应
SDO 请求
600h + Node-ID
SDO 客户端向服务端请求
Heartbeat
700h + Node-ID
节点周期上报 NMT 状态
例如 Node-ID 为 4 时,默认 Heartbeat COB-ID 为 704h,SDO 请求为 604h,SDO 响应为 584h。抓包时先按 COB-ID 分类,比盯着 8 字节数据硬猜高效得多。

2.6 从上电到实时通信

NMT 状态

状态
主要行为
适合执行的操作
Initializing
协议栈和对象字典初始化
等待节点完成启动
Pre-operational
可进行 SDO 通信,常规 PDO 通常未启用
参数读取、PDO 配置、设备检查
Operational
SDO、PDO 和网络管理正常运行
实时业务通信
Stopped
停止大部分通信服务,保留网络管理能力
安全停机或维护

推荐启动流程

  1. 上电初始化:节点完成硬件和协议栈初始化,并发送 Boot-up 报文。
  1. 进入预运行态:可以进行 SDO 配置,但通常不进行常规 PDO 通信。
  1. 读取身份与通信参数:确认 Node-ID、设备类型、Heartbeat 和 PDO 配置。
  1. 配置 PDO:先禁用 PDO,再修改通信参数与映射,最后重新启用。
  1. 进入运行态:主站发送 NMT Start,节点开始按配置交换 PDO。
  1. 持续监控:通过 Heartbeat 判断在线状态,通过 EMCY 获取紧急故障。
⚠️
关键约束
PDO 能否传输,不只取决于映射是否正确,还取决于节点 NMT 状态、PDO 是否启用、传输类型和触发条件。只检查对象字典而忽略状态机,是常见误区。

3. CANopen 网络搭建:从拓扑到可通信

canopend 作为主控节点,Node-ID 设置为 1,负责网络管理、参数配置和测试指令;
demoDevice 作为被测节点,Node-ID 设置为 4,负责响应 SDO、发送 Heartbeat,并按配置交换 PDO。
两个设备还需要 CAN 驱动器和连接线。开始调试前,先统一 Node-ID、波特率、CAN_H/CAN_L、共地和 120Ω 终端电阻;软件没问题但物理层不通,是 CAN 调试里最经典也最浪费时间的坑。驱动器选型在这里有列表说明。但我们为了测试,选择设备一般都带有CAN驱动器。
设备或工具
在测试系统中的角色
Linux 开发板
运行 SocketCAN、canopend 或自动化测试脚本
STM32 开发板
运行 CANopenNode,被测嵌入式节点
H7-Tools
CAN/CANopen 调试与报文观察工具
PCAN-USB
PC 与 CAN 总线之间的硬件接口
The PCAN-USB adapter enables simple connection to CAN networks. Its compact plastic casing makes it suitable for mobile applications.
The package is also supplied with the CAN monitor PCAN-View for Windows® and the programming interface PCAN-Basic.

3.1 方案选择

方案
适用阶段
优点
主要用途
H7-Tools/PCAN-USB + STM32
首次移植
抓包直观、变量少
验证 STM32 协议栈
PCAN-USB + Linux
联调
PC 侧工具成熟
验证 Linux 节点
H7-Tools + Linux
现场调试
设备便携
分析实际总线
两块 Linux 开发板
自动化测试
易脚本化、可复现
回归测试与压力测试
建议从方案 1 开始:先减少系统变量,确认 STM32 节点能上线、能响应 SDO、能发送 Heartbeat,再扩展到 Linux 组网。

3.2 方案1:H7-Tools/PCAN-USB + STM32 开发板

H7-Tools 作为 CANopen 助手使用指南参考这里。
PCAN-USB 分析仪这里购买,参考PCAN-USB: PEAK-System 使用。

3.2.1 STM32 开发板移植 CANopen

移植顺序不要反:先验证 CAN 外设收发,再接入 1 ms 时基,最后运行 CANopen 协议栈。否则底层、中断和协议问题混在一起,抓包只会看到一片寂静。
移植步骤概览
notion image
  1. 在 STM32CubeMX 中配置 CAN/FDCAN 波特率、引脚和自动恢复能力。
  1. 启用 CAN 接收、发送及错误相关中断。
  1. 配置 1 ms 周期定时器,作为 CANopen 周期处理时基。
  1. 将 CANopenNode 与 STM32 适配层加入工程源码和头文件路径。
  1. 绑定 CAN 句柄、定时器句柄、Node-ID 和波特率。
  1. 在定时器回调中调用 canopen_app_interrupt()。
  1. 在主循环中持续调用 canopen_app_process()。
  1. 先验证 Boot-up 和 Heartbeat,再进行 SDO 与 PDO 测试。
以下为原始移植说明:
  1. Configure CAN/FDCAN to your desired bitrate and map it to the relevant TX/RX pins. Make sure to activate Auto Bus Recovery (bxCAN) or Protocol Exception Handling (FDCAN).
  1. Activate the RX and TX interrupt on the CAN peripheral
  1. Enable a timer for a 1ms overflow interrupt and activate interrupt for that timer
  1. Copy or clone CANopenNode and CANopenNodeSTM32 into your project directory
  1. Add CANopenNode and CANopenNodeSTM32 to Source locations
  1. Add CANOpenNode and CANopenNodeSTM32 to  Include locations
  1. In your main.c, add #include "CO_app_STM32.h"
    1. Make sure that the HAL_TIM_PeriodElapsedCallback function is implemented and calls canopen_app_interrupt.
      1. Now based on your application, you'll take one of the following approaches :
    1. In your main.c
      🔎
      当前示例存在参数不一致
      上面的 STM32 示例使用 Node-ID 29、125 kbit/s;前文拓扑使用 Node-ID 4;后面的 Linux 示例使用 1 Mbit/s。实际联调时必须统一规划,否则节点一定无法通信。建议本文示例统一为:被测节点 Node-ID 4,主控节点 Node-ID 1,波特率选择 125 kbit/s 或 1 Mbit/s 中的一种并在所有节点保持一致。
      初始化参数的职责:
      • CANHandle:绑定底层 CAN/FDCAN 外设。
      • HWInitFunction:提供硬件重新初始化入口。
      • timerHandle:提供协议栈周期任务所需的 1 ms 时基。
      • desiredNodeID:设置节点地址,必须避免总线上重复。
      • baudrate:设置 CAN 波特率,必须与其他节点一致。
      主循环负责执行非实时协议处理:

      3.2.2 测试与验收

      CAN 分析仪能看到节点启动报文
      节点进入预运行或运行状态
      能通过 SDO 读取 0x1017 心跳生产者时间
      修改 0x1017 后,Heartbeat 周期按预期变化
      目标 TPDO/RPDO 映射和收发正常
      断线或节点异常时能观察到 Heartbeat 超时或 EMCY

      3.3 方案2:PCAN-USB + Linux 开发板

      该方案用于验证 Linux 节点是否能在真实 CAN 总线上正常工作:
      1. 在 PC 上安装 PCAN 驱动与 PCAN-View。
      1. 在 Linux 开发板上确认 SocketCAN 驱动已加载并出现 can0。
      1. 统一 PCAN 与 Linux 端波特率。
      1. 先用 candump/cansend 验证原始 CAN 收发。
      1. 再启动 canopend,验证 Boot-up、Heartbeat 和 SDO。
      1. 最后启用 PDO,检查周期、触发方式和数据字节序。

      3.4 方案3:H7-Tools + Linux 开发板

      该方案适合脱离 PC 的现场调试。H7-Tools 负责观察和发送 CANopen 报文,Linux 开发板运行被测节点。
      最小验证流程:
      1. H7-Tools 与 Linux 开发板共地,并正确连接 CAN_H、CAN_L。
      1. 两端设置相同波特率,在总线两端放置 120Ω 终端电阻。
      1. Linux 端启动 can0 和 canopend。
      1. H7-Tools 检查 Boot-up 与 Heartbeat。
      1. 使用 SDO 读取 1018h 身份对象和 1017h Heartbeat 周期。
      1. 切换 NMT 状态并验证 PDO 是否按预期启动或停止。

      3.5 方案4:两块 Linux 开发板

      3.5.1 配置 Linux 开发板接收端

      推荐使用 ip 命令查看和配置 SocketCAN,并在修改参数前先关闭接口:

      3.5.2 配置 Linux 开发板发送端

      3.5.3 验证对象读写

      验证顺序:接口上线 → 原始 CAN 收发 → CANopen 节点上线 → SDO 读取 → SDO 写入 → PDO 收发。不要一上来就调 PDO 映射,那是在给自己制造悬案。

      验证其他操作

      4. 调试闭环与下一步

      4.1 推荐排错顺序

      1. 物理层:检查供电、共地、CAN_H/CAN_L、终端电阻。
      1. 链路层:检查波特率、采样点、错误计数和 Bus-Off。
      1. 节点层:检查 Node-ID、NMT 状态和 Heartbeat。
      1. 对象层:用 SDO 验证索引、子索引、数据类型和访问权限。
      1. 实时数据层:最后检查 PDO 通信参数、映射参数和触发方式。

      4.2 最小完成标准

      • 两个节点使用相同波特率且 Node-ID 不冲突。
      • 主站能控制从站 NMT 状态。
      • 主站能稳定读写至少一个对象字典参数。
      • Heartbeat 周期可配置且掉线可检测。
      • 至少一组 PDO 完成映射、发送和接收。
      • 抓包记录能解释每类关键报文的 COB-ID、数据含义和触发条件。

      4.3 测试记录模板

      每次联调至少记录以下信息,避免“这次能跑、下次靠猜”:
      项目
      记录内容
      硬件拓扑
      节点、收发器、终端电阻、供电与共地方式
      通信参数
      波特率、Node-ID、采样点、CAN/FDCAN 模式
      软件版本
      CANopenNode 版本、应用提交号、对象字典版本
      测试步骤
      NMT、SDO、PDO、Heartbeat 的操作顺序
      证据
      candump/PCAN 抓包、日志、错误计数、关键截图
      结果
      预期、实际、差异和结论

      4.4 后续深化顺序

      1. 用 CANopenEditor 固化对象字典并生成代码。
      1. 系统梳理 PDO 通信参数与映射参数。
      1. 增加 EMCY、SYNC、TIME 和参数持久化。
      1. 建立可重复执行的 Linux 自动化测试脚本。
      1. 补充总线负载、错误注入和断线恢复测试。
       
      上一篇
      常用接口协议-CAN 入门书学习笔记
      下一篇
      常用接口协议-SOES EtherCAT 从站

      Comments
      Loading...