FPGA 实现 CAN 总线接口与数据帧解析
CAN 总线在工业现场和汽车电子中应用极其广泛,它的可靠性、实时性和多主特性是 UART、SPI、I2C 无法比拟的。从零实现一个完整的 CAN 控制器确实有一定复杂度,但掌握核心的数据帧收发和解析能力,就能应对大多数 FPGA 与 CAN 总线交互的场景。下面我带你一步步落地。
1. 先理解 CAN 协议的核心特点
在写代码前,必须理解 CAN 总线与众不同的地方:
| 特性 | 说明 |
|---|---|
| 物理层 | 差分信号(CAN_H 和 CAN_L),显性(逻辑 0)覆盖隐性(逻辑 1) |
| 多主通信 | 任何节点都可主动发送,通过标识符(ID)仲裁决定谁获得总线控制权 |
| 非破坏性仲裁 | ID 值越小(显性位越多),优先级越高。仲裁失败的节点自动转为接收 |
| 短帧结构 | 一帧最多携带 8 字节数据,有效降低干扰概率 |
| 强大的检错机制 | CRC 校验、位填充、格式检查、应答确认等 |
对比一下:UART 需要约定波特率,SPI 需要片选线,I2C 有地址。而 CAN 的仲裁机制使得多个节点可以同时发送,靠 ID 决定谁说话,这是它最核心的魅力。
2. CAN 数据帧结构详解
我们最常用的是标准数据帧(CAN2.0A),它的组成如下:
帧起始 (1bit) + 仲裁段 (12bit) + 控制段 (6bit) + 数据段 (0~8byte) + CRC 段 (16bit) + ACK 段 (2bit) + 帧结束 (7bit)
逐段拆解:
- 帧起始(SOF):1 个显性位(0),标志一帧开始,用于同步。
- 仲裁段:
- 11 位标识符(ID),高位先发。
- RTR 位(远程传输请求):数据帧为显性(0),远程帧为隐性(1)。
- 控制段:
- IDE 位(标识符扩展):标准帧为显性(0)。
- 保留位 r0(显性)。
- DLC(数据长度码):4 位,表示数据段字节数(0~8)。
- 数据段:0~8 字节,MSB 先行。
- CRC 段:15 位 CRC 校验码 + 1 位隐性 CRC 界定符。
- ACK 段:发送节点发送 2 位隐性位,接收节点在 ACK 槽位发送显性位应答。
- 帧结束:7 个隐性位(1)。
扩展帧(CAN2.0B)有 29 位 ID,我们暂不涉及。

