第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的位时序和同步,这可是保证通信稳定的关键。有什么问题,咱们课上交流。