AUTOSAR CAN模块详解
基于AUTOSAR R4.4.0规范的CAN模块架构与实现
目录
1. 概述
AUTOSAR (AUTomotive Open System ARchitecture) 是汽车电子软件的标准化开放式架构,它定义了一系列用于汽车电子控制单元(ECU)的软件组件和接口。CAN (Controller Area Network) 是汽车行业中使用最广泛的通信总线之一,AUTOSAR规范对CAN相关功能模块进行了详细定义。
本文详细介绍AUTOSAR标准中CAN相关模块的架构、配置、状态机、通信序列及传输层协议,基于AUTOSAR R4.4.0规范。主要包括以下CAN相关基础软件模块:
- CAN驱动(Can): 直接操作CAN控制器硬件
- CAN接口(CanIf): 提供标准化的上层接口,路由CAN PDU
- CAN状态管理器(CanSM): 管理CAN网络状态
- CAN传输层(CanTp): 支持大数据块的分段传输
- CAN总线收发器驱动(CanTrcv): 管理CAN收发器硬件
2. AUTOSAR CAN模块架构
AUTOSAR CAN模块采用分层架构设计,每层具有明确定义的职责和接口。

2.1 架构层次解析
AUTOSAR CAN模块架构分为以下几个层次:
-
应用层:
- COM:通信服务模块,负责应用层数据的打包和解包
- CAN NM:CAN网络管理模块,负责管理网络唤醒和睡眠
- PDU Router:PDU路由器,负责将PDU路由到正确的目标模块
-
通信服务层:
- CAN Transport Layer (CanTp):实现ISO 15765-2协议,支持大数据块的分段传输
-
ECU抽象层:
- CAN Interface (CanIf):提供标准化的上层接口,负责路由CAN PDU到不同模块
- CAN State Manager (CanSM):管理CAN网络状态,协调网络唤醒和睡眠
-
微控制器抽象层:
- CAN Driver (Can):直接操作CAN控制器硬件,管理发送和接收缓冲区
- CAN Transceiver Driver (CanTrcv):管理CAN收发器,支持总线唤醒检测
-
硬件层:
- CAN控制器:CAN通信的核心硬件组件
- CAN收发器:连接CAN控制器与物理CAN总线
2.2 模块间关系
-
上下层交互:
- 上层模块通过标准化的API调用下层模块服务
- 下层模块通过回调函数向上层模块通知事件
-
水平交互:
- CanSM调用CanIf和CanTrcv的API协调网络状态管理
- PDU Router根据配置将消息路由到CanIf或CanTp
-
硬件抽象:
- Can模块屏蔽了不同CAN控制器硬件的差异
- CanTrcv模块屏蔽了不同CAN收发器硬件的差异
2.3 关键接口说明
- CAN Interface API:提供CAN帧传输服务,包括发送请求、接收指示和控制功能
- CAN Driver API:提供CAN控制器操作服务,包括初始化、控制器模式设置和硬件对象访问
- CAN Transport API:提供基于ISO 15765-2协议的分段传输服务
- CAN State Manager API:提供网络状态管理服务
- CAN Transceiver API:提供收发器操作服务,包括操作模式设置和唤醒处理
3. CAN驱动配置模型
CAN驱动配置是实现CAN通信的基础,AUTOSAR定义了详细的配置类和数据结构。

3.1 配置类结构解析
-
Can_ConfigType:
- CAN驱动的全局配置结构,包含所有控制器和硬件对象配置
- 初始化时传递给
Can_Init()
函数 - 包含指向各类配置的指针,实现模块化配置
-
Can_ControllerConfigType:
- 定义单个CAN控制器的配置参数
- 包含控制器ID、基地址、波特率等基本参数
- 定义控制器的工作模式和处理方式(中断/轮询)
-
Can_HardwareObjectConfigType:
- 定义CAN控制器中的消息缓冲区配置
- 可配置为发送或接收对象(CanObjectType)
- 支持标准ID和扩展ID过滤(CanIdType)
-
Can_GeneralConfigType:
- 定义CAN驱动的全局参数
- 包含开发错误检测、版本信息API支持等功能开关
- 定义总线关闭恢复时间和唤醒处理周期
-
Can_CallbackType:
- 定义上层回调函数指针
- 包括总线关闭通知、唤醒通知、错误通知等
- 实现事件驱动的通信模型
3.2 运行时数据结构
-
Can_PduType:
- 用于发送和接收CAN消息的数据结构
- 包含CAN ID、数据长度、数据指针和句柄
- 在
Can_Write()
函数中使用
-
Can_StateType:
- 存储CAN控制器的运行时状态
- 包含控制器模式和错误状态
- 通过
Can_GetControllerMode()
和Can_GetControllerErrorState()
函数访问
3.3 枚举类型说明
-
Can_ControllerModeType:
- 定义控制器可能的模式状态
- 包括UNINIT(未初始化)、STARTED(已启动)、STOPPED(已停止)和SLEEP(睡眠)
-
Can_ErrorStateType:
- 定义CAN控制器的错误状态
- 包括ACTIVE(活动)、PASSIVE(被动)和BUSOFF(总线关闭)
-
Can_ProcessType:
- 定义处理方式:中断或轮询
- 分别用于接收和发送处理
-
Can_IdTypeType:
- 定义支持的ID类型
- 包括标准ID(11位)、扩展ID(29位)和混合模式
3.4 配置示例
c
/* CAN驱动配置示例 */
const Can_ControllerConfigType CanControllerConfig = {
.CanControllerId = 0,
.CanControllerBaseAddress = CAN0_BASE_ADDRESS,
.CanControllerDefaultBaudrate = 0, /* 索引到波特率配置 */
.CanCpuClockRef = 80000000UL, /* 80MHz时钟 */
.CanControllerActivation = TRUE,
.CanRxProcessing = CAN_PROCESS_TYPE_INTERRUPT,
.CanTxProcessing = CAN_PROCESS_TYPE_INTERRUPT,
.CanBusoffProcessing = 0,
.CanWakeupProcessing = 0,
.CanWakeupFunctionalityAPI = 0,
.CanControllerMode = 0
};
const Can_HardwareObjectConfigType CanHardwareObjectConfig[] = {
{ /* 接收硬件对象 */
.CanHardwareObjectCount = 0,
.CanObjectType = CAN_OBJECT_TYPE_RECEIVE,
.CanIdType = CAN_ID_TYPE_STANDARD,
.CanHwFilterCode = 0x100, /* 接收ID过滤码 */
.CanHwFilterMask = 0x7FF, /* 标准ID掩码 */
.CanControllerRef = 0, /* 控制器索引 */
.CanHardwareObjectRef = 0 /* 硬件对象索引 */
},
{ /* 发送硬件对象 */
.CanHardwareObjectCount = 1,
.CanObjectType = CAN_OBJECT_TYPE_TRANSMIT,
.CanIdType = CAN_ID_TYPE_STANDARD,
.CanHwFilterCode = 0x200, /* 发送ID */
.CanHwFilterMask = 0x000, /* 不适用于发送对象 */
.CanControllerRef = 0, /* 控制器索引 */
.CanHardwareObjectRef = 1 /* 硬件对象索引 */
}
};
const Can_ConfigType CanConfig = {
.ControllerConfigPtr = &CanControllerConfig,
.HardwareObjectConfigPtr = CanHardwareObjectConfig,
.CallbackFunctions = &CanCallbacks,
.GeneralConfig = &CanGeneralConfig,
.InitConfig = &CanInitConfig
};
4. CAN驱动状态机
CAN驱动模块通过状态机管理CAN控制器的不同工作状态,实现CAN通信功能和错误处理。

4.1 控制器主状态
-
UNINIT(未初始化):
- 上电后的默认状态
- CAN控制器未配置,不可通信
- 通过
Can_Init()
函数转换到STOPPED状态
-
STOPPED(已停止):
- CAN控制器已初始化但总线已禁用
- 不参与总线通信,不发送或接收数据
- 可通过
Can_SetControllerMode(CAN_T_START)
转换到STARTED状态 - 可通过
Can_SetControllerMode(CAN_T_SLEEP)
转换到SLEEP状态
-
STARTED(已启动):
- CAN控制器完全激活,参与总线通信
- 可发送和接收数据,执行正常通信功能
- 内部包含三个子状态:ERROR_ACTIVE、ERROR_PASSIVE和BUS_OFF
- 可通过
Can_SetControllerMode(CAN_T_STOP)
转换到STOPPED状态
-
SLEEP(睡眠):
- CAN控制器处于低功耗模式
- 可通过总线唤醒事件唤醒
- 可通过
Can_SetControllerMode(CAN_T_WAKEUP)
转换到STOPPED状态 - 在总线唤醒后,还需调用
Can_SetControllerMode(CAN_T_START)
才能恢复通信
4.2 错误状态子状态机
在STARTED主状态内,根据CAN协议,控制器可能处于以下三种错误状态之一:
-
ERROR_ACTIVE(错误活动):
- 正常通信状态
- 发送和接收错误计数器均低于128
- 可正常发送和接收消息,包括错误帧
-
ERROR_PASSIVE(错误被动):
- 发送或接收错误计数器超过127
- 仍可发送和接收消息,但发送带有被动错误标志
- 发送后需等待额外的8个位时间
- 当错误计数器回落到128以下时,可恢复到ERROR_ACTIVE状态
-
BUS_OFF(总线关闭):
- 发送错误计数器超过255
- 停止所有通信活动,不再发送或接收数据
- 需要经过恢复过程才能重新参与通信
- 恢复过程包括调用
Can_SetControllerMode(CAN_T_STOP)
和Can_SetControllerMode(CAN_T_START)
4.3 状态转换触发机制
-
初始化触发:
- 调用
Can_Init()
函数触发从UNINIT到STOPPED的转换 - 初始化控制器寄存器和硬件对象
- 调用
-
模式切换API触发:
- 调用
Can_SetControllerMode()
函数指定目标模式 - 转换参数包括CAN_T_START、CAN_T_STOP、CAN_T_SLEEP和CAN_T_WAKEUP
- 调用
-
错误事件触发:
- CAN协议错误机制自动管理ERROR_ACTIVE、ERROR_PASSIVE和BUS_OFF之间的转换
- 根据错误计数器的值确定当前错误状态
-
总线唤醒触发:
- 在SLEEP状态下,总线上的唤醒事件(特定电平变化)可触发唤醒处理
- 触发回调函数通知上层
4.4 错误恢复机制
对于BUS_OFF状态的恢复,AUTOSAR规范定义了自动恢复机制:
c
/* 总线关闭恢复处理示例 */
void Can_BusoffRecovery(uint8 Controller) {
/* 1. 设置控制器为STOP模式 */
Can_SetControllerMode(Controller, CAN_T_STOP);
/* 2. 等待恢复时间(取决于配置) */
Delay(CanConfig.GeneralConfig->CanBusoffRecoveryTime);
/* 3. 重新启动控制器 */
Can_SetControllerMode(Controller, CAN_T_START);
/* 4. 通知上层总线恢复 */
CanIf_ControllerModeIndication(Controller, CANIF_CS_STARTED);
}
5. CAN收发器驱动状态图
CAN收发器驱动管理CAN收发器硬件,控制其工作模式并处理唤醒事件。

5.1 收发器主状态
-
UNINIT(未初始化):
- 上电后的默认状态
- 收发器未配置,无法收发数据
- 通过
CanTrcv_Init()
函数转换到NORMAL状态
-
NORMAL(正常工作):
- 收发器完全激活,可正常收发数据
- 功耗较高,用于正常通信阶段
- 通过
CanTrcv_SetOpMode(CANTRCV_TRCVMODE_STANDBY)
转换到STANDBY状态
-
STANDBY(待机):
- 收发器部分激活,可接收但不发送
- 可检测唤醒事件,中等功耗
- 通过
CanTrcv_SetOpMode(CANTRCV_TRCVMODE_NORMAL)
转换到NORMAL状态 - 通过
CanTrcv_SetOpMode(CANTRCV_TRCVMODE_SLEEP)
转换到SLEEP状态
-
SLEEP(睡眠):
- 收发器最低功耗模式,只能检测唤醒事件
- 无法收发数据,最低功耗
- 通过
CanTrcv_SetOpMode(CANTRCV_TRCVMODE_STANDBY)
转换到STANDBY状态 - 在总线唤醒后,可直接通过
CanTrcv_SetOpMode(CANTRCV_TRCVMODE_NORMAL)
转换到NORMAL状态
5.2 唤醒原因状态
当收发器检测到唤醒事件时,会记录唤醒原因,主要包括:
-
INTERNALLY(内部唤醒):
- 由ECU内部触发的唤醒
- 通常是软件请求唤醒
-
BY_BUS(总线唤醒):
- 检测到总线上的唤醒模式
- 由外部设备请求唤醒
-
其他唤醒原因:
- NOT_SUPPORTED:不支持的唤醒原因
- POWER_ON:上电唤醒
- RESET:复位唤醒
- SLEEP:唤醒前处于睡眠状态
5.3 总线唤醒处理流程
当收发器在SLEEP状态下检测到总线唤醒事件时,处理流程如下:
- 收发器硬件检测到唤醒模式(特定电平变化)
- 触发中断或在轮询模式下被检测到
- 调用
CanTrcv_CheckWakeup()
函数确认唤醒 - 调用
CanIf_TrcvWakeupNotification()
通知CAN接口层 - 设置唤醒标志并记录唤醒原因为BY_BUS
- 上层模块根据需要调用
CanTrcv_SetOpMode()
改变收发器模式
5.4 状态转换API
AUTOSAR定义了以下API用于控制收发器状态:
c
/* 收发器初始化 */
void CanTrcv_Init(const CanTrcv_ConfigType* ConfigPtr);
/* 设置收发器操作模式 */
Std_ReturnType CanTrcv_SetOpMode(
uint8 Transceiver,
CanTrcv_TrcvModeType OpMode
);
/* 获取收发器当前模式 */
Std_ReturnType CanTrcv_GetOpMode(
uint8 Transceiver,
CanTrcv_TrcvModeType* OpMode
);
/* 检查是否发生唤醒 */
Std_ReturnType CanTrcv_CheckWakeup(uint8 Transceiver);
/* 获取唤醒原因 */
Std_ReturnType CanTrcv_GetTrcvWakeupReason(
uint8 Transceiver,
CanTrcv_TrcvWakeupReasonType* TrcvWakeupReason
);
6. CAN通信序列
CAN通信涉及多个层之间的协作,下图展示了CAN消息发送和接收的完整序列。

6.1 发送CAN消息流程
-
应用层发起发送请求:
- 应用层调用
CanIf_Transmit(PduId, PduInfoPtr)
- 传递PDU ID和PDU信息(数据指针和长度)
- 应用层调用
-
CAN接口层处理:
- 查找L-PDU映射配置,确定硬件对象句柄(Hth)
- 准备Can_PduType结构,包含CAN ID、数据等
- 调用
Can_Write(Hth, PduInfoPtr)
请求发送
-
CAN驱动层处理:
- 查找硬件对象,填充CAN控制器发送缓冲区
- 如果缓冲区可用,触发消息发送并返回E_OK
- 如果缓冲区不可用,返回E_NOT_OK
-
发送完成处理:
- CAN控制器发送完成后产生中断
- CAN驱动处理中断,调用
CanIf_TxConfirmation(CanTxPduId)
- CAN接口层通知应用层发送完成
6.2 接收CAN消息流程
-
硬件接收消息:
- CAN控制器接收到匹配的CAN消息并产生中断
- CAN驱动处理中断,读取硬件接收缓冲区
-
CAN驱动层处理:
- 调用
CanIf_RxIndication(Hrh, CanId, CanDlc, CanSduPtr)
- 传递硬件对象句柄、CAN ID、数据长度和数据指针
- 调用
-
CAN接口层处理:
- 查找L-PDU映射配置,根据硬件对象句柄和CAN ID查找PDU ID
- 执行CAN ID过滤,验证DLC
- 如果匹配,调用上层回调函数通知接收数据
- 如果不匹配或DLC无效,丢弃消息
6.3 总线关闭恢复流程
-
检测总线关闭:
- CAN驱动检测到控制器进入总线关闭状态
- 调用
CanIf_ControllerBusOff(ControllerId)
通知接口层
-
停止控制器:
- 接口层通知应用层总线关闭
- 调用
Can_SetControllerMode(Controller, CAN_T_STOP)
停止控制器
-
等待恢复时间:
- 根据配置等待一段恢复时间
- 恢复时间取决于ECU策略和应用需求
-
重启控制器:
- 调用
Can_SetControllerMode(Controller, CAN_T_START)
重新启动控制器 - CAN驱动重新初始化控制器
- 通知应用层控制器模式变更
- 调用
6.4 关键API解析
-
CanIf_Transmit:
- 功能:请求发送CAN消息
- 参数:PDU ID和PDU信息
- 返回:E_OK(接受请求)或E_NOT_OK(拒绝请求)
-
Can_Write:
- 功能:向CAN控制器发送消息
- 参数:硬件对象句柄和PDU信息
- 返回:E_OK(消息已放入发送缓冲区)或E_NOT_OK(发送缓冲区已满)
-
CanIf_TxConfirmation:
- 功能:通知消息发送完成
- 参数:PDU ID
- 调用:CAN驱动在发送完成后调用
-
CanIf_RxIndication:
- 功能:通知接收到CAN消息
- 参数:硬件对象句柄、CAN ID、数据长度和数据指针
- 调用:CAN驱动在接收消息后调用
7. CAN传输层协议
CAN传输层协议(CanTp)实现了ISO 15765-2标准,支持大数据块的分段传输。

7.1 传输层帧类型
ISO 15765-2协议定义了四种帧类型,由PCI(Protocol Control Information)字段的前4位标识:
-
单帧(SF - Single Frame):
- PCI=0x0,用于小于8字节的消息
- 格式:[0x0|SF_DL|Data...]
- SF_DL表示数据长度(最大7字节)
-
首帧(FF - First Frame):
- PCI=0x1,多帧传输的第一帧
- 格式:[0x1|FF_DL_HI|FF_DL_LO|Data...]
- FF_DL表示总数据长度(两字节)
-
连续帧(CF - Consecutive Frame):
- PCI=0x2,多帧传输的后续帧
- 格式:[0x2|SN|Data...]
- SN表示序列号(0-15),循环使用
-
流控帧(FC - Flow Control):
- PCI=0x3,控制数据流
- 格式:[0x3|FS|BS|STmin]
- FS表示流状态(0=CTS, 1=WAIT, 2=OVFLW)
- BS表示块大小(在需要下一个FC前可发送的CF数量)
- STmin表示连续帧之间的最小时间间隔
7.2 单帧传输流程
用于传输小于8字节的数据:
- 上层应用调用
CanTp_Transmit(TxSduId, PduInfoPtr)
- CanTp准备单帧格式,设置PCI=0x0,SF_DL=数据长度
- 调用
CanIf_Transmit()
发送单帧 - 接收方的CanIf接收到消息后调用
CanTp_RxIndication()
- 接收方CanTp解析单帧,提取数据并通知上层应用
- 发送方收到确认后通知上层应用传输完成
7.3 多帧传输流程
用于传输大于7字节的数据:
-
首帧(FF)发送:
- 上层应用调用
CanTp_Transmit()
- CanTp准备首帧,设置PCI=0x1,FF_DL=总数据长度
- 首帧包含前5-6字节数据
- 调用
CanIf_Transmit()
发送首帧
- 上层应用调用
-
流控帧(FC)处理:
- 接收方收到首帧后分配接收缓冲区
- 发送流控帧(FC),设置FS=0(CTS),BS=块大小,STmin=帧间隔
- 发送方解析流控帧,设置传输参数
-
连续帧(CF)传输:
- 发送方根据BS和STmin参数发送连续帧
- 连续帧包含PCI=0x2,SN=序列号(0-15)
- 接收方校验序列号,拼接数据
- 当块大小达到或传输完成时,接收方可能发送新的流控帧
7.4 超时参数与错误处理
ISO 15765-2定义了多个超时参数:
- N_As:发送方等待首帧传输确认的最大时间
- N_Bs:发送方等待流控帧的最大时间
- N_Cs:发送方等待连续帧发送确认的最大时间
- N_Ar:接收方等待首帧接收的最大时间
- N_Br:接收方等待连续帧的最大时间
- N_Cr:接收方发送流控帧后等待连续帧的最大时间
当超时发生时,传输中止并通知上层应用。例如:
c
/* 超时处理示例 */
void CanTp_MainFunction(void) {
/* 检查各种超时 */
if (CanTp_CheckN_CrTimeout()) {
/* N_Cr超时:未接收到预期的连续帧 */
CanTp_NotifyRxTimeout();
/* 通知上层应用接收失败 */
<接收错误回调函数>(RxPduId, NTFRSLT_E_NOT_OK);
/* 重置连接状态 */
CanTp_ResetConnection();
}
if (CanTp_CheckN_BsTimeout()) {
/* N_Bs超时:未接收到预期的流控帧 */
CanTp_NotifyTxTimeout();
/* 通知上层应用发送失败 */
CanTp_TxConfirmation(TxPduId, NTFRSLT_E_NOT_OK);
/* 重置连接状态 */
CanTp_ResetConnection();
}
/* 其他超时检查... */
}
8. 总结
AUTOSAR CAN模块提供了一套完整、标准化的CAN通信解决方案,具有以下特点:
-
分层架构:
- 清晰的层次结构,职责明确
- 标准化的接口,便于模块替换和升级
- 硬件抽象,屏蔽底层差异
-
灵活配置:
- 详细的配置类和数据结构
- 支持多种控制器模式和处理方式
- 可根据应用需求定制
-
完善的状态管理:
- 控制器和收发器状态机设计合理
- 支持低功耗模式和唤醒机制
- 错误处理和恢复机制健全
-
高效通信:
- 支持基本CAN帧通信
- 支持大数据块分段传输
- 流控制和错误检测机制
通过本文详细介绍的AUTOSAR CAN模块架构、配置、状态机、通信序列及传输层协议,读者可以全面了解AUTOSAR CAN相关模块的设计理念和实现方式,为基于AUTOSAR标准的汽车电子软件开发提供参考。