CANIF(CAN Interface)收发完整流程 + 实战举例(AUTOSAR 标准)
CANIF 是 AUTOSAR 通信层核心模块 ,承上(PDUR/COM)启下(CAN Driver/CAN 控制器),核心做:上层 I-PDU ↔ 底层 CAN 报文 映射、路由、收发调度、确认、滤波。
下面分 发送流程、接收流程 ,每一步配真实可落地的报文举例(含:上层发什么包、底层发什么包、总线上是什么、接收反向流程)。
一、前置基础(必须先懂)
1. 架构层级(从上到下)
COM → PDU Router(PDUR)→ CAN Interface(CANIF) → CAN Driver → CAN Controller → CAN Bus
2. 关键术语
- I-PDU:上层(COM/PDUR)与 CANIF 交互的单元(只含:数据 + 长度)
- CAN L-PDU:CANIF 与 CAN Driver 交互的单元(含:CAN ID、帧类型、DLC、数据)
- HOH(Hardware Object Handle):CAN 控制器硬件收发邮箱/缓冲区(TxHOH 发、RxHOH 收)
- TxConfirmation:发送完成回调(总线发成功后底层回传)
- RxIndication:接收到达回调(总线上有报文上传)
二、CANIF 发送(Tx)完整流程 + 逐步骤举例
1. 发送场景举例(固定参数,全程用)
我们要发:ECU 内部应用 → 总线 标准帧报文
- 上层 Tx I-PDU ID:
TxPduId = 0x05 - 目标 CAN 控制器:
CanController = 0(CAN1) - 映射 TxHOH(发送硬件句柄):
Hth = 1 - CAN ID(标准 11bit):
0x123 - 数据长度 DLC:
4 - 发送数据:
[0x11, 0x22, 0x33, 0x44] - 帧类型:标准帧(CAN_ID_STD)
2. 发送前关键配置(简化,实际由 ARXML 配置)
- Tx I-PDU 绑定 CAN ID、DLC、控制器
- Tx I-PDU 映射到 TxHOH(Hth=1)
- 使能发送确认回调
3. 完整发送流程(7 步,每步带实例)
步骤1:上层(PDUR/COM)调用 CANIF 发送 API
上层通过 CanIf_Transmit 下发 I-PDU(只有数据+长度,无 CAN ID)
c
// 上层调用(伪代码)
PduInfoType TxPduInfo;
TxPduInfo.SduDataPtr = &DataBuffer[0]; // [0x11,0x22,0x33,0x44]
TxPduInfo.SduLength = 4; // DLC=4
Std_ReturnType ret = CanIf_Transmit( TxPduId=0x05, &TxPduInfo );
✅ 上层发包格式(I-PDU):
- PduId: 0x05
- Length: 4
- Data: [0x11, 0x22, 0x33, 0x44]
(无 CAN ID、无帧类型,这些由 CANIF 配置决定)
步骤2:CANIF 校验 + 路由映射
CANIF 做:
- 校验 TxPduId 合法性
- 查表:
TxPduId=0x05→ 对应CanCtrl=0、Hth=1、CAN ID=0x123、STD 帧 - 把 I-PDU 封装为 CAN L-PDU(补全 ID、帧类型、DLC)
步骤3:CANIF 调用 CAN Driver 底层发送 Can_Write
CANIF 向下调用驱动接口,传入 TxHOH + 完整 CAN 报文
c
// CANIF 调用 Can_Write(伪代码)
Can_MsgType CanMsg;
CanMsg.CanId = 0x123; // 配置好的ID
CanMsg.CanIdType = CAN_ID_STD; // 标准帧
CanMsg.CanDlc = 4; // 长度
CanMsg.CanSduPtr = [0x11,0x22,0x33,0x44];
Std_ReturnType ret = Can_Write( Hth=1, &CanMsg );
✅ CANIF → CAN Driver 发包格式(CAN L-PDU):
- Hth: 1
- CanId: 0x123
- Type: STD
- DLC: 4
- Data: [0x11,0x22,0x33,0x44]
步骤4:CAN Driver 配置控制器硬件发送
驱动将报文写入 TxHOH=1 对应硬件缓冲区,启动发送。
步骤5:CAN 控制器把报文发到总线上
总线上真实波形/报文(CANoe 可抓到):
ID: 0x123 | DLC:4 | Data: 11 22 33 44 | 标准帧
步骤6:发送完成 → CAN Driver 回调 Can_TxConfirmation
控制器发送成功后,驱动向上回调,告知 哪个 TxHOH 发完
c
// CAN Driver 回调 CANIF
void Can_TxConfirmation( Can_HwHandleType Hth=1, Std_ReturnType Result=E_OK );
步骤7:CANIF 转发确认 → 上层 PduR_TxConfirmation
CANIF 把 Hth=1 反向映射回 TxPduId=0x05,回调上层:
c
// CANIF 回调 PDUR
void PduR_TxConfirmation( PduIdType TxPduId=0x05, Std_ReturnType Result );
至此 发送全流程结束。
三、CANIF 接收(Rx)完整流程 + 逐步骤举例
1. 接收场景举例(固定参数,全程用)
总线上发来报文:
- CAN ID(标准 11bit):
0x456 - DLC:
3 - 数据:
[0xAA, 0xBB, 0xCC] - 帧类型:标准帧
- 接收控制器:
CanCtrl=0 - 匹配 RxHOH(接收硬件句柄):
Hrh=2 - 上层 Rx I-PDU ID:
RxPduId=0x0A
2. 接收前关键配置
- 配置 Rx 滤波:精确匹配
ID=0x456 - 滤波通过 → 路由到
RxPduId=0x0A - RxHOH=2 绑定控制器0、ID=0x456
3. 完整接收流程(6 步,每步带实例)
步骤1:CAN 控制器收到总线报文 → 硬件滤波匹配
总线报文:
ID:0x456 | DLC:3 | Data:AA BB CC | STD
控制器滤波命中 → 存入 RxHOH=2。
步骤2:CAN Driver 读取报文 → 回调 Can_RxIndication
驱动从硬件读出报文,上传给 CANIF:
c
// CAN Driver 回调 CANIF
void Can_RxIndication(
Can_HwHandleType Hrh=2, // 接收HOH
const Can_MsgType* CanMsgPtr // 完整CAN报文
);
// CanMsg 内容:ID=0x456, STD, DLC=3, Data=[0xAA,0xBB,0xCC]
✅ 底层上传包格式(CAN L-PDU):
- Hrh:2
- CanId:0x456
- Type:STD
- DLC:3
- Data:[0xAA,0xBB,0xCC]
步骤3:CANIF 校验、ID 路由、映射为 Rx I-PDU
CANIF 做:
- 校验 DLC、控制器
- 查表:
ID=0x456 + Ctrl=0→RxPduId=0x0A - 剥离底层硬件信息,只保留 数据+长度 形成 I-PDU
步骤4:CANIF 调用 PduR_RxIndication 上传上层
c
// CANIF 回调 PDUR/COM
void PduR_RxIndication(
PduIdType RxPduId=0x0A,
const PduInfoType* PduInfoPtr
);
// PduInfo:Length=3, Data=[0xAA,0xBB,0xCC]
✅ 上层收到的包格式(I-PDU):
- RxPduId:0x0A
- Length:3
- Data:[0xAA,0xBB,0xCC]
(上层看不到 CAN ID、HOH、控制器,只关心业务数据)
四、收发报文格式对比(最直观总结)
| 方向 | 交互层级 | 报文类型 | 包含内容 | 实例值(发送) | 实例值(接收) |
|---|---|---|---|---|---|
| 发送(上→下) | COM/PDUR ↔ CANIF | I-PDU | PduId + SduLength + SduData | TxPduId=0x05, Len=4, [11,22,33,44] | - |
| 发送(下→底) | CANIF ↔ CAN Driver | CAN L-PDU | Hth + CanId + Type + DLC + Data | Hth=1, ID=0x123, DLC=4, 同上数据 | - |
| 接收(底→上) | CAN Driver ↔ CANIF | CAN L-PDU | Hrh + CanId + Type + DLC + Data | - | Hrh=2, ID=0x456, DLC=3, [AA,BB,CC] |
| 接收(上→应用) | CANIF ↔ COM/PDUR | I-PDU | PduId + SduLength + SduData | - | RxPduId=0x0A, Len=3, 同上数据 |
| 总线实际报文 | ECU ↔ 总线 | CAN 帧 | ID + IDE(标准/扩展) + DLC + Data + CRC | ID=0x123, DLC=4, [11,22,33,44] | ID=0x456, DLC=3, [AA,BB,CC] |
五、核心关键点(开发必注意)
- 上层看不到 CAN ID:ID、HOH、控制器全由 CANIF 配置屏蔽,上层只认 PduId。
- DLC 必须匹配配置:发送时上层长度 ≠ 配置 DLC 会报错;接收时 DLC 不匹配会丢弃。
- 发送确认必须处理 :
TxConfirmation是总线真正发成功的标志,不是CanIf_Transmit返回成功就代表发完。 - 接收靠滤波:Rx 流程第一步是硬件/软件滤波,不匹配的 ID 直接丢弃,不上传。
- 标准帧 vs 扩展帧 :CANIF 会区分
CAN_ID_STD/CAN_ID_EXT,配置和路由必须一一对应。
六、极简一句话总结
- 发送:上层给 CANIF 「PduId+数据」→ CANIF 查表补全「CAN ID+HOH」→ 驱动发总线 → 底层确认回调上层。
- 接收:总线报文 → 控制器滤波 → 驱动上传「CAN ID+数据」→ CANIF 映射为「PduId+数据」→ 上传应用。