本帖最后由 mxkw0514 于 2025-5-9 09:36 编辑
#技术资源# #申请原创#@21小跑堂
前段时间学习了LIN通信,LIN(局域互联网)在车载领域一些实时性要求不高的应用被使用,如车内座椅下方新风系统的风扇控制、照明系统阅读灯的调节、车顶天窗的控制等,如果要做这一块的实际应用,需要借助供应商提供的LIN driver和车厂提供的LIN stack结合使用,了解LIN基础知识可以帮助理解相关应用。一根LIN总线中包含了一个主机节点和最多16个从机节点,总线长度可达几十米。
图1 LIN网络节点
LIN收发器可以简化为下图,电池电压经过一个二极管和电阻对LIN收发器的开楼输出进行上拉,LIN总线上的电压可达几十伏,是适用车载12V和24V供电系统的。LIN收发器将微控制器EUSART外设的RXD和TXD位逻辑转换成LIN总线电平信号,微控制器会向Slave器件发送不同PID的帧,对应PID的Slave设备会做出响应。说到这里,不得不聊一下LIN通信的帧和信号了。
图2 LIN收发器结构
LIN通信的帧是数据传输的基本单元,下图是从LIN通信中捕获的一帧数据,对此做简单介绍。LIN帧由主帧头(Master Header)和从响应(Slave Response)组成,主帧头由同步间隔段(Break Field)、同步段(Sync Field)和受保护标识段(PID Field)组成,从响应由数据段(Data Field)和校验和段(Checksum Field)组成,同步间隔段、同步段和受保护标识段之间1位时间长度的间隔界定符组成,同步字段(0x55)发送给主机用于同步波特率。
图3 LIN协议帧结构
刚好手里有一对ATA6588 Demo板,开始粗略地学习ATA6588的数据手册,发现这个SBC包含了1个CAN、3个LDO和2个LIN,这个是不是有点鸡肋了......,有什么实际应用能同时用到SBC的CAN、LIN和LDO呢?
图4 ATA6588的简化框图
这次打算利用ATA6588的LIN2来做一个LIN的主从通信演示,以此学习一下LIN的基础知识。搭建的LIN的主从通信Demo的框图如下所示,采用PIC18F47Q10的UART作为LIN收发器的控制器,使用MPLAB的MCC工具生成LIN的驱动程序,以LIN从机响应LIN主机发送的数据来验证LIN通信。
图5 LIN主从通信示意图
图6 LIN通信实物图
首先要使用SPI接口对ATA6588的配置,设置ATA6588的LIN工作在Normal模式(LTRXCR寄存器,地址0x21),ATA6588支持低功耗唤醒模式,这里就不作过多介绍了。不过在使用SPI配置ATA6588的时候,需要注意SPI时序(如下图所示),SPI为模式1,地址位应当左移1位,最低位必须为0以指示写操作。
图7 SPI通信时序
然后通过CMCC分别配置两个PIC单片机的LIN,一个单片机的LIN配置成Master,另外一个单片机的LIN配置成Slave,配置界面如下所示(目前只有Classic的MCC对LIN有完善的支持)。LIN控制器的配置是在EUSART和定时器的基础上完成,因为需要EUSART产生驱动LIN收发器的逻辑位,需要定时器产生LIN协议栈的时基(1ms),EUART和定时器的MCC配置较为简单,就不做展示了。用户可以在MCC中修改不同帧的收发类型、超时时间、PID的名称等。利用MCC产生LIN protocol driver后,需要将LIN_slaved.c中的LIN_Handler添加到main函数的主循环中。此外,MCC还会生成一个简单的LIN示例代码(Lin_app.c),这个Stack仅仅用于简单的测试验证,实际应用要结合第三方车厂的LIN stack进行开发。
图8 LIN Master配置
图9 LIN Slave配置
MCC生成的LIN_Handler程序的工作原理是对LIN通信过程的不同状态进行轮询和响应,Master的LIN_handler有4个状态机,Slave的LIN_handler有10个状态机。下图是Mater的LIN_Handler的流程图,Master的LIN_Handle有LIN_IDLE(空闲态)、LIN_TX_IP(发送态)、LIN_RX_IP(接收态)和LIN_RX_RDY(准备接收态)四个状态机,由此实现对LIN总线上的设备进行广播和接收从机的响应。
图10 Master LIN_Handler流程图
最后是在Slave的LIN_app.c中添加简单的测试代码验证程序(如下所示),Slave在收到对应PID(ID为0x00,PID为0x80)的帧后,会传回一个0x55的数据,如果收到0x00的数据,则将LED0灯的状态翻转。#include "lin_app.h"
#include "../pin_manager.h"
void LIN_Slave_Initialize(void){
LIN_init(TABLE_SIZE, scheduleTable, processLIN);
}
void processLIN(void){
uint8_t tempRxData[8];
uint8_t cmd;
cmd = LIN_getPacket(tempRxData);
switch(cmd){
case UNLOCK:
if(UNLOCK_Data[0] == 0x00)
{
LED0_Toggle();
}
break;
case RSSI:
break;
case LFRX:
LFRX_Data[0] = 0x55;
break;
default:
break;
}
}
PID与MCC设定的ID是不同的,比如我在MCC中设定的信号UNLOCK的ID是0x00(这里所说的信号是代指帧名称,而不是数据字段的位和字节),实际发往LIN总线上的帧头的PID是0x80,PID与ID之间存在着一定的转换关系,用户可以通过Microchip查找表获得ID对应下的PID(PID由6位帧标识符和2位奇偶校验位组成),同时MCC生成的驱动程序中也提供了计算帧ID奇偶校验位的程序,从该程序中,我们了解ID与PID之间的数学多项式关系。
图12 搭载信号的帧PID查找表
uint8_t LIN_calcParity(uint8_t CMD){
lin_pid_t PID;
PID.rawPID = CMD;
//Workaround for compiler bug - CAE_MCU8-200:
// PID.P0 = PID.ID0 ^ PID.ID1 ^ PID.ID2 ^ PID.ID4;
// PID.P1 = ~(PID.ID1 ^ PID.ID3 ^ PID.ID4 ^ PID.ID5);
PID.P0 = PID.ID0 ^ PID.ID1;
PID.P0 = PID.P0 ^ PID.ID2;
PID.P0 = PID.P0 ^ PID.ID4;
PID.P1 = PID.ID1 ^ PID.ID3;
PID.P1 = PID.P1 ^ PID.ID4;
PID.P1 = PID.P1 ^ PID.ID5;
PID.P1 = ~PID.P1;
return PID.rawPID;
}
将LIN Master和LIN Slave的程序调试无误后,分别下载到对应的单片机中,然后用示波器捕获LIN Master的RX引脚处的一帧数据如下所示。从下图中我们可以看到,LIN Slave会响应PID为0x42(ID为0x02)的接收帧广播,即发送{0x55,0,0,0,0,0,0,0}的数据作为响应。LIN Slave在收到PID为0x80(ID为0x00)的发送帧后,解析Master Slave发送的数据(如果数据为0x00,则LED灯状态翻转)。到此为止,实现了LIN总线的主从通信驱动的搭建和验证。实际上,单片机在LIN通信中一般是担任从机,主机是性能强的车载中控或者域控制器,本次的演示主要是验证和简单测试LIN主从通信驱动的搭建。
图13 LIN Master的RX引脚接收帧
由于本人水平有限,文中内容难免存在不足,希望发现错误的朋友批评指正。
|
基于ATA6588的LIN总线主从通信驱动搭建,通过原理分析和数据帧解析,最后以实操搞定LIN总线的主从通信案例。