4、PDO通信机制:TPDO/RPDO配置、同步/异步PDO、PDO映射、事件定时器与禁止时间

PDO,说白了就是CANopen里跑实时数据的通道。SDO像快递柜,你取一件我放一件,慢但稳;PDO像广播喇叭,一喊全听见,快但不保证每句都有人听。电机控制这种需要高频交换位置、速度、电流的场景,PDO才是主角。

我个人习惯把PDO理解成“数据管道”。你提前把管道里要传什么、什么时候传、传多少都定好,运行时就不需要再协商了。这也是PDO效率高的根本原因——配置一次,终身使用。

4.1 TPDO与RPDO:谁发谁收?

先搞清楚方向:

  • TPDO(Transmit PDO):设备往外发数据。比如驱动器把当前转速、电流发到总线上。
  • RPDO(Receive PDO):设备从总线收数据。比如驱动器接收上位机下发的目标位置。

一个设备可以有多个TPDO和RPDO。CANopen标准最多支持每个设备4个TPDO + 4个RPDO,但实际芯片实现各有不同。我见过有些国产驱动器只实现了2个TPDO,踩坑后才发现的。

类型 方向 典型用途 COB-ID范围
TPDO 设备 → 总线 上报状态、位置、电流 0x180 + NodeID ~ 0x1FF + NodeID
RPDO 总线 → 设备 下发目标值、控制字 0x200 + NodeID ~ 0x2FF + NodeID
小技巧: 调试时可以用CAN分析仪直接抓COB-ID。看到0x181开头的报文,就知道是Node-ID=1的设备在发TPDO1。这个规律记牢了,排查总线问题能快不少。

4.2 同步PDO vs 异步PDO:什么时候发?

这是PDO配置里最核心的选择。我刚开始做电机同步控制时,就因为这个没选对,导致四轴联动总是差一拍。

同步PDO(Synchronous PDO)

依赖SYNC报文触发。主站周期发SYNC,从站收到后统一采集数据、统一输出。适合多轴插补、同步运动。

  • 传输类型:0~4(同步周期模式)、5~15(同步非周期模式)
  • 特点:所有节点在同一时间基准上动作
  • 缺点:SYNC报文丢失会导致整周期数据失效

异步PDO(Asynchronous PDO)

由事件触发。比如数据变化、定时器到期、远程帧请求等。适合单轴控制、状态监测。

  • 传输类型:252~255(事件触发)、253(远程帧请求)
  • 特点:响应快,不依赖SYNC
  • 缺点:多个节点同时触发可能造成总线冲突
实战建议: 多轴同步必须用同步PDO,传输类型设为1(每个SYNC发一次)。单轴位置控制用异步PDO+事件触发就够了,别浪费总线带宽。

4.3 PDO映射:管道里到底装什么?

PDO映射就是告诉设备:这个PDO报文里,第1个字节是什么,第2个字节是什么。映射关系写在对象字典的0x1A00~0x1A03(TPDO映射)和0x1600~0x1603(RPDO映射)里。

举个例子,我想让TPDO1发“实际位置+实际速度”:

// 对象字典配置(以CiA 402标准为例)
0x1A00 sub0 = 2          // 映射对象数量
0x1A00 sub1 = 0x60640020 // 实际位置,32位
0x1A00 sub2 = 0x606C0010 // 实际速度,16位

// 映射值解析:
// 0x60640020 → 索引0x6064,子索引0x00,长度32位
// 0x606C0010 → 索引0x606C,子索引0x00,长度16位

映射格式是固定的:索引(16位) + 子索引(8位) + 长度(8位),拼成一个32位值。写错了设备会报错,我调试时经常因为长度写错位导致数据对不上。

注意: 修改映射前必须先停止PDO通信(将对应PDO的COB-ID最高位置1)。运行时改映射,轻则数据错乱,重则总线离线。我曾经在生产线上遇到过,教训深刻。

4.4 事件定时器与禁止时间:控制发送节奏

这两个参数是异步PDO的“节流阀”。没有它们,数据变化一次就发一次,总线可能被冲垮。

事件定时器(Event Timer)

定义在0x1800~0x1803的子索引5。单位毫秒。定时器到期就触发一次PDO发送,不管数据有没有变化。

  • 典型值:10ms(100Hz)、50ms(20Hz)、100ms(10Hz)
  • 设为0表示禁用定时器触发

禁止时间(Inhibit Time)

定义在0x1800~0x1803的子索引3。单位100微秒。两次PDO发送之间的最小间隔。

  • 典型值:100(即10ms禁止时间)
  • 防止数据频繁变化时总线被刷屏
参数 对象字典位置 单位 作用
事件定时器 0x1800~0x1803 sub5 ms 周期触发PDO发送
禁止时间 0x1800~0x1803 sub3 100μs 最小发送间隔
经验值: 电机电流环一般用1ms周期,速度环2~5ms,位置环10~20ms。事件定时器设得比控制周期略大一点,避免数据冗余。

4.5 传输类型详解:一张表说清楚

PDO传输类型(0x1800~0x1803 sub2)决定了PDO的触发方式。我整理了一张速查表,调试时贴在工位上很管用:

类型值 触发方式 同步/异步 典型场景
0 每个SYNC发一次,但数据由事件更新 同步 同步采集+事件触发更新
1 每个SYNC发一次 同步 多轴同步控制
2~240 每N个SYNC发一次 同步 降频同步(如每5个SYNC发一次)
252 事件触发+定时器触发 异步 状态监测
253 远程帧请求触发 异步 主站按需读取
254 制造商特定 异步 定制功能
255 事件触发(数据变化) 异步 快速响应变化

嗯,这里要注意:类型255虽然响应最快,但如果数据在短时间内剧烈抖动(比如编码器噪声),总线会被无效报文塞满。我建议配合禁止时间一起用,设个5~10ms的最小间隔。

4.6 核心逻辑图:PDO通信全流程

下面这张图把TPDO从配置到发送的完整路径画出来了。我每次培训新人都拿这张图讲,比看半天文档管用。

PDO通信全流程(以TPDO为例) 对象字典 0x1A00映射配置 PDO映射 数据打包成8字节 传输类型 同步/异步选择 同步路径 等待SYNC报文 异步路径 事件/定时器触发 禁止时间检查 最小间隔过滤 CAN总线发送 COB-ID + 8字节数据 说明: 同步路径:等待SYNC→打包数据→禁止时间检查→发送;异步路径:事件/定时器触发→打包数据→禁止时间检查→发送。

4.7 避坑指南:我踩过的PDO坑

做CANopen这些年,PDO相关的坑我踩了不少。挑几个典型的说说:

  • 映射长度不对齐:比如映射了3个16位数据,总长度6字节,但CAN报文是8字节。剩下的2字节是随机值,接收方如果没做掩码处理,数据会跳变。我后来强制要求所有PDO映射总长度必须是8的倍数,不够的补0。
  • 禁止时间设太小:有一次把禁止时间设为10(即1ms),结果数据变化频繁时,总线负载率直接飙到80%。后来改到100(10ms),问题解决。
  • 同步PDO的SYNC丢失:SYNC报文优先级不够高,被其他报文挤掉了。我建议把SYNC的COB-ID设为0x80,优先级最高,并且主站要加超时重发机制。
  • 运行时改映射:这个前面提过,但值得再说一遍——改映射前必须停PDO,否则设备行为不可预测。我见过有人在线改映射导致驱动器直接进入错误状态。
重要: 如果你用CANopenNode,PDO配置在CO_PDO.c里。修改映射后要调用CO_PDO_init()重新初始化,否则新映射不生效。这个细节文档里没写,我是读源码才发现的。