因为LIN相较于CAN通信小众很多,即使是接触过LIN通信的同学往往对其的认识也只是停留在使用层面,所以文章从LIN通信的基础概念讲起,意图在读者能够对LIN通信有一个比较直观且全面的认识,使各位能够更好的理解后面的驱动配置以及调试实现。
文章后续内容则延续系列一贯风格,从LIN驱动基础概念讲起,然后根据开发板实际情况完成MCAL配置,最后提供调试代码与测试结果,帮助读者更好的理解LIN驱动的使用。
目录
LIN通信简介
LIN 是 Local Interconnect Network 的缩写,LIN总线是针对汽车分布式电子系统而定义的一种低成本串行通信总线,是对CAN总线的一种补充,适用于对网络的带宽、性能或容错要求不高的总线应用。LIN总线是基于UART/SCI开发的协议,采用主从控制方式,单主机多从机的工作模式。在汽车应用中,LIN总线主要用于车身系统,例如:后视镜调节、座椅调节、电动车窗、雨刮器控制、顶灯控制、空调系统等。
LIN总线采用单主机多从机的通信方式,主节点(Master Node)包括主机任务(Master Task)与从机任务(Slave Task),从节点(Slave Node)只包括从机任务,由于物理层的限制,LIN网络最多只能连接16个节点。
这里涉及两个任务:主机任务和从机任务。主机任务仅仅存在于主节点中,负责根据Schedule Tables来调度总线上帧的传输次序,并监控数据、处理错误,给从节点提供标准时钟参考、并接收从节点发出的唤醒总线命令。从机任务则根据接收到的帧头,判断发送或者接收应答。
LIN帧报文包括帧头(Header)和应答(Response)两部分。主机任务负责发送帧头,从机任务接收到帧头后,对帧头进行解析,判断需要发送应答、接收应答、还是不作响应,一个帧头对应一个应答。
LIN帧报文结构如下图所示:
我们来分为报头和应答两个部分来分别介绍帧的组成:
- 报头(Header):帧头由同步间隔段(Sync break field)、同步段(Sync field)和PID(Protected Identifier)组成。
-
同步间隔段:由至少13个持续的显性位和至少1个隐性位的界定符组成,由于总线空闲时处于隐性位,并且除同步间隔场外的任何其他字段都不会发出大于9个位的显性位,所以同步间隔可以表示一帧报文的起始。
-
同步段:用于初始同步,固定格式,长度10位,由起始位0,数据0x55,停止位1组成的字节域。
-
PID:由6位ID和两位奇偶校验位组成,长度10位,ID范围0x00-0x3F,0x3C-0x3D为诊断报文,0x3E-0x3F保留。
-
-
应答(Response):应答包含数据段(Data Field)与校验和段(Checksum)。
-
数据段:1~8字节数据。
-
校验和段:校验和保护传输内容。
-
PS:1个起始位(显性电平)+8位数据位+1位停止位(隐性电平)表示为一个字节域,属于标准的标准UART数据编码方式,除了同步间隔段外,其余各段都是通过字节域的格式进行传输。在LIN帧报文中,数据传输都是先发送LSB(Least Significant Bit,最低有效位),最后发送MSB(Most Significant Bit,最高有效位)。
调度表(Schedule Tables)规定总线上帧的传输次序以及各帧在总线上的传输时间。进度表位于主节点,主机任务根据应用层需要进行调度,进度表可以有多个,顺序循环执行,若发生冲突,则中断进度表,执行冲突解决调度表。
进度表除规定了帧ID的传输次序外,还规定了帧时隙(Frame Slot)的大小,其规定了一个帧的帧头起始点与下一个的帧的帧头起始点之间的时间。每个帧的帧时隙都可以不同,一个帧时隙对应了进度表的一个入口。帧时隙必须为时基(Time Base为LIN子网的最小计时单位,通常设定为5ms或10ms。)的整数倍,并且起始于时基的开始时刻,称为时基的节拍(Tick),等待当前帧时隙结束后,才能切换到另外一个进度表。
LIN的帧类型一共分为无条件帧(Unconditional Frame)、事件触发帧(Event Triggered Frame)、偶发帧(Sporadic Frame)、诊断帧(Diagnostic Frame)、保留帧(Reserved Frame)。我们下面介绍两个常用的帧类型。
无条件帧(Unconditional Frame)具有单一发布节点,无论信号是否发生变化,帧头都会被设定好的节点被无条件应答。 无条件帧在主机任务分配给它的固定的帧时隙中传输。总线上一旦有帧头发送出去,必须有从机任务做出应答。
-
当帧头ID=0x10时,从节点1为应答发布节点,主节点为订阅节点,表示从机向主机汇报自身信号状态的典型应用。
-
当帧头ID=0x11时,主节点为应答发布节点,从节点1与从节点2为订阅节点,表示主机向从机发布信息的典型应用。
-
当帧头ID=0x12时,从节点2为应答发布节点,从节点1为订阅节点,表示从节点之间彼此通信的典型应用。
事件触发帧(Event Triggered Frame)是主节点在一个帧时隙中,查询从节点信号是否发生改变,信号发生改变的节点将成为发布节点,当存在多个发布节点时,通过冲突解决进度表来解决冲突,如下图所示。事件触发帧的典型应用就是查询四个车门的开关状况,若其中一个车门状态发生变化,则该节点做出应答,可以减小带宽(避免每次都要轮询各个车门状态)。
与无条件帧不同,事件触发帧会出现两种特殊情况:
-
没有车门被打开,帧头无节点应答,事件触发帧允许一帧中只有帧头。
-
同时开启了两扇及以上的门,两个节点同时应答,事件触发帧不会视为错误,而是调用“冲突解决进度表”,轮询各个车门状态。
-
第1帧,事件触发帧帧头ID 0x20发出后,对应节点信号均未发生改变,不做应答。
-
第2帧,从节点1信号发生改变,应答。
-
第3帧,从节点1和从节点2信号均发生改变,同时应答,产生冲突,需要调用冲突解决进度表。
-
第4帧,解决冲突,发送对应无条件帧帧头ID0x21,从节点1应答。
-
第5帧,解决冲突,发送对应无条件帧帧头ID0x22,从节点2应答。
LIN驱动概述
LIN驱动遵循LIN协议2.1(ISO-17987)并符合AUTOSAR4.2.2和AUTOSAR 4.4.0版本定义,这两个版本都支持主模式,但仅在AUTOSAR4.4版本中支持从模式。英飞凌芯片提供的名叫ASCLIN模块为LIN协议实现提供支持。LIN驱动提供UI选项,用于配置符合AUTOSAR LIN规范(版本AS4.2.2和AS 4.4.0)中描述的驱动程序参数以及用于配置ASCLIN各种功能块的额外参数。LIN驱动支持主模式和从模式的LIN通道。下图为LIN软硬件接口图。
在AURIX2G MCAL实现中,LIN驱动程序使用ASCLIN进行LIN通信。驱动程序使用的关键硬件功能特性包括:
- LIN所支持功能特性。
- LSB传输。
- 一个停止位。
- 范围1K~20K波特率范围。
- TX和RX可以使用FIFO。
- 同步中断场产生。
- 使用LIN看门狗(报头超时、响应超时)。
- 碰撞检测特性。
- 唤醒检测特性。
- 中断与错误中断处理标志。
LIN和UART驱动程序使用ASCLIN IP。将ASCLIN通道分配给LIN/UART驱动程序由MCU驱动程序完成。LIN和UART驱动程序都只利用分配给它们的通道。LIN驱动程序使用以下来自ASCLIN的硬件事件:
- 主响应:传输报头(TH-传输报头结束标志)和响应(TR-传输响应结束标志),报头和响应传输错误,碰撞错误(CE-碰撞检测错误标志),奇偶校验错误(LP-LIN奇偶校验错误标志),报头超时错误(HT-报头超时标志)。
- 从响应:接收(接收响应结束标志)和发送响应(发送响应结束标志),接收错误(只接收到ID但没有响应),校验和错误(ceccolision Detecion Error标志),帧错误(FE-帧错误标志),FIFO溢出(RFU-Receive FIFO错误标志,RFO-Receive FIFO溢出标志),报头超时错误(HT-报头超时错误标志)和响应超时错误(RT-响应超时结束标志)。
- 从对从:报头传输错误( TH-传输报头结束标志)冲突错误,(CE-碰撞检测错误标志),奇偶校验错误(LP-LIN奇偶校验错误标志)和报头超时错误(HT-报头超时标志)。
环境与目标
本文使用的为英飞凌提供的开发板KIT_A2G_TC397XA_TFT,使用P10.6作为RX,P10.5作为TX,经过LIN收发器之后,在X203上排针的第4号引脚作为LIN信号输出/输入。
涉及的软件如下:
- EB-tresos:用于生成动态代码,具体工程搭建参考《【AUTOSAR MCAL】MCAL基础与EB tresos工程新建》。
- HighTech:用于编译生成elf文件,具体的工程搭建参考《【MCAL】HighTec集成TC3xx对应MCAL的Demo》。
- UDE 5.2:用于下载和调试程序。
涉及的参考文档如下表。
序号 | 参考资料 | 内容 |
1 | 《Infineon-AURIX_TC39x-UserManual-v02_00-EN》 | 英飞凌TC39x用户手册 |
2 | 《Infineon-AURIX_TC3xx_Part1-UserManual-v02_00-EN.pdf》 | 英飞凌TC3xx用户手册 |
3 | 《Infineon-AURIX_TC3xx_Part2-UserManual-v02_00-EN.pdf》 | 英飞凌TC3xx用户手册 |
4 | 《Infineon-TC39x-DataSheet-v01_00-EN》 | 英飞凌TC39x数据手册 |
5 | 《ApplicationKitManual-TC3X7-ADAS-V21.pdf》 | 开发板KIT_A2G_TC397XA_TFT说明 |
6 | 《MC-ISAR_TC3xx_UM_Lin_17_AscLin.pdf》 | 英飞凌提供的TC3xx芯片LIN用户手册 |
配置目标如下:
使用Lin_FrameResponseType为LIN_MASTER_RESPONSE类型发送一个报头ID为0x80,应答(应答为主发送)为0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,0xAA,0xBB的LIN帧。
EB tresos配置
Port
根据TC39x芯片DataSheet,配置选择对应的复用功能为ASCLIN2的TX与RX。
下图为对应Port口中TX的配置。
下图是RX的配置。
MCU
McuClockSettingConfig
ASCLIN模块时钟。
McuAscLinAllocationConf
选择LIN使用的对应ASCLIN模块,ASCLIN一共有12个模块,可以用作LIN/UART/STDLIN。
LIN
LinGeneral
这个容器包含LIN驱动的通用参数。
其中需要关注的参数有:
- LinHwMcuTrigSleepEnable:通过为所有配置的通道设置相应的CLC寄存器EDIS位,根据请求启用或禁用ASCLIN模块睡眠。该参数对于所有ASCLIN通道都是
通用的。 - LinSysClockRef:此参数为MCU驱动配置的系统时钟。以此为参考用于波特率计算。
- LinCsrClksel :该参数为LIN驱动选择波特率逻辑时钟。
- ASCLINF:ASCLIN fast clock mode。
- ASCLINS:ASCLIN slow clock mode。
LinChannel
这个容器包含LIN通道的配置信息。
我们需要关注的参数有:
- LinChannelBaudRate: 指定LIN通道的波特率。如果LinAutoCalcBaudParams(自动波特率)参数为true,则该参数可编辑。
- LinChannelld:定义通道的数字ID,这是通道的逻辑ID。一般都是从0开始的。
- LinChannelWakeupSupport:指定LIN硬件通道是否支持唤醒功能。
- LinChanAssignedHw:该参数定义LIN通道选择哪个ASCLIN模块。例如在本例子里面的ASCLIN2。
- LinAutoCalcBaudParams:是否自动计算波特率。自动计算则根据模块时钟和LinChannelBaudRate自动完成波特率相关寄存器配置。
- LinInterByteSpace:该参数用于配置LinInterByteSpace延迟(以位为单位)。在LIN模式中,这是在字节传输之间插入的暂停,LinInterByteSpace延迟也适用于报头和响应(响应空间)之间的暂停。虽然HW支持0到7作为范围,但在tresos范围中选择0到4之间,因为根据LIN协议的最大公差是允许40%的帧偏差,根据该协议定义,最大值限制为4。默认值一选择“最小字节间空间”作为默认值。
- LinRxAlternateInputSignal:接收信号管脚的选择。
IRQ
完成对应ASCLIN模块优先级等配置。
LIN驱动代码调试
测试代码
测试代码如下。首先完成LIN中断使能等初始化工作,Lin_DemoFunction函数发送了一个LIN_MASTER_RESPONSE的LIN帧,它是报头和应答都由主设备发送的LIN帧,这对我们测试很友好。前文介绍的帧类型在驱动层面没有意义,驱动层面只根据帧的方向分为以下三类:
-
LIN_MASTER_RESPONSE:当前帧发送负责发送应答,也就是既发送报头,也发送应答内容。
-
LIN_SLAVE_RESPONSE:当前帧发送不负责发送应答,也就是只发送报头,接收从的应答。
-
LIN_SLAVE_TO_SLAVE:当前帧负责发送应答,且不发送报头,这个模式目前不用,因为LIN栈目前不支持从模式,这里我就不详述了。
下面是具体的代码。
void Lin_Init()
{
/*ASCLIN Init*/
IrqAsclin_Init();
SRC_ASCLIN_ASCLIN2_TX.B.SRE = 1;
SRC_ASCLIN_ASCLIN2_RX.B.SRE = 1;
SRC_ASCLIN_ASCLIN2_ERR.B.SRE = 1;
Lin_17_AscLin_Init(&Lin_17_AscLin_Config);
}
uint8 Sdu_Data[][8] =
{
{0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,0xAA,0xBB},
{0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00}
};
Lin_PduType Lin_Pdu[] =
{
{0x80, LIN_ENHANCED_CS, LIN_MASTER_RESPONSE, 8, Sdu_Data[0]},
{0xC1, LIN_ENHANCED_CS, LIN_SLAVE_RESPONSE, 8, Sdu_Data[1]},
{0xC2, LIN_ENHANCED_CS, LIN_SLAVE_TO_SLAVE, 8, Sdu_Data[1]}
};
uint8 DataRead[8];
volatile uint8 *SlaveSduPtr = DataRead;
void Lin_DemoFunction(void)
{
Std_ReturnType Ret1;
Std_ReturnType Ret2;
Lin_Init();
Ret1 = Lin_17_AscLin_SendFrame(Lin_17_AscLinConf_LinChannel_LinChannel_0, &Lin_Pdu[0]);
do
{
Ret2 = Lin_17_AscLin_GetStatus(Lin_17_AscLinConf_LinChannel_LinChannel_0,(uint8**)&SlaveSduPtr);
if ((Ret1 != LIN_TX_BUSY) && (Ret1 != LIN_TX_OK))
{
break;
}
}while(Ret2 != LIN_TX_OK );
}
测试结果
下图是测试结果,可以在LIN线上看到对应的报头和数据。
十六宿舍 原创作品,转载必须标注原文链接。
©2023 Yang Li. All rights reserved.
欢迎关注 『十六宿舍』,大家喜欢的话,给个👍,更多关于嵌入式相关技术的内容持续更新中。