AUTOSAR进阶图解==>AUTOSAR_SRS_CAN

AUTOSAR CAN模块详解

基于AUTOSAR R4.4.0规范的CAN模块架构与实现

目录

  1. 概述
  2. [AUTOSAR CAN模块架构](#AUTOSAR CAN模块架构)
  3. CAN驱动配置模型
  4. CAN驱动状态机
  5. CAN收发器驱动状态图
  6. CAN通信序列
  7. CAN传输层协议
  8. 总结

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模块架构分为以下几个层次:

  1. 应用层

    • COM:通信服务模块,负责应用层数据的打包和解包
    • CAN NM:CAN网络管理模块,负责管理网络唤醒和睡眠
    • PDU Router:PDU路由器,负责将PDU路由到正确的目标模块
  2. 通信服务层

    • CAN Transport Layer (CanTp):实现ISO 15765-2协议,支持大数据块的分段传输
  3. ECU抽象层

    • CAN Interface (CanIf):提供标准化的上层接口,负责路由CAN PDU到不同模块
    • CAN State Manager (CanSM):管理CAN网络状态,协调网络唤醒和睡眠
  4. 微控制器抽象层

    • CAN Driver (Can):直接操作CAN控制器硬件,管理发送和接收缓冲区
    • CAN Transceiver Driver (CanTrcv):管理CAN收发器,支持总线唤醒检测
  5. 硬件层

    • CAN控制器:CAN通信的核心硬件组件
    • CAN收发器:连接CAN控制器与物理CAN总线

2.2 模块间关系

  1. 上下层交互

    • 上层模块通过标准化的API调用下层模块服务
    • 下层模块通过回调函数向上层模块通知事件
  2. 水平交互

    • CanSM调用CanIf和CanTrcv的API协调网络状态管理
    • PDU Router根据配置将消息路由到CanIf或CanTp
  3. 硬件抽象

    • 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 配置类结构解析

  1. Can_ConfigType

    • CAN驱动的全局配置结构,包含所有控制器和硬件对象配置
    • 初始化时传递给Can_Init()函数
    • 包含指向各类配置的指针,实现模块化配置
  2. Can_ControllerConfigType

    • 定义单个CAN控制器的配置参数
    • 包含控制器ID、基地址、波特率等基本参数
    • 定义控制器的工作模式和处理方式(中断/轮询)
  3. Can_HardwareObjectConfigType

    • 定义CAN控制器中的消息缓冲区配置
    • 可配置为发送或接收对象(CanObjectType)
    • 支持标准ID和扩展ID过滤(CanIdType)
  4. Can_GeneralConfigType

    • 定义CAN驱动的全局参数
    • 包含开发错误检测、版本信息API支持等功能开关
    • 定义总线关闭恢复时间和唤醒处理周期
  5. Can_CallbackType

    • 定义上层回调函数指针
    • 包括总线关闭通知、唤醒通知、错误通知等
    • 实现事件驱动的通信模型

3.2 运行时数据结构

  1. Can_PduType

    • 用于发送和接收CAN消息的数据结构
    • 包含CAN ID、数据长度、数据指针和句柄
    • Can_Write()函数中使用
  2. Can_StateType

    • 存储CAN控制器的运行时状态
    • 包含控制器模式和错误状态
    • 通过Can_GetControllerMode()Can_GetControllerErrorState()函数访问

3.3 枚举类型说明

  1. Can_ControllerModeType

    • 定义控制器可能的模式状态
    • 包括UNINIT(未初始化)、STARTED(已启动)、STOPPED(已停止)和SLEEP(睡眠)
  2. Can_ErrorStateType

    • 定义CAN控制器的错误状态
    • 包括ACTIVE(活动)、PASSIVE(被动)和BUSOFF(总线关闭)
  3. Can_ProcessType

    • 定义处理方式:中断或轮询
    • 分别用于接收和发送处理
  4. 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 控制器主状态

  1. UNINIT(未初始化)

    • 上电后的默认状态
    • CAN控制器未配置,不可通信
    • 通过Can_Init()函数转换到STOPPED状态
  2. STOPPED(已停止)

    • CAN控制器已初始化但总线已禁用
    • 不参与总线通信,不发送或接收数据
    • 可通过Can_SetControllerMode(CAN_T_START)转换到STARTED状态
    • 可通过Can_SetControllerMode(CAN_T_SLEEP)转换到SLEEP状态
  3. STARTED(已启动)

    • CAN控制器完全激活,参与总线通信
    • 可发送和接收数据,执行正常通信功能
    • 内部包含三个子状态:ERROR_ACTIVE、ERROR_PASSIVE和BUS_OFF
    • 可通过Can_SetControllerMode(CAN_T_STOP)转换到STOPPED状态
  4. SLEEP(睡眠)

    • CAN控制器处于低功耗模式
    • 可通过总线唤醒事件唤醒
    • 可通过Can_SetControllerMode(CAN_T_WAKEUP)转换到STOPPED状态
    • 在总线唤醒后,还需调用Can_SetControllerMode(CAN_T_START)才能恢复通信

4.2 错误状态子状态机

在STARTED主状态内,根据CAN协议,控制器可能处于以下三种错误状态之一:

  1. ERROR_ACTIVE(错误活动)

    • 正常通信状态
    • 发送和接收错误计数器均低于128
    • 可正常发送和接收消息,包括错误帧
  2. ERROR_PASSIVE(错误被动)

    • 发送或接收错误计数器超过127
    • 仍可发送和接收消息,但发送带有被动错误标志
    • 发送后需等待额外的8个位时间
    • 当错误计数器回落到128以下时,可恢复到ERROR_ACTIVE状态
  3. BUS_OFF(总线关闭)

    • 发送错误计数器超过255
    • 停止所有通信活动,不再发送或接收数据
    • 需要经过恢复过程才能重新参与通信
    • 恢复过程包括调用Can_SetControllerMode(CAN_T_STOP)Can_SetControllerMode(CAN_T_START)

4.3 状态转换触发机制

  1. 初始化触发

    • 调用Can_Init()函数触发从UNINIT到STOPPED的转换
    • 初始化控制器寄存器和硬件对象
  2. 模式切换API触发

    • 调用Can_SetControllerMode()函数指定目标模式
    • 转换参数包括CAN_T_START、CAN_T_STOP、CAN_T_SLEEP和CAN_T_WAKEUP
  3. 错误事件触发

    • CAN协议错误机制自动管理ERROR_ACTIVE、ERROR_PASSIVE和BUS_OFF之间的转换
    • 根据错误计数器的值确定当前错误状态
  4. 总线唤醒触发

    • 在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 收发器主状态

  1. UNINIT(未初始化)

    • 上电后的默认状态
    • 收发器未配置,无法收发数据
    • 通过CanTrcv_Init()函数转换到NORMAL状态
  2. NORMAL(正常工作)

    • 收发器完全激活,可正常收发数据
    • 功耗较高,用于正常通信阶段
    • 通过CanTrcv_SetOpMode(CANTRCV_TRCVMODE_STANDBY)转换到STANDBY状态
  3. STANDBY(待机)

    • 收发器部分激活,可接收但不发送
    • 可检测唤醒事件,中等功耗
    • 通过CanTrcv_SetOpMode(CANTRCV_TRCVMODE_NORMAL)转换到NORMAL状态
    • 通过CanTrcv_SetOpMode(CANTRCV_TRCVMODE_SLEEP)转换到SLEEP状态
  4. SLEEP(睡眠)

    • 收发器最低功耗模式,只能检测唤醒事件
    • 无法收发数据,最低功耗
    • 通过CanTrcv_SetOpMode(CANTRCV_TRCVMODE_STANDBY)转换到STANDBY状态
    • 在总线唤醒后,可直接通过CanTrcv_SetOpMode(CANTRCV_TRCVMODE_NORMAL)转换到NORMAL状态

5.2 唤醒原因状态

当收发器检测到唤醒事件时,会记录唤醒原因,主要包括:

  1. INTERNALLY(内部唤醒)

    • 由ECU内部触发的唤醒
    • 通常是软件请求唤醒
  2. BY_BUS(总线唤醒)

    • 检测到总线上的唤醒模式
    • 由外部设备请求唤醒
  3. 其他唤醒原因

    • NOT_SUPPORTED:不支持的唤醒原因
    • POWER_ON:上电唤醒
    • RESET:复位唤醒
    • SLEEP:唤醒前处于睡眠状态

5.3 总线唤醒处理流程

当收发器在SLEEP状态下检测到总线唤醒事件时,处理流程如下:

  1. 收发器硬件检测到唤醒模式(特定电平变化)
  2. 触发中断或在轮询模式下被检测到
  3. 调用CanTrcv_CheckWakeup()函数确认唤醒
  4. 调用CanIf_TrcvWakeupNotification()通知CAN接口层
  5. 设置唤醒标志并记录唤醒原因为BY_BUS
  6. 上层模块根据需要调用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消息流程

  1. 应用层发起发送请求

    • 应用层调用CanIf_Transmit(PduId, PduInfoPtr)
    • 传递PDU ID和PDU信息(数据指针和长度)
  2. CAN接口层处理

    • 查找L-PDU映射配置,确定硬件对象句柄(Hth)
    • 准备Can_PduType结构,包含CAN ID、数据等
    • 调用Can_Write(Hth, PduInfoPtr)请求发送
  3. CAN驱动层处理

    • 查找硬件对象,填充CAN控制器发送缓冲区
    • 如果缓冲区可用,触发消息发送并返回E_OK
    • 如果缓冲区不可用,返回E_NOT_OK
  4. 发送完成处理

    • CAN控制器发送完成后产生中断
    • CAN驱动处理中断,调用CanIf_TxConfirmation(CanTxPduId)
    • CAN接口层通知应用层发送完成

6.2 接收CAN消息流程

  1. 硬件接收消息

    • CAN控制器接收到匹配的CAN消息并产生中断
    • CAN驱动处理中断,读取硬件接收缓冲区
  2. CAN驱动层处理

    • 调用CanIf_RxIndication(Hrh, CanId, CanDlc, CanSduPtr)
    • 传递硬件对象句柄、CAN ID、数据长度和数据指针
  3. CAN接口层处理

    • 查找L-PDU映射配置,根据硬件对象句柄和CAN ID查找PDU ID
    • 执行CAN ID过滤,验证DLC
    • 如果匹配,调用上层回调函数通知接收数据
    • 如果不匹配或DLC无效,丢弃消息

6.3 总线关闭恢复流程

  1. 检测总线关闭

    • CAN驱动检测到控制器进入总线关闭状态
    • 调用CanIf_ControllerBusOff(ControllerId)通知接口层
  2. 停止控制器

    • 接口层通知应用层总线关闭
    • 调用Can_SetControllerMode(Controller, CAN_T_STOP)停止控制器
  3. 等待恢复时间

    • 根据配置等待一段恢复时间
    • 恢复时间取决于ECU策略和应用需求
  4. 重启控制器

    • 调用Can_SetControllerMode(Controller, CAN_T_START)重新启动控制器
    • CAN驱动重新初始化控制器
    • 通知应用层控制器模式变更

6.4 关键API解析

  1. CanIf_Transmit

    • 功能:请求发送CAN消息
    • 参数:PDU ID和PDU信息
    • 返回:E_OK(接受请求)或E_NOT_OK(拒绝请求)
  2. Can_Write

    • 功能:向CAN控制器发送消息
    • 参数:硬件对象句柄和PDU信息
    • 返回:E_OK(消息已放入发送缓冲区)或E_NOT_OK(发送缓冲区已满)
  3. CanIf_TxConfirmation

    • 功能:通知消息发送完成
    • 参数:PDU ID
    • 调用:CAN驱动在发送完成后调用
  4. CanIf_RxIndication

    • 功能:通知接收到CAN消息
    • 参数:硬件对象句柄、CAN ID、数据长度和数据指针
    • 调用:CAN驱动在接收消息后调用

7. CAN传输层协议

CAN传输层协议(CanTp)实现了ISO 15765-2标准,支持大数据块的分段传输。

7.1 传输层帧类型

ISO 15765-2协议定义了四种帧类型,由PCI(Protocol Control Information)字段的前4位标识:

  1. 单帧(SF - Single Frame)

    • PCI=0x0,用于小于8字节的消息
    • 格式:[0x0|SF_DL|Data...]
    • SF_DL表示数据长度(最大7字节)
  2. 首帧(FF - First Frame)

    • PCI=0x1,多帧传输的第一帧
    • 格式:[0x1|FF_DL_HI|FF_DL_LO|Data...]
    • FF_DL表示总数据长度(两字节)
  3. 连续帧(CF - Consecutive Frame)

    • PCI=0x2,多帧传输的后续帧
    • 格式:[0x2|SN|Data...]
    • SN表示序列号(0-15),循环使用
  4. 流控帧(FC - Flow Control)

    • PCI=0x3,控制数据流
    • 格式:[0x3|FS|BS|STmin]
    • FS表示流状态(0=CTS, 1=WAIT, 2=OVFLW)
    • BS表示块大小(在需要下一个FC前可发送的CF数量)
    • STmin表示连续帧之间的最小时间间隔

7.2 单帧传输流程

用于传输小于8字节的数据:

  1. 上层应用调用CanTp_Transmit(TxSduId, PduInfoPtr)
  2. CanTp准备单帧格式,设置PCI=0x0,SF_DL=数据长度
  3. 调用CanIf_Transmit()发送单帧
  4. 接收方的CanIf接收到消息后调用CanTp_RxIndication()
  5. 接收方CanTp解析单帧,提取数据并通知上层应用
  6. 发送方收到确认后通知上层应用传输完成

7.3 多帧传输流程

用于传输大于7字节的数据:

  1. 首帧(FF)发送

    • 上层应用调用CanTp_Transmit()
    • CanTp准备首帧,设置PCI=0x1,FF_DL=总数据长度
    • 首帧包含前5-6字节数据
    • 调用CanIf_Transmit()发送首帧
  2. 流控帧(FC)处理

    • 接收方收到首帧后分配接收缓冲区
    • 发送流控帧(FC),设置FS=0(CTS),BS=块大小,STmin=帧间隔
    • 发送方解析流控帧,设置传输参数
  3. 连续帧(CF)传输

    • 发送方根据BS和STmin参数发送连续帧
    • 连续帧包含PCI=0x2,SN=序列号(0-15)
    • 接收方校验序列号,拼接数据
    • 当块大小达到或传输完成时,接收方可能发送新的流控帧

7.4 超时参数与错误处理

ISO 15765-2定义了多个超时参数:

  1. N_As:发送方等待首帧传输确认的最大时间
  2. N_Bs:发送方等待流控帧的最大时间
  3. N_Cs:发送方等待连续帧发送确认的最大时间
  4. N_Ar:接收方等待首帧接收的最大时间
  5. N_Br:接收方等待连续帧的最大时间
  6. 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通信解决方案,具有以下特点:

  1. 分层架构

    • 清晰的层次结构,职责明确
    • 标准化的接口,便于模块替换和升级
    • 硬件抽象,屏蔽底层差异
  2. 灵活配置

    • 详细的配置类和数据结构
    • 支持多种控制器模式和处理方式
    • 可根据应用需求定制
  3. 完善的状态管理

    • 控制器和收发器状态机设计合理
    • 支持低功耗模式和唤醒机制
    • 错误处理和恢复机制健全
  4. 高效通信

    • 支持基本CAN帧通信
    • 支持大数据块分段传输
    • 流控制和错误检测机制

通过本文详细介绍的AUTOSAR CAN模块架构、配置、状态机、通信序列及传输层协议,读者可以全面了解AUTOSAR CAN相关模块的设计理念和实现方式,为基于AUTOSAR标准的汽车电子软件开发提供参考。