1. CAN协议基础回顾:CAN总线物理层与数据链路层核心概念
CAN(Controller Area Network)总线自1980年代由Bosch公司开发以来,已成为嵌入式系统中应用最广泛的现场总线之一。在MCU驱动开发中,理解CAN的物理层与数据链路层是进行报文过滤与ID分配优化的前提。本章从底层机制出发,梳理核心概念,为后续中断模式下的驱动实现奠定理论基础。
1.1 物理层:差分信号与总线拓扑
CAN总线物理层采用差分信号传输,通过两条线——CAN_H(高电平线)和CAN_L(低电平线)——之间的电压差来表示逻辑状态。这种设计提供了极强的共模噪声抑制能力,适用于电磁环境复杂的工业与汽车场景。
| 逻辑状态 | CAN_H电压 | CAN_L电压 | 差分电压 (Vdiff) |
|---|---|---|---|
| 显性 (Dominant) | ≈ 3.5 V | ≈ 1.5 V | ≈ 2.0 V |
| 隐性 (Recessive) | ≈ 2.5 V | ≈ 2.5 V | ≈ 0 V |
总线两端必须各接一个120 Ω终端电阻,用于匹配阻抗、抑制信号反射。标准CAN(ISO 11898-2)的最高速率可达1 Mbps,而CAN FD(灵活数据速率)在数据段可提升至8 Mbps以上。
1.2 数据链路层:报文格式与仲裁机制
CAN数据链路层定义了完整的报文传输规则,包括帧格式、错误检测、位填充和仲裁。MCU驱动开发中最常打交道的两类帧是数据帧和远程帧,其中数据帧又分为标准格式(11位ID)和扩展格式(29位ID)。
1.2.1 标准数据帧结构
| 字段 | 位数 | 说明 |
|---|---|---|
| SOF (Start of Frame) | 1 | 显性位,同步所有节点 |
| Identifier (ID) | 11 | 报文优先级标识,数值越小优先级越高 |
| RTR (Remote Transmission Request) | 1 | 显性=数据帧,隐性=远程帧 |
| IDE (Identifier Extension) | 1 | 显性=标准格式,隐性=扩展格式 |
| DLC (Data Length Code) | 4 | 数据字节数(0~8) |
| Data Field | 0~64 | 实际数据负载 |
| CRC (Cyclic Redundancy Check) | 15 | 校验数据完整性 |
| ACK (Acknowledgment) | 2 | 接收节点确认 |
| EOF (End of Frame) | 7 | 隐性位序列,帧结束标志 |
1.2.2 非破坏性位仲裁
当多个节点同时发送时,CAN总线通过线与逻辑实现仲裁:每个节点在发送ID位的同时监听总线电平。如果发送的隐性位被显性位覆盖,该节点立即退出竞争,转为接收模式。ID数值最小的报文获得总线访问权。
1.3 报文过滤与ID分配基础
在MCU驱动中,报文过滤是降低CPU负载的核心手段。CAN控制器内置硬件过滤机制,通过验收滤波器(Acceptance Filter)决定哪些报文进入接收缓冲区,哪些被丢弃。
1.3.1 过滤模式对比
| 过滤模式 | 原理 | 适用场景 | 灵活性 |
|---|---|---|---|
| 掩码模式 | ID + 掩码,匹配ID中指定比特位 | 批量过滤一组连续ID | 中等 |
| 列表模式 | 预设多个ID,精确匹配 | 只接收少数特定ID | 高 |
| 范围模式 | 定义ID起始和结束范围 | 接收一段连续ID区间 | 高 |
1.3.2 标准ID vs 扩展ID的过滤差异
标准CAN控制器通常提供2~4个过滤组,每个过滤组可配置为11位或29位模式。扩展ID的过滤需要更多硬件资源,因为29位ID的掩码比较需要更多逻辑门。在MCU驱动中,如果系统不需要扩展ID,建议关闭扩展帧接收,以释放过滤资源。
1.4 位时序与同步机制
CAN总线采用位同步机制保证多节点在无统一时钟下的可靠通信。每个位时间被划分为4个段:
- 同步段 (Sync_Seg):1个时间量子,用于检测边沿同步
- 传播段 (Prop_Seg):补偿物理延迟
- 相位缓冲段1 (Phase_Seg1):采样点前调整
- 相位缓冲段2 (Phase_Seg2):采样点后调整
1.5 错误处理机制
CAN协议定义了5种错误类型,MCU驱动必须正确处理这些错误状态:
| 错误类型 | 检测位置 | 典型原因 |
|---|---|---|
| 位错误 | 发送节点 | 发送位与总线电平不一致 |
| 填充错误 | 接收节点 | 连续6个相同位(违反位填充规则) |
| CRC错误 | 接收节点 | CRC校验和与本地计算不匹配 |
| 格式错误 | 接收节点 | 固定格式位(如EOF、ACK)电平错误 |
| ACK错误 | 发送节点 | 无节点在ACK槽发送显性位 |