LIN总线协议详解10(LIN的API)

本文详细介绍了LIN(Local Interconnect Network)的API,包括核心API、传输层API和配置与识别API,阐述了其功能和使用方法。 LIN API是LIN节点软件开发的关键,分为主机节点和从机节点的不同应用。文章还提供了API使用示例,展示了如何在从机节点初始化和主程序中调用API。此外,讨论了API的兼容性和开发工具的选择,强调了在不同硬件上的适配问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

LIN的API

1、什么是API

2、LIN的API

​3、核心API 

​4、传输层API

5、配置与识别API

6、注意事项

6.1、兼容性

6.2、开发工具

​7、API使用示例 

7.1从机节点初始化

7.2、从机节点主程序


LIN的API

        本章介绍 LIN API 的概念、功能和一般用法,并以例子的形式介绍了调用 API 的一般流程。本章内容对应 LIN 规范的以下部分:
● LIN Application Program Interface Specification

1、什么是API

        API(Application Program Interface) 是一组“ 规约 ,用来定义软件模块的使用方法。 API 既可以是数据结构,也可以是若干个函数,还可以是它们的混合。
        软件开发者可以把 API 看作是与软件模块的会话方式。应用程序和程序员既可以使用该模块的功能,又无需访问其源代码,或者理解其内部工作机制的细节。
        API 对软件开发意义重大。软件规模日益庞大,常常需要把复杂系统划分成小的组成部分,或者重复使用代码,这时都会涉及到 API

2、LIN的API

        LIN 规范用 C 语言定义了 LIN API ,但未定义 API 的内部实现。
         LIN 协会规定:对于采用 LIN 规范 2.x 版的 LIN 节点,如果用 C 语言开发应用程序,那么就必须使用 API,对采用 LIN 规范 1.x 版的 LIN 节点,可以不使用标准规定的 API。
        按照用途,可以把 LIN API 分为 3 —— 核心 API、传输层 API 和配置与识别 API 。三类 API 相对独立,彼此关联,如图 6.1 所示。

3、核心API 

        核心 API API 的基础,除了完成协议层的帧收发, LIN 应用层各项功能都要用到核心 API
        核心 API 包含多个函数,其中, l_sch_tick()( 时基节拍管理 ) l_sch_set()( 进度表管理 ) 是与进度表相关的两个函数。其他的函数负责控制各种硬件协调工作,完成初始化、中断响应、比特流收发、字节缓冲、休眠、唤醒以及物理层的差错报告等功能。
        LIN 规范把核心 API 分成 6 个组,如下表 所示。

4、传输层API

LIN 规范 2.0 版开始,增加了传输层 API
        传输层 API 是为配置、识别和诊断这三项服务设置的,是应用层与协议层的接口。 传输层 API 的功能包括:建立并管理 PDU 队列、收发 PDU 以及检查 PDU 的通信状态。 传输层 API 接收应用层消息,调用核心 API 发送主机请求帧;收到从机应答帧时,传输层剥离协议层的帧头信息获得 PDU ,送往应用层处理。
        对于识别或配置服务,因为用于识别和配置的诊断帧已经预先安排在进度表内,所以传输层 API 只是在有关帧时隙到来时才工作,不影响核心 API 的进度表调度,不影响 LIN 的确定性。对于诊断服务,因为诊断请求通常来自诊断仪表或者上级网络( 例如 CAN) ,发生时机和频次不可预测,所以传输层 API 要能动态地产生诊断帧,并将诊断帧插入到当前的进度表里,这会影响 LIN 的确定性。
         LIN 规范定义了两种传输层 API——Raw API 和 Cooked API ,二者功能一致,区别在于对应用层消息的处理方式。两种 API 不建议混用,用户宜根据需要选用一种。 如果节点需要监视通信细节,那么应该用 Raw API,它允许节点以 PDU 为单位处理信息。如果节点只需要转发消息而不需要关心消息内容,那么适合使用 Cooked API,它允许节点以消息为单位处理信息。
传输层 API 如表 6.2 所示。

5、配置与识别API

从LIN 规范 2.0 版开始,增加了配置与识别 API 。用于支持应用层的配置功能和识别功能。
配置与识别 API 如表 6.3 所示。

 注:1. 仅适用于主机节点

        2. 仅适用于从机节点。

        配置 API 除了实现具体的服务项目,还可以向应用程序报告服务的执行情况。
识别 API 包含两个函数: ld_read_by_id ld_read_by_id_callout
        ld_read_by_id 仅供主机节点使用,主机节点只能通过它获得从机节点的硬件信息,例如产品代号等。        
        ld_read_by_id_callout 仅供从机节点使用,这是一 个从 API 向节点应用程序的逆向调用,它并不是必须的,专门用于实现用户自定义的服务。

6、注意事项

6.1、兼容性

        API 的兼容性体现在两个方面,一是不同版本 API 之间的兼容性,二是 API 对帧收发硬件的兼容性。
API 版本之间的兼容性如表 6.4 所示。

 不同的硬件需要使用不同的 APILIN API 的实现通常都是与帧收发硬件密切相关的,不能简单挪用。

6.2、开发工具

        目前已经有一些商品化的 LIN 开发工具。要开发 LIN 的应用,商品化的开发工具并不是必须的,不过,此类工具确实能提高开发效率,尤其是处理那些同时容纳不同 LIN 规范版本的节点的网络。
        图 6.2 显示了此类开发工具的工作原理。 API 的实现可以是独立的若干个库文件,也可能包含在某种开发工具之中。API 通常不能直接被调用,需要配合若干外部附属模块 ( 例如驱动函数 ) 以及映射文件 ( 例如用宏定义实现节点端口与 API 库文件之间的衔接 ) 。库文件与附属模块、映射文件一起,在编译阶段添加到用户代码中

7、API使用示例 

        参考资料[11] 给出了一个 LIN 2.0 版的 API 的示例,从中可以看出 API 的调用次序。该示例包括两部分:在从机节点初始化阶段需要执行的 API,以及在从机节点应用程序中调用 API 的方法。

7.1从机节点初始化

extern unsigned char lin_SomeCotrol_init( void ); 
void PowerON_Reset(void) 
{ 
     HardwareSetup();/* 系统初始化 */ 
     if( l_sys_init() ) 
    { 
         /* LIN API 初始化失败 */ 
        sleep(); 
     } 
     else 
    { 
         if( lin_SomeCotrol_init() ) { 
         /* LIN 相关的模块初始化失败,例如传感器、执行器 */ 
         sleep(); 
         } 
     } 
     /* 其他系统要求的功能 */ 
     main(); 
     return; 
} 
/* 帧收发硬件的驱动程序入口 */ 
const T_Lib_Slave_Handle Slave_handle = { 
 Lin_Drv_Init, 
 Lin_Drv_HeaderIn, 
 Lin_Drv_Pid_RecvReq, 
 Lin_Drv_SendData, 
 Lin_Drv_RecvData, 
 Lin_Drv_SendRecvFinish, 
 Lin_Drv_LinBus_Enable, 
 Lin_Drv_LinBus_Disable, 
 Lin_Drv_WakeUp 
}; 
/* LIN 网络初始化 */ 
unsigned char lin_SomeCotrol_init( void )
{ 
     unsigned char rtn; 
 
     rtn = 0; 
     if( l_ifc_ioctl( 0, LIN_ENTRY_SLAVE_DRV, &Slave_handle ) ) 
    { 
         /* 帧收发硬件的驱动程序初始化失败 */ 
         rtn = 1u; 
    } 
     else 
    { 
        l_ifc_init(0); /* LIN 端口初始化 */ 
        if( l_ifc_connect(0) ) 
        { 
             /* LIN 端口初始化失败 */ 
             rtn = 1u; 
        } 
         else 
        { 
         /* 其他必要的操作 */ 
        } 
    } 
    return rtn; 
}

7.2、从机节点主程序

#include "sfr_r825.h"
#include "Lin_DrvR8C.h"
#include "lin20.h"
void lin_application( void );
/***************************/
/* Main Function */
/***************************/
void main(void)
{
    while( 1 ) 
    {
        /* ......Something to do */
        lin_application();
        /* ......Something to do */
    }
}
/*******************************/ 
/* LIN Application Function */ 
/*******************************/ 
extern l_flg Lin_Frm_FrameMst0_flg; 
extern l_flg Lin_Frm_FrameU1_flg; 
extern l_flg Lin_Frm_FrameU2_flg; 
extern l_flg Lin_Frm_FrameU3_flg; 
extern l_flg Lin_Frm_FrameEve0_flg; 
extern l_flg Lin_Frm_FrameSlv0_flg; 
extern l_flg Lin_Sig_Command_flg; 
extern T_Signal Lin_Sig_Status_Slv0; 
extern T_Signal Lin_Sig_Status_Slv1; 
extern T_Signal Lin_Sig_Command; 
void lin_application( void ) 
{ 
     l_u8 data[8]; 
     l_u16 status; 
 
     /* 判断:是否收到了新的帧? */ 
    if( 0 != l_flg_tst(&Lin_Frm_FrameU1_flg) ) 
    { 
        l_flg_clr( &Lin_Frm_FrameU1_flg ); 
        /* 根据收到的帧执行相应的操作 */ 
    } 
    else if( 0 != l_flg_tst(&Lin_Frm_FrameMst0_flg) ) 
    { 
         l_flg_clr( &Lin_Frm_FrameMst0_flg ); 
         /* 根据收到的帧执行相应的操作 */ 
    } 
    /* 判断:帧是否已经发出? */ 
    if( 0 != l_flg_tst(&Lin_Frm_FrameU2_flg) ) 
    { 
        l_flg_clr( &Lin_Frm_FrameU2_flg ); 
        /* 执行发送结束之后的操作 */ 
    } 
    else if( 0 != l_flg_tst(&Lin_Frm_FrameU3_flg) ) 
    { 
        l_flg_clr( &Lin_Frm_FrameU3_flg ); 
        /* 执行发送结束之后的操作 */
        else if( 0 != l_flg_tst(&Lin_Frm_FrameEve0_flg) ) 
        { 
            l_flg_clr( &Lin_Frm_FrameEve0_flg ); 
            /* 执行发送结束之后的操作 */ 
        } 
        else if( 0 != l_flg_tst(&Lin_Frm_FrameSlv0_flg) ) 
        { 
            l_flg_clr( &Lin_Frm_FrameSlv0_flg ); 
            /* 执行发送结束之后的操作 */ 
        } 
        status = l_ifc_read_status( 0 ); 
        /* 处理可能出现的应答错误 */ 
        if( status & 0x0001u ) 
        { 
            /* 出现应答错误,执行相关操作 */ 
        } 
        if( LD_DATA_AVAILABLE == ld_raw_rx_status(0) ) 
        { 
            ld_get_raw( 0, data ); 
        } 
        /* 判断:来自主节点的信号被更新了吗? */ 
        if( 0 != l_flg_tst(&Lin_Sig_Command_flg) ) 
        { 
            l_flg_clr( &Lin_Sig_Command_flg ); 
            if( 0x1234u == l_u16_rd(&Lin_Sig_Command) ) 
            { 
                l_u16_wr( &Lin_Sig_Status_Slv0, 0x0101u ); 
                l_u16_wr( &Lin_Sig_Status_Slv1, 0x0201u ); 
                /* 其他相关操作 */ 
            } 
            else if( 0x5678u == l_u16_rd(&Lin_Sig_Command) ) 
            { 
                l_u16_wr( &Lin_Sig_Status_Slv0, 0x0100u ); 
                l_u16_wr( &Lin_Sig_Status_Slv1, 0x0200u ); 
                /* 其他相关操作 */ 
            } 
        } 
        /* 监测休眠命令 */ 
        if( status & 0x0008u ) 
        { 
            /* LIN 端口休眠的相关操作 */ 
        } 
    return; 
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值