AUTOSAR Classic CAN 模块详解:作用、原理、配置与协作关系
说明:本文所说的 CAN 模块,特指 AUTOSAR Classic 中的 Can Driver / Can MCAL,也就是直接控制 CAN 控制器硬件的底层驱动模块。
它不是“整条 CAN 通信栈”的统称,而是这条链路里最靠近硬件的一层。
1. CAN 模块是什么?
在 AUTOSAR Classic 架构中,CAN 模块位于 MCAL(Microcontroller Abstraction Layer),负责把上层发下来的报文请求,转换为 CAN 控制器能够执行的收发动作;同时把硬件收到的报文,向上通知给 CanIf,再继续上传到 PduR、COM 等模块。
你可以把它理解成:
- 上层:关心“发什么报文、收什么报文”
- CAN 模块:关心“怎么把报文真正送上总线、怎么从总线上接回来”
- 硬件:真正完成仲裁、位时序、发送、接收、错误检测
2. CAN 模块的作用
CAN 模块的核心职责可以概括为 5 点:
- 控制 CAN 控制器硬件:初始化控制器、切换模式、设置波特率、进入睡眠/唤醒、处理中断等。
- 发送和接收报文:将上层传来的 L-PDU 交给硬件发送;将硬件接收到的帧转交给上层。
- 配置和管理硬件对象:管理发送/接收邮箱、FIFO、过滤器、硬件对象句柄等。
- 处理总线错误和状态变化:包括 bus-off、error passive、error warning 等状态通知与恢复控制。
- 为上层模块提供统一接口:上层不用直接访问寄存器,而是通过 AUTOSAR 标准 API 与 CAN 模块交互。
3. CAN 模块在 AUTOSAR 通信栈中的位置
flowchart LR
APP[应用层 / SWC] --> COM[COM]
COM --> PDUR[PduR]
PDUR --> CANIF[CanIf]
CANIF --> CAN[Can Driver]
CAN --> HW[CAN Controller / Mailbox / FIFO]
HW --> BUS[(CAN Bus)]
3.1 各层职责一句话理解
- COM:把信号打包成 I-PDU
- PduR:负责 PDU 路由
- CanIf:做 CAN 协议接口适配,连接上层与 CAN Driver
- CAN:直接操作 CAN 控制器硬件
- CAN Controller:真正完成物理总线收发
4. CAN 模块的工作原理
CAN 模块的工作原理,最适合从 发送路径 和 接收路径 两条线来理解。
4.1 发送流程
- 上层 COM 形成一个 I-PDU
- PduR 将该 PDU 路由到 CanIf
- CanIf 根据映射关系,找到对应的 CAN 硬件对象(HTH)
- CanIf 调用 Can_Write()
- CAN 模块把数据写入发送邮箱/FIFO
- CAN 控制器在总线空闲时发出报文
- 发送完成后,CAN 模块通知 CanIf,再逐级回调上层
4.2 接收流程
- CAN 控制器在总线上收到一帧报文
- 控制器根据硬件过滤器判断是否接收
- 接收中断触发,或由轮询任务读取
- CAN 模块取出报文数据
- 通过 CanIf 上报给 PduR
- 最终由 COM 还原为信号
sequenceDiagram
participant COM as COM
participant PduR as PduR
participant CanIf as CanIf
participant Can as CAN Driver
participant HW as CAN Controller
COM->>PduR: 发送 I-PDU
PduR->>CanIf: 路由到 CAN
CanIf->>Can: Can_Write(HTH, L-PDU)
Can->>HW: 写发送邮箱/触发发送
HW-->>Can: 发送完成中断
Can-->>CanIf: Can_TxConfirmation()
CanIf-->>PduR: Tx Confirmation
PduR-->>COM: 发送确认
sequenceDiagram
participant BUS as CAN Bus
participant HW as CAN Controller
participant Can as CAN Driver
participant CanIf as CanIf
participant PduR as PduR
participant COM as COM
BUS->>HW: 报文到达
HW->>Can: Rx 中断 / 轮询通知
Can->>CanIf: CanIf_RxIndication()
CanIf->>PduR: 上报收到的 L-PDU
PduR->>COM: Com_RxIndication()
COM->>COM: 解包成信号
4.3 为什么 CAN 能“优先级仲裁”?
CAN 的仲裁机制基于 报文 ID:
- ID 数值越小,优先级越高
- 多个节点同时发送时,优先级高的报文能赢得总线
- 这也是 CAN 在车身、底盘、动力等系统中常见的原因之一
4.4 中断模式和轮询模式
CAN 模块通常既支持:
- 中断方式:收发完成后立即通知,实时性更好
- 轮询方式:由周期任务读取状态,适合某些简化或特殊场景
实际项目里,很多平台会把二者结合使用:例如 Rx 用中断,Bus-off 或错误状态用周期轮询补充处理。
5. CAN 模块的典型配置项及作用
说明:以下配置名采用常见/典型名称表达,不同工具链、不同 AUTOSAR 版本里名字可能略有差异,但含义基本一致。
| 常见/典型名称 | 作用 | 说明 |
|---|---|---|
| CanDevErrorDetect | 开发错误检测 | 开启后会检查非法参数、未初始化调用等问题,便于集成调试 |
| CanVersionInfoApi | 版本信息接口 | 允许上层查询 CAN 模块版本 |
| CanSetBaudrateApi | 运行时修改波特率 | 支持在运行阶段切换波特率,常用于诊断、刷写或特殊模式 |
| CanGetControllerErrorStateApi | 获取控制器错误状态 | 便于诊断 CAN 控制器是否处于 error passive / bus-off 等状态 |
| CanWakeupSupport | 唤醒支持 | 配合低功耗场景,支持从 sleep/wakeup 相关流程 |
| CanBusOffProcessing | Bus-off 处理方式 | 定义 bus-off 后是中断通知、轮询处理还是由上层统一处理 |
| CanMainFunctionRead/Write/BusOff/Wakeup | 主函数轮询接口 | 若项目采用轮询方式,需要周期调用这些主函数 |
| CanControllerId | 控制器编号 | 区分 MCU 上的多个 CAN 控制器实例 |
| CanControllerActivation | 控制器初始激活状态 | 决定初始化后是否立即可用 |
| CanControllerDefaultBaudrate | 默认波特率 | 控制器初始化后默认使用的速率 |
| CanControllerBaudRateConfig | 波特率配置集 | 保存某个波特率方案的完整位时序参数 |
| CanBitRatePrescaler | 预分频 | 影响 CAN 时钟分频,是位时序的基础参数 |
| CanSyncJumpWidth | SJW | 同步跳转宽度,用于时钟偏差补偿 |
| CanTimeSeg1 / CanTimeSeg2 | 位段配置 | 决定采样点与位时序分配 |
| CanControllerMode | 控制器模式 | 常见有 STARTED / STOPPED / SLEEP |
| CanHardwareObject | 硬件对象配置项 | 定义一个邮箱/FIFO/对象组 |
| CanHandleType | 句柄类型 | 常见为 BASIC / FULL,决定接收/发送管理方式 |
| CanObjectType | 对象方向 | TRANSMIT 或 RECEIVE |
| CanIdType | 标识符类型 | STANDARD(11 bit)或 EXTENDED(29 bit) |
| CanHwObjectCount | 对象数量 | 一组硬件对象可管理多少个邮箱/槽位 |
| CanFilterMask / CanAcceptanceMask | 接收过滤掩码 | 决定哪些 ID 能被硬件接收 |
| CanControllerRef | 所属控制器引用 | 一个 HOH 归属哪个 CAN 控制器 |
| CanHwObjectRef / CanMailboxRef | 硬件邮箱引用 | 与具体硬件邮箱对应,便于映射 |
| CanRxProcessing | 接收处理方式 | 中断还是轮询读取接收报文 |
| CanTxProcessing | 发送处理方式 | 发送完成通知方式 |
| CanInterruptEnable | 中断使能 | 是否启用发送/接收/错误中断 |
| CanWakeupSource | 唤醒源配置 | 指定哪个控制器/通道支持唤醒 |
| CanAutoBusOffRecovery | 自动 Bus-off 恢复 | 是否支持自动恢复或由上层控制恢复 |
6. CANIF、PDUR、COM 与 CAN 模块的关系
这三者和 CAN 模块的关系,可以用一句话概括:
COM 负责“内容”,PduR 负责“路由”,CanIf 负责“接口适配”,CAN 负责“硬件执行”。
COM 负责信号级处理;PduR 负责 PDU 路由;CanIf 负责把上层 PDU 映射到 CAN 硬件对象;CAN 模块直接对接硬件,真正完成发帧、收帧、控制器模式切换、错误状态处理等。
flowchart TB
COM[COM: 信号打包/解包] --> PDUR[PduR: PDU 路由]
PDUR --> CANIF[CanIf: CAN 接口适配]
CANIF --> CAN[Can Driver: 硬件驱动]
CAN --> CTRL[CAN Controller]
CTRL --> BUS[(CAN Bus)]
BUS --> CTRL
CTRL --> CAN
CAN --> CANIF
CANIF --> PDUR
PDUR --> COM
7. CAN 模块的常见使用场景
- 动力域/底盘域实时报文:如发动机转速、扭矩请求、制动状态、转向状态等。
- 车身域控制:如门锁、灯光、雨刮、空调面板等。
- 网关通信:配合网关逻辑实现不同 CAN 网络、或 CAN 与其他总线之间的转发。
- UDS 诊断与刷写:诊断服务、Bootloader 刷写、在线升级等。
- 低功耗唤醒:与 CanTrcv、EcuM、BswM 协同工作。
- 测试与标定:测试台架、HIL、产线刷写、日志采集等。
8. 一个更容易记住的理解方式
如果把 AUTOSAR CAN 通信链路比作“物流系统”:COM 是打包货物,PduR 是分拣中心,CanIf 是仓库出入口管理员,CAN 模块是叉车和装卸设备,CAN Controller 是真正把货物送上运输带(总线)。
10. 结语
CAN 模块在 AUTOSAR Classic 中属于“看起来很底层,但实际非常关键”的模块。它不负责信号语义,不负责路由逻辑,但它决定了通信是否真的能稳定地在总线上跑起来。
COM 关心“发什么”,PduR 关心“发给谁”,CanIf 关心“怎么映射”,CAN 关心“如何把它真正发到总线上”。