CAN总线学习

2天理解了CAN协议

CAN/CANopen 开发全栈指南:从理论到工业实践

📅 更新日期:2025年11月25日
🎯 适用对象:嵌入式工程师、机器人开发者、工业自动化工程师
💡 核心价值:掌握 CAN/CAN FD + CANopen 全栈开发能力,构建高可靠工业通信系统

 

 

🔑 一、核心定位:CANopen 之于 CAN,正如 Modbus 之于 RS-485

 
协议层
物理层
应用特点
Modbus RTU
RS-485
主从轮询,简单但实时性差
CANopen
CAN/CAN FD
事件驱动 + 同步机制,工业级实时性

关键认知

CAN = 高速可靠的“高速公路”
CANopen = 标准化的“交通规则+车辆类型”
没有 CANopen,CAN 只是原始数据通道

 

 

🛣️ 二、CAN/CAN FD 基础:数据链路层核心

1. 经典 CAN vs CAN FD 关键差异

 
特性
经典 CAN
CAN FD
最大数据长度
8 字节
64 字节
数据段速率
≤1 Mbps
2~5 Mbps(仲裁段仍 1Mbps)
CRC 校验
15 位
17/21 位(更强纠错)
帧结构
固定
双速率 + BRS 位切换

2. CAN FD 双速率机制(图解)

image

 

 
  • BRS 位 = 速率切换开关(Bit Rate Switch)
  • 类比:收费站前限速 60km/h(仲裁),收费站后放开 240km/h(数据)
 

3. DLC 码映射表(必须牢记!)

 
DLC 码
实际字节数
典型用途
0~8
0~8
经典 CAN 兼容
9
12
小数据块
10
16
标准块
11
20
12
24
13
32
常用
14
48
15
64
最大容量

⚠️ 关键技巧
非标准长度数据向上取整 DLC + 首字节携带真实长度
例:25 字节数据 → 选 DLC=13 (32字节) → 帧格式:[真实长度=25][25字节数据][7字节填充]

 

 

🏗️ 三、CANopen 核心架构:工业通信的骨架

1. 通信模型全景图

image

 

 
 

2. NMT 网络管理(生命线!)

 
命令码
功能
节点状态
0x01
启动节点
Operational
0x02
停止节点
→ Pre-operational
0x80
进入初始化
→ Initialisation
0x81
重置节点
硬件复位
0x82
重置通信
清配置

NMT 工作流程

  1. 上电 → Initialisation
  2. 主机发 NMT_Reset_Comm(0x82) → 清配置
  3. Pre-operational → SDO 配置 PDO
  4. NMT_Start(0x01)Operational → PDO 激活
 

3. 心跳/节点守护(在线监控)

 
机制
从机行为
主机行为
推荐度
Heartbeat
周期发 0x700+NodeID
超时判离线
首选
Node Guarding
收请求后回复
周期发请求
⚠️ 次选

💡 心跳配置

  • 从机 SDO 写 0x1017 = 1000(1000ms 心跳)
  • 主机超时阈值 = 150% 心跳周期(1500ms)
 

 

📚 四、对象字典:CANopen 的“灵魂”

1. 标准分区表(CiA 301)

 
Index 范围
名称
用途
类比 Modbus
0x1000-0x1029
Device Profile
设备信息
保持寄存器
0x1200-0x127F
SDO Server
SDO 服务参数
0x1400-0x15FF
RPDO Communication
RPDO 通信参数
0x1600-0x17FF
RPDO Mapping
RPDO 数据映射
0x1800-0x19FF
TPDO Communication
TPDO 通信参数
0x1A00-0x1BFF
TPDO Mapping
TPDO 数据映射
0x2000-0x5FFF
Manufacturer Specific
厂商自定义
4x 寄存器
0x6000-0x9FFF
Standard Device Profile
标准设备规范
0x6040
Controlword
控制字
4x(可写)
0x6041
Statusword
状态字
3x(只读)
0x6064
Position Actual
实际位置
3x
0x607A
Target Position
目标位置
4x

2. 子索引(Sub-index)机制

  • 不是连续数组! 是稀疏映射表(如 0x1802 有 sub1, sub2, sub5)
  • sub0 = 最高子索引号(必须存在)
  • 保留子索引(如 sub4)直接跳过
 

🔑 内存真相
对象字典 = ROM 中的索引表(指向 RAM 变量)
数据变量 = RAM 中的独立存储(通过指针关联)

 

 

⚡ 五、PDO/SDO 深度解析:实时与配置的双通道

1. 通信模型对比

 
特性
PDO
SDO
用途
实时数据传输
配置/诊断
方向
TPDO(从→主)<br>RPDO(主→从)
点对点(主↔从)
协议
无交互(推模式)
请求-响应(拉模式)
延迟
μs 级
ms 级
带宽
高效(无头部)
有开销

正确类比

  • RPDO = Modbus 4x 写(主机下发控制)
  • TPDO = Modbus 3x 读(从机上报状态)
  • SDO = 配置通道(替代轮询)
 

2. PDO 配置四步法(必须掌握!)

目标:配置 TPDO1 上报 Statusword + Position

  1. 禁用 TPDOSDO 写 0x1800+0 = 0x80000181
  2. 清空映射SDO 写 0x1A00+0 = 0x00
  3. 写入映射
    • SDO 写 0x1A00+1 = 0x60410010(Statusword, 16bit)
    • SDO 写 0x1A00+2 = 0x60640020(Position, 32bit)
  4. 启用 TPDOSDO 写 0x1800+0 = 0x00000181
 

💡 映射值格式0x[INDEX][SUB][SIZE]
SIZE:16bit=0x10, 32bit=0x20, 8bit=0x08

 

3. 多 PDO 通道策略(工业级实践)

 
通道
触发方式
典型数据
用途
TPDO1
SYNC (type=1)
Statusword + Position
高速同步控制
TPDO2
周期 10ms (type=255)
Velocity + Torque
中速监控
TPDO3
事件触发 (type=254)
Error register
故障即时上报
RPDO1
Controlword + TargetPos
主运动指令
RPDO2
MaxCurrent
参数动态调整

设计原则

  • TPDO1 保留给安全关键数据
  • 避免在 TPDO 中映射可写对象
  • 事件触发用于报警,避免周期浪费
 

 

⚙️ 六、实现与优化:从理论到产品

1. 内存优化技巧(RAM 为王!)

✅ 推荐方案:按功能模块划分小结构体

image

  

2. RTOS 集成最佳实践

image

 

 

关键原则

CO_process() 必须每 1ms 被调用一次,误差 < 100μs
空闲任务钩子绝不处理心跳!(违反实时性)

 

3. 协议栈资源需求

 
协议栈
最小 ROM
最小 RAM
适用场景
CANopenNode
12 KB
800 B
首选(STM32/RTOS)
micro-canopen
8 KB
500 B
资源受限设备
CANopenSocket
20 KB
2 KB
Linux 主站

💡 裁剪技巧

  • 禁用 CO_EMERGENCY(省 200B RAM)
  • 减少 PDO 通道数(默认 4TPDO+4RPDO → 按需裁剪)
  • #ifdef 控制模块编译
 

 

🛠️ 七、工具链与开发流程

image

 

 
 
  • EDS 本质:扩展 INI 文件([Section] + Key=Value
  • 主机无需预存 SDO 帧!动态组装(8 字节栈变量)
  • 从机 SDO 响应:动态组装(无预存帧,节省 RAM)
 

2. 调试黄金组合

 
工具
用途
关键技巧
CANalyzer
总线分析
加载 EDS → 自动解析数据
SavvyCAN
免费替代
支持 CAN FD + 脚本扩展
STM32CubeMX
驱动配置
时序计算器(1Mbps/4Mbps)
CANopenEDS
EDS 编辑
生成 CO_OD.h 脚本

🔑 调试口诀

  1. 先看 心跳(0x701) → 判断设备是否存活
  2. 监控 紧急报文(0x81) → 捕获错误
  3. CANalyzer + EDS → 自动解析 PDO 内容
 

 

⚠️ 八、常见陷阱与避坑指南

1. 致命错误清单

 
问题
现象
解决方案
PDO 未禁用直接修改
总线错误/数据错乱
先写 0x8000xxxx 禁用
NMT 未启动进 Operational
PDO 不工作
先发 0x01 0x01
心跳超时阈值过小
频繁判离线
设为 150% 心跳周期
DLC 未向上取整
数据截断
25字节 → 选 32字节 DLC
SDO 超时无重试
配置失败
实现 3 次重试机制

2. 实时性陷阱

  • 问题:TPDO 被高优先级任务抢占,心跳延迟
  • 真相:心跳独立于 TPDO,但依赖 CO_process() 调用
  • 方案
    • 协议栈任务优先级 > 应用任务
    • 用硬件定时器保证 1ms 周期
    • CAN 中断中仅置标志,任务中处理
 

3. Modbus 习惯带入 CANopen

 
Modbus 习惯
CANopen 正确做法
轮询读 3x 寄存器
用 TPDO 自动上报
4x 寄存器存传感器数据
3x 只读,4x 可写(严格分离)
固定寄存器地址
SDO 配置 PDO 映射(动态)

工业规范
PDO 用于实时数据,SDO 用于配置
绝不轮询 TPDO 已上报的数据!

 

 

📈 九、学习路径建议:从入门到工业级

阶段 1:基础夯实(1-2周)

  • 用 STM32 CubeMX 配置 CAN(1Mbps)
  • 用 CANalyzer 抓包分析标准帧
  • 实现自定义协议传输 >8 字节数据
 

阶段 2:CAN FD 进阶(1周)

  • 配置 CAN FD 双速率(1Mbps/4Mbps)
  • 实现 64 字节数据传输 + CRC16
  • 用 DLC 码处理非标准长度
 

阶段 3:CANopen 入门(2-3周)

  • 移植 CANopenNode 到 STM32
  • 用 SDO 读写 0x6041/0x6064
  • 配置 TPDO1 上报位置
 

阶段 4:工业实践(持续)

  • 实现 SYNC 同步多轴
  • 集成到 RTOS(FreeRTOS/RT-Thread)
  • 用 EDS 文件生成配置
 

💡 终极检验
不依赖 CANalyzer,仅靠逻辑分析仪 + 协议文档
调试通一个 3 节点 CANopen 网络

 

 

🌟 十、关键总结:3 句话掌握精髓

  1. PDO 是“推”,SDO 是“拉”
    → 实时数据用 TPDO 自动上报,配置用 SDO 按需读写
  2. 对象字典 = ROM 索引表 + RAM 变量
    功能模块化结构体 优于单一巨型结构体
  3. NMT 控制状态,心跳监控生命
    先配置(Pre-op),再运行(Operational),超时 = 离线
 

 

📚 附录:推荐资源

  • 协议栈CANopenNode GitHub
  • 书籍:《The Complete CANopen Book》by Holger Zeltwanger
  • 工具:CANopenEDS Editor(免费)、SavvyCAN(开源)
  • 标准:CiA 301(基础)、CiA 402(伺服)
 

💡 最后建议
用 STM32 + CANopenNode + 周立功 USBCAN
搭建最小系统,亲手配置一个 TPDO
—— 理论百遍,不如动手一次!

posted on 2022-11-29 00:48  杰瑞鼠  阅读(29)  评论(0)    收藏  举报