2. CANopen基础与从站通信模型
好,咱们正式开始啃CANopen的核心。这一章的内容,说白了就是CANopen协议的“骨架”。你把这章吃透了,后面写代码就是往骨架上填肉。
我个人习惯把CANopen理解成一个“智能设备网络”。每个设备(也就是从站)都得知道自己能干什么、怎么被别人控制、出了错怎么报告。这些信息都存在哪?就存在我们今天要讲的几个核心概念里。
2.1 对象字典(Object Dictionary, OD)
对象字典,我更喜欢叫它“设备的名片加说明书”。它是一个标准化的数据结构,里面按索引(Index)和子索引(Subindex)存放了设备的所有参数。
你想想看,一个电机驱动器,它需要知道额定电流、最大转速、当前转速、控制模式……这些东西如果每个厂家都用自己的方式存,那上位机(主站)就没法统一访问了。CANopen就是通过对象字典,把这些信息全部标准化。
对象字典的核心结构:
- 索引(Index):16位地址,范围0x0000~0xFFFF。相当于书的“章”。
- 子索引(Subindex):8位地址,范围0x00~0xFF。相当于“节”。
- 对象内容:包括数据类型(如UNSIGNED8、INTEGER32)、访问权限(只读、读写)、默认值等。
我在项目中遇到过最典型的坑:有人把对象字典的索引号搞混了。比如标准CiA 301规定,0x1000是设备类型,0x1001是错误寄存器。结果他写成了0x1001存设备类型,主站一读,数据全乱套。所以,对象字典的索引定义,必须严格遵循CiA标准,别自己瞎编。
| 索引范围 | 用途 | 举例 |
|---|---|---|
| 0x1000~0x1FFF | 通信对象(通信参数) | 0x1000 设备类型,0x1017 心跳生产者时间 |
| 0x2000~0x5FFF | 制造商特定对象 | 自定义参数,如固件版本、校准数据 |
| 0x6000~0x9FFF | 标准设备子协议(如驱动、I/O) | 0x6040 控制字,0x6041 状态字 |
我的小技巧:在STM32上用CANopenNode时,对象字典通常是一个巨大的C结构体数组。我习惯在代码里把每个索引的定义都加上注释,标明对应哪个CiA标准条目。这样半年后回来改代码,自己还能看懂。
2.2 通信对象:设备之间怎么说话?
对象字典是“静态数据”,那怎么读写它?怎么让设备动起来?这就靠通信对象了。CANopen定义了多种通信对象,每种负责不同的任务。
2.2.1 SDO(服务数据对象)
SDO,说白了就是“点对点”的读写服务。主站通过SDO,可以直接访问从站对象字典里的任何一个条目。它用的是“请求-应答”模式,可靠,但速度慢。
- 用途:配置参数、下载固件、读取诊断信息。
- 特点:保证送达,一次最多传4字节数据(快速SDO),大块数据用分段SDO。
- COB-ID:通常使用0x600 + NodeID(请求)和0x580 + NodeID(应答)。
避坑指南:我曾经在一个项目中,用SDO频繁读取一个传感器的实时值(比如每10ms读一次)。结果总线负载飙升,导致其他紧急报文(EMCY)被延迟。记住,SDO不适合传输实时性要求高的数据,那是PDO的活。
2.2.2 PDO(过程数据对象)
PDO是“广播式”的,一个设备发,所有设备都能收。它没有应答,所以速度快,但不可靠(丢了就丢了)。PDO是CANopen实现实时控制的核心。
- 用途:传输实时控制命令、传感器数据、状态反馈。
- 触发方式:事件触发、定时触发、远程请求、同步触发。
- 映射:PDO里的数据可以“映射”到对象字典的任意条目。比如把“当前转速”和“电流”打包在一个PDO里发出去。
2.2.3 NMT(网络管理)
NMT是“管理员”,负责控制从站的状态机。主站通过NMT报文,可以让从站在初始化、预操作、操作、停止这几个状态之间切换。
- COB-ID:固定为0x000。
- 命令:启动远程节点、停止远程节点、进入预操作、复位节点等。
2.2.4 SYNC(同步对象)
SYNC是“节拍器”。主站周期性地发送SYNC报文,所有从站收到后,同步执行PDO的发送或接收。这在多轴运动控制中特别有用,保证所有轴在同一时刻开始动作。
2.2.5 EMCY(紧急报文)
EMCY是“报警器”。当设备检测到严重错误(如过压、过热、通信丢失),会立即发送一个高优先级的EMCY报文。主站收到后,可以采取紧急措施。
通信对象对比总结:
| 对象 | 模式 | 可靠性 | 实时性 | 典型用途 |
|---|---|---|---|---|
| SDO | 点对点 | 高(有应答) | 低 | 配置、诊断 |
| PDO | 广播 | 低(无应答) | 高 | 实时控制、数据采集 |
| NMT | 广播 | 高 | 中 | 状态管理 |
| SYNC | 广播 | 中 | 最高 | 同步触发 |
| EMCY | 广播 | 高 | 最高 | 故障报警 |
2.3 状态机:设备的“生命历程”
每个CANopen从站,都运行在一个有限状态机里。这个状态机定义了设备从上电到正常工作的完整流程。你想想看,如果设备一上电就开始发PDO,但参数还没配置好,那不乱套了吗?状态机就是为了解决这个问题的。
CANopenNode里,状态机的实现非常清晰。我刚开始看源码时,就是先找到状态机切换的那几个函数,一下子就理清了整个程序的脉络。
这张图,我建议你多看几遍。每个状态能干什么、不能干什么,心里要有数。
- Initialization(初始化):设备上电后自动进入。这个阶段,设备会读取对象字典的默认值,进行硬件自检。完成后自动跳转到Pre-operational。
- Pre-operational(预操作):这是“配置模式”。主站可以通过SDO修改从站的参数(比如PDO映射、通信参数)。但此时禁止PDO通信,防止配置过程中产生误动作。
- Operational(操作):这是“工作模式”。所有通信对象(SDO、PDO、SYNC、EMCY)都正常工作。设备开始执行它的核心功能。
- Stopped(停止):这是“安全模式”。设备停止所有通信(除了NMT和心跳)。通常用于紧急停止或维护。
我的经验:在调试阶段,我经常让设备停在Pre-operational状态,然后用SDO一条一条地配置参数。确认无误后,再发NMT命令切换到Operational。这样能避免很多因参数错误导致的意外。
2.4 本章小结
这一章的内容,是CANopen协议的“世界观”。对象字典是数据仓库,通信对象是运输工具,状态机是交通规则。三者缺一不可。