3、CAN数据帧结构:标准帧与扩展帧的区别、ID仲裁机制、数据场与CRC校验
好,咱们今天聊聊CAN数据帧。说实话,这个知识点是CAN通信的基石。你搞不懂帧结构,后面调试起来会非常痛苦。我当年刚入行时,就因为搞混了标准帧和扩展帧,浪费了整整两天时间。
3.1 标准帧 vs 扩展帧:到底差在哪?
CAN总线有两种帧格式:标准帧和扩展帧。说白了,就是ID长度的区别。
- 标准帧:11位ID,帧头更短,传输效率高
- 扩展帧:29位ID,帧头更长,但能容纳更多节点
你想想看,11位ID最多支持2^11=2048个不同的ID。对于呼吸机这种设备,通常够用了。但如果是大型医疗系统,比如整个ICU的联网监控,29位ID就很有必要。
关键区别点:IDE位(Identifier Extension Bit)
- IDE=0:标准帧
- IDE=1:扩展帧
我在项目中遇到过一个问题:某款呼吸机的主控板和传感器板,一个用标准帧,一个用扩展帧,结果死活通信不上。查了半天才发现,是IDE位配置不一致。嗯,这里要注意,同一网络里所有节点必须统一帧格式。
3.2 ID仲裁机制:谁说了算?
CAN总线的仲裁机制,我觉得是它最巧妙的设计。多个节点同时发送时,不会冲突,而是按优先级来。
仲裁规则很简单:ID越小,优先级越高。
为什么?因为CAN总线是“线与”逻辑。显性电平(0)会覆盖隐性电平(1)。所以ID中0越靠前,这个节点就越“强势”。
实战建议:
- 呼吸机的主控报警信号,ID设小一点,比如0x001
- 普通传感器数据,ID设大一点,比如0x100
- 这样紧急数据总能优先发送
我曾经犯过一个错:把呼吸机的压力传感器ID设成了0x010,而报警信号设成了0x100。结果报警信号老是发不出去,因为压力数据太频繁了。后来我把报警ID改成0x001,问题立刻解决。你想想看,这就是优先级没规划好的后果。
3.3 数据场:你到底要传什么?
CAN数据帧的数据场,最多8个字节。为什么是8个?因为CAN总线设计时考虑的是实时控制,8字节足够传递关键参数了。
对于呼吸机,我一般这样分配数据场:
| 字节位置 | 内容 | 说明 |
|---|---|---|
| Byte 0 | 命令/状态码 | 0x01=请求数据,0x02=报警 |
| Byte 1-2 | 压力值 | 16位整数,单位0.1cmH2O |
| Byte 3-4 | 流量值 | 16位整数,单位0.1L/min |
| Byte 5-6 | 氧浓度 | 16位整数,单位0.1% |
| Byte 7 | 校验和 | 简单累加校验 |
我个人习惯把最重要的参数放在前两个字节。因为有些CAN控制器支持“只接收前几个字节”的模式,这样能提高处理效率。
3.4 CRC校验:别让数据出错
CAN帧自带15位CRC校验。这个CRC覆盖了帧起始、仲裁场、控制场和数据场。说白了,除了ACK位和帧结束,其他都校验了。
CRC算法是固定的:CRC-15,生成多项式是x^15 + x^14 + x^10 + x^8 + x^7 + x^4 + x^3 + 1。
你不用自己算,CAN控制器硬件会自动完成。但有一点要注意:
我曾经踩过的坑:
有一次呼吸机在强电磁干扰环境下,CRC错误率飙升。我以为是硬件问题,查了半天发现是CAN控制器的时钟精度不够。CAN要求时钟误差在1%以内,我那款芯片的晶振偏差到了1.5%。换了个高精度晶振,CRC错误率立刻降下来了。
所以,如果你发现CRC错误很多,别急着怀疑协议。先看看硬件时钟准不准。
3.5 完整的数据帧结构
咱们把整个标准帧串起来看看:
帧起始(1bit) + 仲裁场(12bit: 11位ID + RTR) + 控制场(6bit: IDE + r0 + DLC)
+ 数据场(0-64bit) + CRC场(16bit: 15位CRC + 1位CRC界定符)
+ ACK场(2bit) + 帧结束(7bit)
扩展帧就是把仲裁场的11位ID换成了29位,其他基本一样。
你想想看,一个标准帧最少44位,最多108位。对于1Mbps的CAN总线,传输一个帧也就几十微秒。这就是为什么CAN适合实时控制。
我的调试小技巧:
用逻辑分析仪抓CAN波形时,先看帧起始的下降沿。如果下降沿不陡峭,说明总线负载太重或者终端电阻有问题。我一般会在调试阶段把CAN总线速率降到250kbps,等通信稳定了再提上去。
好了,关于CAN数据帧结构,咱们就聊这么多。记住三点:标准帧和扩展帧别混用、ID越小优先级越高、数据场最多8字节。下一节咱们聊聊CAN的物理层和终端电阻配置,那个也是容易出问题的地方。