第2章:CAN数据帧结构:标准帧与扩展帧、仲裁场、控制场、数据场、CRC校验场

各位同学,咱们今天聊聊CAN数据帧的结构。说实话,搞了这么多年医疗嵌入式,CAN帧结构是我觉得最值得吃透的东西。你想想看,一个医疗设备里,传感器采集的数据要准确无误地传到主控,靠的就是这个帧结构。

我个人习惯把CAN帧比作一个快递包裹。包裹外面写地址(仲裁场),里面装东西(数据场),最后还要贴个防拆标签(CRC校验)。嗯,这个比喻虽然简单,但很实用。

2.1 标准帧 vs 扩展帧

CAN协议最早只有标准帧,11位标识符。后来发现设备多了,11位不够用,就出了扩展帧,29位标识符。我在项目中遇到过不少新手搞混这两者,结果通信死活不通。

两者的核心区别就两点:

  • 标识符长度:标准帧11位,扩展帧29位
  • 帧格式标志:IDE位(Identifier Extension)决定是标准还是扩展

重要提醒:标准帧和扩展帧可以在同一总线上共存。但要注意,扩展帧的优先级不一定比标准帧低,这取决于具体的标识符值。

我曾经在一个心电监护项目里,就因为标准帧和扩展帧混用,导致数据采集卡顿。排查了两天才发现,是某个传感器用了扩展帧,而主控只配置了标准帧滤波。说白了,就是滤波配置没跟上。

2.2 仲裁场:谁先说话?

仲裁场是CAN协议的精华所在。为什么这么说?因为它解决了多设备同时发送时的冲突问题。

仲裁场包含:

  • 标识符:标准帧11位,扩展帧29位
  • RTR位:Remote Transmission Request,区分数据帧和远程帧
  • IDE位:标准帧为显性(0),扩展帧为隐性(1)
  • SRR位:仅扩展帧有,替代标准帧的RTR位

仲裁的规则很简单:谁标识符小,谁优先级高。显性位(0)会覆盖隐性位(1)。你想想看,这就像开会时,职位高的人先发言。标识符越小,相当于职位越高。

实战技巧:在医疗设备中,生命体征数据(如心率、血氧)的标识符要设得小一些,保证高优先级。而配置参数、日志信息可以设大一些。我一般把报警数据放在0x100以内,普通数据放在0x200以上。

2.3 控制场:数据长度的管家

控制场只有6位,但作用不小。它告诉接收方:我这帧数据有多长。

控制场的结构:

  • IDE位:扩展帧标志(标准帧中为保留位)
  • 保留位r0:标准帧和扩展帧都有
  • 保留位r1:仅扩展帧有
  • DLC:Data Length Code,4位,表示数据场字节数(0-8)

DLC的取值范围是0到8,对应数据场0到8个字节。我记得有个同事在调试时,DLC设成了9,结果CAN控制器直接报错。嗯,这里要注意,DLC最大就是8,别超了。

DLC值 数据场长度(字节) 常见用途
0 0 远程帧、心跳包
1-4 1-4 传感器单值数据
5-8 5-8 多通道数据、波形数据

2.4 数据场:真正的干货

数据场是CAN帧里最灵活的部分。0到8个字节,你想怎么用都行。但说实话,怎么用好这8个字节,才是体现功力的地方。

我在医疗设备项目中,通常这样分配数据场:

  • 字节0-1:数据ID或命令码
  • 字节2-3:主数据值(如心率值、血压值)
  • 字节4-5:辅助数据(如信号质量、报警等级)
  • 字节6-7:校验或时间戳

避坑指南:我曾经在一个项目中,把数据场塞得满满当当,8个字节全用上。结果发现,有些传感器数据更新频率高,但数据量小,浪费了带宽。后来我改成:高频小数据用2字节,低频大数据用8字节。说白了,就是按需分配,别一刀切。

2.5 CRC校验场:数据的守护神

CRC校验场是CAN帧的最后一道防线。它用15位CRC校验码,加上1位CRC分隔符,共16位。

CRC的计算范围包括:帧起始、仲裁场、控制场、数据场。但不包括CRC场本身和后面的ACK场。

为什么CRC这么重要?你想想看,医疗设备的数据要是传错了,后果不堪设想。心率80传成180,血压120传成200,这可不是闹着玩的。

CAN协议用的是CRC-15多项式:x¹⁵ + x¹⁴ + x¹⁰ + x⁸ + x⁷ + x⁴ + x³ + 1。这个多项式能检测出:

  • 所有单比特错误
  • 所有双比特错误
  • 所有奇数个错误
  • 所有长度≤15的突发错误
  • 99.997%的长度为16的突发错误
  • 99.998%的长度≥17的突发错误

嗯,这个数据够硬吧?所以我说CRC是数据守护神,一点不夸张。

个人经验:我建议在接收端做双重校验。第一重是硬件CRC校验,CAN控制器会自动完成。第二重是软件校验,对关键数据(如用药剂量、报警阈值)再做一次CRC或累加和校验。虽然增加了开销,但安全第一嘛。

2.6 完整帧结构一览

把上面这些拼起来,一个完整的CAN数据帧长这样:

标准帧:
| SOF | 11位标识符 | RTR | IDE | r0 | DLC | 0-8字节数据 | 15位CRC | CRC分隔符 | ACK | ACK分隔符 | EOF |
|  1  |     11     |  1  |  1  | 1  |  4  |    0-64    |   15    |     1     |  1  |     1     |  7  |

扩展帧:
| SOF | 11位标识符 | SRR | IDE | 18位标识符 | RTR | r1 | r0 | DLC | 0-8字节数据 | 15位CRC | CRC分隔符 | ACK | ACK分隔符 | EOF |
|  1  |     11     |  1  |  1  |     18     |  1  | 1  | 1  |  4  |    0-64    |   15    |     1     |  1  |     1     |  7  |

标准帧总共44位(不含数据场),扩展帧总共64位(不含数据场)。加上数据场后,最长帧是标准帧108位,扩展帧128位。再加上位填充,实际传输的位数会多一些。

好了,CAN数据帧的结构就讲到这里。下一章咱们聊聊CAN的位时序和同步,这可是保证通信稳定的关键。有什么问题,咱们课上交流。