4. PDO通信机制:TPDO与RPDO配置、通信参数与映射参数、同步与异步传输
PDO,说白了就是CANopen里跑实时数据的通道。我刚开始接触CANopen时,总觉得PDO和SDO差不多,都是收发数据嘛。后来被现场总线折腾了几回才明白——这俩完全是两码事。
SDO像快递,点对点,确认送达,但慢。PDO像广播,一发出去所有人都能收到,快,但不保证对方一定接着了。工业I/O从站要的就是快,所以PDO才是主力。
4.1 TPDO与RPDO:谁发谁收?
先搞清楚方向:
- TPDO(Transmit PDO):从站往外发数据。比如我采集到传感器值,通过TPDO告诉主站。
- RPDO(Receive PDO):从站接收数据。比如主站发来一个输出指令,从站通过RPDO拿到。
每个从站最多支持4个TPDO和4个RPDO,编号从1到4。嗯,这是标准规定的上限,实际芯片资源够不够另说。
关键点:TPDO和RPDO的编号是独立的。TPDO1和RPDO1没有绑定关系,别搞混了。
4.2 通信参数:谁来决定什么时候发?
PDO不能乱发,得有个规矩。通信参数就是管这个的。每个PDO对应一个通信参数对象,索引从0x1800开始(TPDO1)到0x1A00(RPDO4)。
通信参数里最重要的几个字段:
| 子索引 | 名称 | 说明 |
|---|---|---|
| 0x01 | COB-ID | PDO的CAN标识符,决定优先级 |
| 0x02 | 传输类型 | 0~255,决定触发方式 |
| 0x03 | 禁止时间 | 最小发送间隔,单位100μs |
| 0x05 | 事件定时器 | 周期发送时间,单位ms |
传输类型是重点,我单独列一下:
- 0:同步非周期。收到SYNC后发一次,但只发一次。
- 1~240:同步周期。每收到N个SYNC发一次,N就是类型值。
- 254:异步,由事件触发(数据变化或定时器到)。
- 255:异步,由远程帧触发(RPDO专用)。
我在项目里最常用的是类型254和类型1。254适合传感器数据,变了就发;1适合周期性状态上报,比如每10个SYNC报一次。
小技巧:禁止时间别设太短。我曾经设成0,结果数据变化快的时候CAN总线直接被PDO淹没了。建议至少设10(即1ms)。
4.3 映射参数:数据怎么装进PDO?
通信参数管什么时候发,映射参数管发什么。每个PDO的映射参数对象索引从0x1A00(TPDO1)到0x1B00(RPDO4)。
映射参数的结构很简单:
- 子索引0:映射对象数量(最多8个)。
- 子索引1~8:每个映射项,32位,格式为:
索引(16位) + 子索引(8位) + 位长度(8位)。
举个例子,我想把TPDO1映射成:
- 第1字节:数字量输入(0x6000, 子索引01, 8位)
- 第2~3字节:模拟量输入1(0x6401, 子索引01, 16位)
- 第4~5字节:模拟量输入2(0x6401, 子索引02, 16位)
映射参数就是:
子索引0 = 3 // 3个映射项
子索引1 = 0x60000108 // 索引0x6000, 子索引01, 8位
子索引2 = 0x64010110 // 索引0x6401, 子索引01, 16位
子索引3 = 0x64010210 // 索引0x6401, 子索引02, 16位
注意,所有映射项的总位数不能超过64位(8字节)。PDO报文最长就8字节,装不下更多。
踩坑提醒:我曾经把映射项总位数算成65位,结果从站直接进入预操作状态,主站怎么都启不了。查了半天才发现是映射超了。记住,64位是硬上限。
4.4 同步传输 vs 异步传输
同步和异步,说白了就是PDO的触发时机不同。
同步传输:
- 依赖SYNC报文。主站定期发SYNC,所有从站收到后统一行动。
- 好处是确定性高,所有节点在同一时刻采样或输出。
- 适合运动控制、多轴同步这类场景。
- 传输类型设成0或1~240。
异步传输:
- 不依赖SYNC。数据变了就发,或者定时器到了就发。
- 好处是响应快,数据变化立刻上报。
- 适合传感器采集、状态监测这类场景。
- 传输类型设成254或255。
我个人的习惯是:如果系统里有超过3个从站需要同步,就用同步模式。如果只是几个I/O点,异步就够了,省得折腾SYNC周期。
下面这张图能帮你理清PDO的整体流程:
4.5 实战配置步骤
在CANopenNode里配PDO,我一般按这个顺序来:
- 确定需求:哪些数据要实时交换?用TPDO还是RPDO?
- 配置映射参数:把对象字典里的数据映射到PDO里。
- 配置通信参数:设COB-ID、传输类型、禁止时间、事件定时器。
- 使能PDO:把COB-ID的最高位清0,PDO才能用。
- 测试:发SYNC或改变数据,看PDO有没有正常收发。
举个例子,我要配一个TPDO1,异步触发,映射数字量输入:
// 通信参数:TPDO1,索引0x1800
0x1800[0x01] = 0x40000180 + NodeID; // COB-ID,标准帧
0x1800[0x02] = 254; // 异步,事件触发
0x1800[0x03] = 10; // 禁止时间1ms
0x1800[0x05] = 0; // 事件定时器关闭
// 映射参数:TPDO1,索引0x1A00
0x1A00[0x00] = 1; // 1个映射项
0x1A00[0x01] = 0x60000108; // 数字量输入,8位
嗯,这里要注意:COB-ID的计算公式是 0x40000180 + NodeID。0x40000000是PDO的固定前缀,0x180是TPDO1的基地址,NodeID是从站地址。比如NodeID=5,COB-ID就是0x40000185。
经验之谈:我建议在配置完成后,用CAN分析仪抓一下报文。看看PDO的COB-ID对不对,数据长度对不对,触发时机对不对。抓一次报文,胜过看十遍文档。
4.6 常见问题与避坑
- PDO发不出来? 检查COB-ID的最高位是不是0。最高位为1表示PDO禁用,这是出厂默认值。
- 数据不对? 检查映射参数的位长度。比如16位数据映射成8位,数据肯定丢。
- 总线冲突? 检查COB-ID有没有重复。两个节点用同一个COB-ID,CAN总线会报错。
- 同步模式没反应? 检查主站有没有发SYNC。没有SYNC,同步PDO永远不会触发。
我曾经在一个项目里,从站死活不发TPDO。查了两天,最后发现是COB-ID的最高位没清0。嗯,从那以后我每次配PDO,第一件事就是检查COB-ID。
PDO的配置其实不难,关键是理解通信参数和映射参数的关系。通信参数管什么时候发,映射参数管发什么,两者配合好了,PDO就能按你的意愿工作。