3. CAN驱动与CanIf配置实战

在MICROSAR通信栈中,CAN驱动(Can Driver)与CAN接口层(CanIf)是报文进出ECU的第一道关口。CAN驱动直接操作CAN控制器寄存器与收发器引脚,负责位定时、邮箱管理、中断与唤醒;CanIf则位于驱动之上,向上为PduR、Com、CanTp等模块提供统一的报文收发服务,向下屏蔽不同CAN控制器与收发器的差异。本节围绕“硬件抽象—句柄配置—ID过滤映射—回环验证”这条主线,把配置参数与真实报文路径对应起来。

一、CAN控制器与收发器的硬件抽象

CAN驱动对硬件的抽象分为两层:控制器抽象与收发器抽象。控制器抽象由Can模块完成,它把CAN控制器的邮箱(Mailbox/Message Object)抽象为硬件对象(Hardware Object,HO),每个HO对应一个发送或接收邮箱,并带有唯一的Handle。收发器抽象由CanTrcv模块完成,它把收发器的模式引脚(STB、EN、NSTB等)抽象为CanTrcv_SetOpMode接口,支持NORMAL、STANDBY、SLEEP等模式切换。

以常见的CAN控制器为例,其位定时参数由CanControllerBaudRateConfig给出。假设CAN时钟为40 MHz,目标波特率500 kbit/s,采样点取80%,则位时间TQ总数为:40 MHz / 500 kbit/s = 80 TQ。按采样点80%划分,SYNC_SEG=1 TQ,PROP_SEG+PHASE_SEG1=63 TQ,PHASE_SEG2=16 TQ。若BRP=5,则每TQ为5个时钟周期,TSEG1=63、TSEG2=16,采样点=(1+63)/(1+63+16)=80%。这些参数在CanControllerBaudRateConfig中体现为CanControllerBaudRate、CanControllerPropSeg、CanControllerSeg1、CanControllerSeg2、CanControllerSyncJumpWidth。

收发器抽象的关键是模式与唤醒。CanTrcv模块通过CanTrcvChannelId区分通道,通过CanTrcvHwPnPort、CanTrcvHwPnPolarity描述引脚极性。当ECU进入SLEEP时,CanTrcv_SetOpMode(TRCV_MODE_STANDBY)拉低STB引脚;当总线出现显性位唤醒时,收发器通过RXD引脚产生唤醒事件,CanIf再调用CanIf_CheckWakeup通知EcuM。硬件抽象的价值在于:上层Com、CanTp只关心PduId,不关心是哪个控制器、哪个收发器、哪个邮箱。

二、CanIf的HOH、HRH、HTH配置

CanIf用三类句柄描述报文路径:HOH(Hardware Object Handle)是驱动层邮箱句柄,HRH(Receive Handle)是接收句柄,HTH(Transmit Handle)是发送句柄。三者关系是:一个HRH对应一个或多个HOH,一个HTH对应一个HOH。配置时先定义CanIfRxPduCfg与CanIfTxPduCfg,再通过CanIfRxPduHrhIdRef、CanIfTxPduHthIdRef绑定到HRH/HTH,最后通过CanIfHrhCanIdRef、CanIfHthCanIdRef关联到具体CAN ID。

典型配置片段如下(示例参数,非实测):

CanIfRxPduCfg:
  CanIfRxPduId        = 0x10
  CanIfRxPduCanId     = 0x123
  CanIfRxPduCanIdMask = 0x7FF
  CanIfRxPduHrhIdRef  = HRH_0
  CanIfRxPduDlc        = 8

CanIfTxPduCfg:
  CanIfTxPduId        = 0x20
  CanIfTxPduCanId     = 0x456
  CanIfTxPduHthIdRef  = HTH_0
  CanIfTxPduDlc        = 8

CanIfHrhCfg:
  CanIfHrhId          = HRH_0
  CanIfHrhCanIdRef    = HOH_0
  CanIfHrhSoftwareFilter = TRUE

CanIfHthCfg:
  CanIfHthId          = HTH_0
  CanIfHthCanIdRef    = HOH_1

这里HRH_0绑定HOH_0(接收邮箱),HTH_0绑定HOH_1(发送邮箱)。若一个HRH绑定多个HOH,则这些邮箱共享同一接收句柄,CanIf在CanIf_RxIndication中按CanId分发给不同上层PduId。HTH则通常一对一,因为发送邮箱需要独立的状态机管理发送确认。

三、CAN ID过滤与映射

CAN ID过滤分两级:硬件过滤与软件过滤。硬件过滤由CAN控制器邮箱的验收滤波器完成,配置CanIfHrhRangeCfg中的CanIfHrhRangeRxPduLowerCanId与UpperCanId,只有落在范围内的报文才会被邮箱接收。软件过滤由CanIf在CanIf_RxIndication中执行,通过CanIfRxPduCanId与CanIfRxPduCanIdMask做掩码比较,例如Mask=0x7FF表示精确匹配,Mask=0x7F0表示忽略低4位。

映射关系是:CAN ID → HRH → CanIfRxPduId → 上层PduId。例如0x123映射到HRH_0,HRH_0再映射到CanIfRxPduId=0x10,PduR根据0x10路由到Com的RxPdu。发送方向则是:上层PduId → CanIfTxPduId → HTH → HOH → 邮箱。若映射错误,典型现象是CanIf_RxIndication不触发,或Com收不到信号,而总线示波器上报文正常。

四、基于真实ECU的CAN通信回环测试

回环测试用于验证驱动、CanIf、ID过滤与映射是否贯通。测试拓扑有两种:内部回环(Controller Loopback)和外部回环(External Loopback)。内部回环由CAN控制器自身把发送邮箱的报文回送到接收邮箱,不依赖收发器和总线;外部回环需要收发器与总线,通常用CANoe或CANalyzer模拟对端节点。

以内部回环为例,操作步骤如下:将CanControllerLoopbackMode设为CAN_LOOPBACK_INTERNAL;配置HTH_0发送0x456,HRH_0接收0x456;调用CanIf_Transmit(0x20, &PduInfo)触发发送;在CanIf_RxIndication中打断点,观察是否收到CanIfRxPduId=0x10、CanId=0x456、Dlc=8。若收到,说明HOH、HRH、HTH、ID过滤与映射全部正确;若未收到,先检查CanIfRxPduCanIdMask是否把0x456过滤掉,再检查HRH是否绑定了正确的HOH。

外部回环则需把收发器切到NORMAL模式,用CANoe发送0x123,观察ECU是否回发0x456。此时可用CANoe的Trace窗口查看报文周期、DLC与数据场,用Bus Statistics查看错误帧计数。若出现Error Frame,优先检查波特率与采样点是否与总线一致;若出现Form Error,检查DLC与数据长度是否匹配。

CAN驱动与CanIf报文路径及回环测试 Com / CanTp 上层PduId PduR 路由与网关 CanIf HRH_0 接收句柄 HTH_0 发送句柄 ID过滤 Mask CanIf_RxIndication / CanIf_Transmit CanIfRxPduId=0x10 CanIfTxPduId=0x20 Can Driver HOH_0 接收邮箱 HOH_1 发送邮箱 位定时 500k/80% CanTrcv 收发器抽象 STB / EN 引脚 · NORMAL / STANDBY / SLEEP CAN Bus CAN_H / CAN_L 内部回环 PduId 0x10 / 0x20 外部回环:CANoe 模拟对端 上层 CanIf Can Driver CanTrcv 总线 回环路径

回环测试的判据可以归纳为三点:第一,发送调用返回E_OK,说明HTH与HOH绑定正确;第二,CanIf_RxIndication被调用且CanId、Dlc与预期一致,说明HRH、ID过滤与映射正确;第三,若使用外部回环,CANoe Trace中无Error Frame且周期稳定,说明位定时与收发器模式正确。若第一点失败,检查CanIfTxPduHthIdRef是否指向有效HTH;若第二点失败,检查CanIfRxPduCanIdMask与CanIfHrhRangeCfg是否把目标ID排除;若第三点失败,检查CanControllerBaudRate与采样点是否与总线一致。

配置CanIf时,建议先画一张“CAN ID → HRH/HTH → HOH → 邮箱”的映射表,再逐项填写CanIfRxPduCfg与CanIfTxPduCfg。映射表能提前暴露ID冲突、掩码过宽、HRH重复绑定等问题,比在回环测试中逐个排查效率更高。
内部回环模式下,收发器通常不参与,因此不能验证收发器引脚极性与总线电平。若ECU在整车上无法通信但内部回环通过,应优先检查CanTrcvHwPnPolarity、STB引脚电平以及终端电阻,而不是继续修改CanIf映射。

把上述配置与测试串起来看,CAN驱动与CanIf的配置本质是“硬件资源—句柄—ID—上层Pdu”的四层映射。硬件抽象保证可移植性,HOH/HRH/HTH保证路径可追踪,ID过滤与映射保证报文只进入正确的上层,回环测试则用最小闭环验证这四层是否一致。掌握这条链路后,后续CanTp分段传输、Com信号打包与E2E保护才有可靠的底层基础。