AUTOSAR进阶图解==>AUTOSAR_SRS_LIN

发布于:2025-07-30 ⋅ 阅读:(16) ⋅ 点赞:(0)

AUTOSAR LIN (Local Interconnect Network) 协议详解

基于AUTOSAR CP 4.4.0 规范的LIN协议分析

目录

  1. 概述
  2. AUTOSAR LIN架构
  3. LIN状态转换
  4. LIN帧结构
  5. LIN调度表
  6. 总结

1. 概述

LIN(Local Interconnect Network,本地互联网络)是一种低成本的串行通信总线系统,主要用于汽车电子领域的分布式系统。AUTOSAR(AUTomotive Open System ARchitecture)标准为LIN协议提供了完整的软件栈支持,实现了对LIN主节点和从节点的配置与控制。

本文基于AUTOSAR CP 4.4.0标准的LIN相关规范,详细分析LIN协议在AUTOSAR架构中的实现方式、状态转换机制、帧结构和调度表设计。

AUTOSAR LIN协议主要包含以下模块:

  • LIN接口 (LinIf):提供统一的API接口
  • LIN驱动 (Lin):负责与硬件交互
  • LIN传输层 (LinTp):处理多帧数据传输
  • LIN收发器驱动 (LinTrcv):管理物理层通信

这些模块共同遵循ISO 17987规范,并向后兼容LIN 2.2、LIN 2.1、LIN 2.0和LIN 1.3等早期版本的LIN规范。


2. AUTOSAR LIN架构

在这里插入图片描述

2.1 架构层次分析

AUTOSAR LIN架构图展示了LIN协议栈在AUTOSAR软件架构中的位置和各模块间的关系。从图中可以清晰地看到,LIN协议栈位于通信服务层和微控制器抽象层之间,作为连接应用软件和硬件的桥梁。

组件 应用软件组件:
  • 职责: 应用软件组件是用户开发的功能模块,通过通信服务层访问LIN总线通信功能
  • 功能点:
    • 使用通信管理服务发起或终止LIN通信
    • 通过PDU路由器发送和接收LIN数据
    • 配置LIN通信参数
组件 通信管理:
  • 职责: 管理所有通信介质(包括LIN)的启动和关闭
  • 功能点:
    • 处理网络管理请求
    • 控制LIN通信状态(唤醒、睡眠)
    • 协调多个网络层的通信状态

根据源文档中的[SRS_Lin_01560]要求,当在睡眠模式转换过程中接收到唤醒请求时,通信管理必须取消睡眠过程,并恢复到运行模式。

组件 LIN接口(LinIf):
  • 职责: 管理LIN调度表,处理LIN帧收发,提供统一API给上层模块
  • 功能点:
    • 管理调度表执行
    • 处理LIN主节点和从节点功能
    • 支持ISO 17987规范及兼容早期LIN规范
    • 提供唤醒和睡眠控制

源文档中的[SRS_Lin_01577]要求LIN接口必须兼容ISO 17987规范,包括支持不同版本的LIN协议。

组件 LIN驱动(Lin):
  • 职责: 控制UART硬件,处理LIN帧的物理传输
  • 功能点:
    • 帧错误检测与处理
    • 管理检验和类型(经典和增强)
    • 支持主节点和从节点操作
    • 实现唤醒和睡眠功能

源文档[SRS_Lin_01504]和[SRS_Lin_01598]指出,AUTOSAR架构适用于LIN主节点和从节点的实现,支持各版本LIN规范。

组件 LIN传输层(LinTp):
  • 职责: 支持多帧数据传输,分段和重组,传输流控制
  • 功能点:
    • 处理诊断数据传输
    • 支持分段和重组
    • 实现传输流控制
    • 管理连接

源文档中定义了LinTp支持LIN诊断传输,包括支持FF(首帧)、CF(连续帧)和SF(单帧)的传输。

2.2 代码示例

以下是LIN接口初始化的代码示例,展示了如何配置和初始化LIN接口:

/* LIN接口配置结构 */
typedef struct {
    uint8 LinIfTimeBase;                 /* LIN接口时间基准(ms) */
    uint8 LinIfVersionInfo;              /* 版本信息启用标志 */
    uint8 LinIfChannel;                  /* LIN通道索引 */
    const LinIf_ChannelConfigType* LinIfChannelConfig; /* 通道配置 */
    const LinIf_ScheduleTableType* LinIfScheduleTableConfig; /* 调度表配置 */
} LinIf_ConfigType;

/* LIN接口初始化函数 */
Std_ReturnType LinIf_Init(const LinIf_ConfigType* ConfigPtr)
{
    Std_ReturnType ret = E_NOT_OK;
    
    /* 参数检查 */
    if (ConfigPtr == NULL) {
        Det_ReportError(LINIF_MODULE_ID, LINIF_INSTANCE_ID, 
                        LINIF_SID_INIT, LINIF_E_PARAM_POINTER);
        return E_NOT_OK;
    }
    
    /* 配置LIN接口 */
    LinIf_State = LINIF_INIT;
    
    /* 初始化所有通道 */
    for (uint8 channel = 0; channel < LINIF_CHANNEL_COUNT; channel++) {
        LinIf_ChannelState[channel] = LINIF_CH_OPERATIONAL;
        /* 初始化通道特定参数 */
    }
    
    /* 初始化LIN驱动 */
    ret = Lin_Init(&Lin_Config);
    
    if (ret == E_OK) {
        LinIf_State = LINIF_OPERATIONAL;
    }
    
    return ret;
}

3. LIN状态转换

在这里插入图片描述

3.1 状态转换机制

LIN状态转换图展示了LIN驱动和接口的状态管理机制,包括初始化、运行和睡眠状态之间的转换。

状态 LIN_UNINIT:
  • 描述: LIN驱动的未初始化状态
  • 特性:
    • 模块加载后的初始状态
    • 此状态下不能执行任何LIN操作
    • 必须通过Lin_Init函数转换到初始化状态
状态 LIN_INIT:
  • 描述: LIN驱动的初始化状态
  • 特性:
    • Lin_Init函数执行后的临时状态
    • 在此状态下完成硬件配置
    • 初始化完成后自动转换到运行状态
状态 LIN_CH_OPERATIONAL:
  • 描述: LIN通道的正常运行状态
  • 特性:
    • 可以执行LIN帧传输
    • 调度表可以正常运行
    • 可以通过Lin_GoToSleep函数请求进入睡眠状态
状态 LIN_CH_SLEEP_TRANSITION:
  • 描述: LIN通道的睡眠转换状态
  • 特性:
    • 主节点会发送睡眠命令帧
    • 从节点收到睡眠命令或总线空闲超时进入此状态
    • 如果在此状态收到唤醒请求,则取消睡眠并返回运行状态

根据源文档[SRS_Lin_01560],如果在睡眠转换过程中接收到唤醒请求,必须取消睡眠过程并返回运行状态。

状态 LIN_CH_SLEEP:
  • 描述: LIN通道的睡眠状态
  • 特性:
    • 低功耗模式
    • 所有LIN通信暂停
    • 只能通过唤醒信号或软件唤醒命令退出

3.2 代码示例

以下代码展示了LIN驱动的状态转换操作:

/* LIN驱动睡眠命令函数 */
Std_ReturnType Lin_GoToSleep(uint8 Channel)
{
    Std_ReturnType ret = E_NOT_OK;
    
    /* 检查模块状态 */
    if (Lin_State != LIN_OPERATIONAL) {
        Det_ReportError(LIN_MODULE_ID, LIN_INSTANCE_ID, 
                        LIN_SID_GOTOSLEEP, LIN_E_UNINIT);
        return E_NOT_OK;
    }
    
    /* 检查通道参数 */
    if (Channel >= LIN_CHANNEL_COUNT) {
        Det_ReportError(LIN_MODULE_ID, LIN_INSTANCE_ID, 
                        LIN_SID_GOTOSLEEP, LIN_E_INVALID_CHANNEL);
        return E_NOT_OK;
    }
    
    /* 检查通道状态 */
    if (Lin_ChannelState[Channel] != LIN_CH_OPERATIONAL) {
        Det_ReportError(LIN_MODULE_ID, LIN_INSTANCE_ID, 
                        LIN_SID_GOTOSLEEP, LIN_E_INVALID_STATE);
        return E_NOT_OK;
    }
    
    /* 发送睡眠命令帧 */
    ret = Lin_SendSleepFrame(Channel);
    
    if (ret == E_OK) {
        /* 更新通道状态 */
        Lin_ChannelState[Channel] = LIN_CH_SLEEP_TRANSITION;
    }
    
    return ret;
}

/* LIN驱动唤醒函数 */
Std_ReturnType Lin_Wakeup(uint8 Channel)
{
    Std_ReturnType ret = E_NOT_OK;
    
    /* 检查模块状态 */
    if (Lin_State != LIN_OPERATIONAL) {
        Det_ReportError(LIN_MODULE_ID, LIN_INSTANCE_ID, 
                        LIN_SID_WAKEUP, LIN_E_UNINIT);
        return E_NOT_OK;
    }
    
    /* 检查通道参数 */
    if (Channel >= LIN_CHANNEL_COUNT) {
        Det_ReportError(LIN_MODULE_ID, LIN_INSTANCE_ID, 
                        LIN_SID_WAKEUP, LIN_E_INVALID_CHANNEL);
        return E_NOT_OK;
    }
    
    /* 发送唤醒脉冲 */
    ret = Lin_SendWakeupPulse(Channel);
    
    if (ret == E_OK) {
        /* 更新通道状态 */
        if (Lin_ChannelState[Channel] == LIN_CH_SLEEP || 
            Lin_ChannelState[Channel] == LIN_CH_SLEEP_TRANSITION) {
            Lin_ChannelState[Channel] = LIN_CH_OPERATIONAL;
        }
    }
    
    return ret;
}

4. LIN帧结构

在这里插入图片描述

4.1 帧结构分析

LIN帧结构图展示了LIN帧的完整组成部分,包括帧头和帧响应。LIN帧由主节点发送的帧头和从节点发送的帧响应两部分组成。

组件 Break字段:
  • 描述: LIN帧的起始部分,用于同步
  • 特性:
    • 长度至少13位低电平
    • 用于唤醒接收器
    • 标志新帧开始
组件 同步字段:
  • 描述: 用于波特率同步的固定值字段
  • 特性:
    • 固定值0x55 (01010101)
    • 用于波特率同步
    • 通过位沿变化帮助从节点确定波特率
组件 帧ID (PID):
  • 描述: 标识LIN帧类型和用途的字段
  • 特性:
    • 6位ID + 2位校验位
    • 决定帧类型和优先级
    • 0x3C/0x3D为诊断帧
    • 0x3E为主节点请求帧(MRF)
    • 0x3F为从节点响应帧(SRF)

源文档中提到,ISO 17987规范支持两种LIN ID分配模型(“2.0"和"2.1或更高版本”),确保兼容性。

组件 数据字段:
  • 描述: 包含实际传输数据的字段
  • 特性:
    • 长度1-8字节
    • 首先传输LSB (最低有效位)
    • 内容由帧ID决定

源文档[SRS_Lin_01522]强调LIN-SDU(数据部分)必须在传输和接收时保持一致性,包括有效数据和标志位。

组件 校验和:
  • 描述: 用于校验数据完整性的字段
  • 特性:
    • LIN 1.x: 经典校验(仅数据)
    • LIN 2.x/ISO 17987: 增强校验(包含PID和数据)
    • 诊断帧始终使用经典校验

源文档中明确指出,除了预留的LIN ID外,每个LIN ID的校验和模型(经典和增强)都是可配置的。

4.2 代码示例

以下是处理LIN帧的代码示例:

/* LIN帧结构定义 */
typedef struct {
    uint8 Pid;          /* 帧ID (PID) */
    uint8 Cs;           /* 校验和类型 (LIN_CLASSIC_CS, LIN_ENHANCED_CS) */
    uint8 Drc;          /* 响应方向 (LIN_MASTER_RESPONSE, LIN_SLAVE_RESPONSE) */
    uint8 Dl;           /* 数据长度 (1-8) */
    uint8 Data[8];      /* 数据内容 */
} Lin_PduType;

/* 计算LIN帧校验和 */
uint8 Lin_CalculateChecksum(const Lin_PduType* LinPduPtr)
{
    uint8 checksum = 0;
    uint8 i;
    
    if (LinPduPtr == NULL) {
        return 0;
    }
    
    /* 增强校验包含PID */
    if (LinPduPtr->Cs == LIN_ENHANCED_CS) {
        checksum = LinPduPtr->Pid;
    }
    
    /* 累加数据字节 */
    for (i = 0; i < LinPduPtr->Dl; i++) {
        checksum += LinPduPtr->Data[i];
        /* 处理进位 */
        if (checksum >= 0xFF) {
            checksum -= 0xFF;
        }
    }
    
    /* 取反 */
    checksum = ~checksum;
    
    return checksum;
}

/* 发送LIN帧 */
Std_ReturnType Lin_SendFrame(uint8 Channel, const Lin_PduType* PduInfoPtr)
{
    Std_ReturnType ret = E_NOT_OK;
    
    /* 参数检查 */
    if (PduInfoPtr == NULL) {
        Det_ReportError(LIN_MODULE_ID, LIN_INSTANCE_ID, 
                        LIN_SID_SENDFRAME, LIN_E_PARAM_POINTER);
        return E_NOT_OK;
    }
    
    if (Channel >= LIN_CHANNEL_COUNT) {
        Det_ReportError(LIN_MODULE_ID, LIN_INSTANCE_ID, 
                        LIN_SID_SENDFRAME, LIN_E_INVALID_CHANNEL);
        return E_NOT_OK;
    }
    
    /* 数据长度检查 */
    if (PduInfoPtr->Dl < 1 || PduInfoPtr->Dl > 8) {
        Det_ReportError(LIN_MODULE_ID, LIN_INSTANCE_ID, 
                        LIN_SID_SENDFRAME, LIN_E_PARAM_LENGTH);
        return E_NOT_OK;
    }
    
    /* 发送帧 */
    if (Lin_ChannelState[Channel] == LIN_CH_OPERATIONAL) {
        /* 发送LIN帧头 */
        ret = Lin_SendHeader(Channel, PduInfoPtr->Pid);
        
        /* 如果是主节点响应,发送响应部分 */
        if (ret == E_OK && PduInfoPtr->Drc == LIN_MASTER_RESPONSE) {
            ret = Lin_SendResponse(Channel, PduInfoPtr);
        }
    } else {
        Det_ReportError(LIN_MODULE_ID, LIN_INSTANCE_ID, 
                        LIN_SID_SENDFRAME, LIN_E_INVALID_STATE);
    }
    
    return ret;
}

5. LIN调度表

在这里插入图片描述

5.1 调度表分析

LIN调度表结构图展示了AUTOSAR中LIN调度表的配置模型,包括表项、帧触发和相关参数。

类 LinIfScheduleTable:
  • 功能: 定义LIN主节点使用的调度表,控制LIN总线通信
  • 关键属性:
    • LinIfScheduleTableName:
      • 描述: 调度表的唯一标识符名称
      • 类型: String
      • 来源: 系统配置工具
    • LinIfScheduleTableIndex:
      • 描述: 调度表索引编号
      • 类型: Integer
      • 取值范围: 0-255
    • LinIfRunMode:
      • 描述: 调度表运行模式
      • 类型: RunModeType
      • 取值范围: LIN_CONTINUOUS, LIN_ONCE
    • LinIfResumePosition:
      • 描述: 调度表恢复位置
      • 类型: Integer
      • 默认值: 0

源文档中提到,调度表用于确定LIN总线上的通信流程,一个LIN总线可以配置多个调度表。

类 LinIfScheduleTableEntry:
  • 功能: 定义调度表中的单个表项,包含帧触发和延迟时间
  • 关键属性:
    • LinIfEntryIndex:
      • 描述: 表项索引号
      • 类型: Integer
    • LinIfEntryDelay:
      • 描述: 延迟时间(毫秒)
      • 类型: Integer
    • LinIfFrameRef:
      • 描述: 引用的LIN帧
      • 类型: Reference
    • LinIfCollisionResolution:
      • 描述: 碰撞解决标志
      • 类型: Boolean
      • 默认值: FALSE

源文档中的ISO 17987规范第5.3节详细描述了调度表的结构和行为。

类 LinIfFrameTriggering:
  • 功能: 定义LIN帧的触发配置,包括帧类型和校验和类型
  • 关键属性:
    • LinIfPduRef:
      • 描述: 引用的PDU
      • 类型: Reference
    • LinIfChannelRef:
      • 描述: 引用的LIN通道
      • 类型: Reference
    • LinIfFrameType:
      • 描述: 帧类型
      • 类型: FrameType
      • 取值范围: UNCONDITIONAL, EVENT_TRIGGERED, SPORADIC, DIAGNOSTIC, SLEEP
    • LinIfChecksumType:
      • 描述: 校验和类型
      • 类型: ChecksumType
      • 取值范围: CLASSIC, ENHANCED

源文档提到,除了预留的LIN ID外,每个LIN ID的校验和类型都是可配置的,支持经典校验和和增强校验和。

5.2 代码示例

以下是LIN调度表配置的代码示例:

/* LIN调度表配置结构 */
typedef enum {
    LIN_CONTINUOUS,  /* 连续执行模式 */
    LIN_ONCE         /* 单次执行模式 */
} LinIf_ScheduleTableRunModeType;

typedef enum {
    LIN_UNCONDITIONAL,    /* 无条件帧 */
    LIN_EVENT_TRIGGERED,  /* 事件触发帧 */
    LIN_SPORADIC,         /* 偶发帧 */
    LIN_DIAGNOSTIC,       /* 诊断帧 */
    LIN_SLEEP             /* 睡眠帧 */
} LinIf_FrameTypeType;

typedef enum {
    LIN_CLASSIC_CS,   /* 经典校验和 */
    LIN_ENHANCED_CS   /* 增强校验和 */
} LinIf_CSModelType;

/* 帧触发配置 */
typedef struct {
    uint8 LinIfPid;                  /* 帧ID */
    LinIf_FrameTypeType LinIfFrameType;  /* 帧类型 */
    LinIf_CSModelType LinIfCsModel;  /* 校验和类型 */
    uint8 LinIfDl;                   /* 数据长度 */
    const PduIdType LinIfTxPduId;    /* 发送PDU ID */
    const PduIdType LinIfRxPduId;    /* 接收PDU ID */
} LinIf_FrameTriggeringConfigType;

/* 调度表表项配置 */
typedef struct {
    uint16 LinIfDelay;               /* 延迟时间(ms) */
    const LinIf_FrameTriggeringConfigType* LinIfFrameTriggeringRef;  /* 帧触发引用 */
} LinIf_ScheduleTableEntryType;

/* 调度表配置 */
typedef struct {
    uint8 LinIfScheduleTableIndex;   /* 调度表索引 */
    LinIf_ScheduleTableRunModeType LinIfRunMode;  /* 运行模式 */
    uint8 LinIfEntryCount;           /* 表项数量 */
    const LinIf_ScheduleTableEntryType* LinIfEntry;  /* 表项数组 */
} LinIf_ScheduleTableConfigType;

/* 调度表配置示例 */
const LinIf_FrameTriggeringConfigType LinIf_FrameTriggeringConfig[] = {
    {
        .LinIfPid = 0x10,
        .LinIfFrameType = LIN_UNCONDITIONAL,
        .LinIfCsModel = LIN_ENHANCED_CS,
        .LinIfDl = 8,
        .LinIfTxPduId = PDU_ID_TX_ENGINE_STATUS,
        .LinIfRxPduId = PDU_ID_RX_ENGINE_STATUS
    },
    {
        .LinIfPid = 0x22,
        .LinIfFrameType = LIN_UNCONDITIONAL,
        .LinIfCsModel = LIN_ENHANCED_CS,
        .LinIfDl = 4,
        .LinIfTxPduId = PDU_ID_TX_DOOR_STATUS,
        .LinIfRxPduId = PDU_ID_RX_DOOR_STATUS
    },
    {
        .LinIfPid = 0x3C,
        .LinIfFrameType = LIN_DIAGNOSTIC,
        .LinIfCsModel = LIN_CLASSIC_CS,  /* 诊断帧使用经典校验和 */
        .LinIfDl = 8,
        .LinIfTxPduId = PDU_ID_TX_DIAG,
        .LinIfRxPduId = PDU_ID_RX_DIAG
    }
};

const LinIf_ScheduleTableEntryType LinIf_NormalTableEntries[] = {
    {
        .LinIfDelay = 10,  /* 10ms */
        .LinIfFrameTriggeringRef = &LinIf_FrameTriggeringConfig[0]
    },
    {
        .LinIfDelay = 20,  /* 20ms */
        .LinIfFrameTriggeringRef = &LinIf_FrameTriggeringConfig[1]
    }
};

const LinIf_ScheduleTableConfigType LinIf_ScheduleTableConfig[] = {
    {
        .LinIfScheduleTableIndex = 0,
        .LinIfRunMode = LIN_CONTINUOUS,
        .LinIfEntryCount = 2,
        .LinIfEntry = LinIf_NormalTableEntries
    }
};

/* 请求切换调度表 */
Std_ReturnType LinIf_ScheduleRequest(uint8 Channel, uint8 ScheduleTableIndex)
{
    Std_ReturnType ret = E_NOT_OK;
    
    /* 参数检查 */
    if (Channel >= LINIF_CHANNEL_COUNT) {
        Det_ReportError(LINIF_MODULE_ID, LINIF_INSTANCE_ID, 
                        LINIF_SID_SCHEDULEREQUEST, LINIF_E_INVALID_CHANNEL);
        return E_NOT_OK;
    }
    
    if (ScheduleTableIndex >= LINIF_SCHEDULE_TABLE_COUNT) {
        Det_ReportError(LINIF_MODULE_ID, LINIF_INSTANCE_ID, 
                        LINIF_SID_SCHEDULEREQUEST, LINIF_E_NONEXISTENT_TABLE);
        return E_NOT_OK;
    }
    
    /* 检查LIN接口状态 */
    if (LinIf_State != LINIF_OPERATIONAL) {
        Det_ReportError(LINIF_MODULE_ID, LINIF_INSTANCE_ID, 
                        LINIF_SID_SCHEDULEREQUEST, LINIF_E_UNINIT);
        return E_NOT_OK;
    }
    
    /* 检查通道状态 */
    if (LinIf_ChannelState[Channel] != LINIF_CH_OPERATIONAL) {
        return E_NOT_OK;
    }
    
    /* 切换调度表 */
    LinIf_ActiveScheduleTable[Channel] = ScheduleTableIndex;
    LinIf_ScheduleTableIndex[Channel] = 0;  /* 从第一个表项开始 */
    
    return E_OK;
}

6. 总结

AUTOSAR LIN协议规范提供了完整的软件栈支持,实现了对LIN主节点和从节点的配置与控制。通过本文的分析,我们了解了AUTOSAR LIN的架构设计、状态管理、帧结构和调度表机制。

AUTOSAR LIN协议的主要特点:

  • 标准兼容性:遵循ISO 17987规范,同时向后兼容LIN 2.2、LIN 2.1、LIN 2.0和LIN 1.3等早期版本
  • 模块化架构:包含LIN接口、LIN驱动、LIN传输层和LIN收发器驱动四个核心模块
  • 灵活配置:支持多种校验和类型、帧类型和调度表类型
  • 状态管理:完善的状态转换机制,支持唤醒和睡眠功能
  • 诊断支持:通过LIN传输层支持诊断服务

AUTOSAR LIN协议的实现为汽车电子系统提供了稳定、标准化的通信方案,特别适合成本敏感的低速控制场景,如车窗控制、座椅调节、照明控制等应用。


网站公告

今日签到

点亮在社区的每一天
去签到