当前位置:首页 > 汽车电子 > 汽车电子
[导读]LIN是单主从、无仲裁总线,本身没有CAN的自动重传和错误帧;所谓“无差错”不是协议兜底,而是靠调度表确定性+校验和+超时丢弃+状态回读四件事做应用层容错。 车门模块最典型:BCM作主节点,四门模块作从节点,命令帧下发、状态帧周期上报。


LIN是单主从、无仲裁总线,本身没有CAN的自动重传和错误帧;所谓“无差错”不是协议兜底,而是靠调度表确定性+校验和+超时丢弃+状态回读四件事做应用层容错。 车门模块最典型:BCM作主节点,四门模块作从节点,命令帧下发、状态帧周期上报。

一、帧划分与信号映射

LIN帧=Break+Sync(0x55)+PID+数据+校验和。 车门场景建议:

0x10 命令帧(主→从):锁/解锁、窗升/降/停、防夹使能

0x11~0x14 状态帧(从→主):锁状态、门状态、窗位置、故障位

0x3C/0x3D 诊断帧:NAD配置、读故障码

数据域按位拼:Data[0]低2位窗命令,bit2防夹使能;状态帧Data[0].bit0=锁状态、bit1=门开、bit2=电机过流、bit3=防夹触发。信号映射写进LDF,C代码只按偏移取位。

二、主节点调度表

主节点用定时器驱动调度表,发完Break+Sync+PID后等从机响应,不在中断里干重活:

typedef struct { uint8_t pid; uint8_t dir; uint8_t len; uint16_t slot_ms; } lin_slot_t;

static const lin_slot_t sch[] = {

   {0x10,TX,2,10}, {0x11,RX,2,8}, {0x12,RX,2,8},

   {0x13,RX,2,8}, {0x14,RX,2,8},

};

void lin_scheduler_tick(void){

   static int idx=0; static uint16_t tick=0;

   if(++tick < sch[idx].slot_ms) return;

   tick=0;

   lin_send_header(sch[idx].pid);

   if(sch[idx].dir==TX) lin_send_response(tx_buf,sch[idx].len);

   idx = (idx+1)%ARRAY_SIZE(sch);

}

slot时间按帧长算,19.2k下2字节帧约几ms,别把slot压到刚够,留响应余量。

三、从节点接收状态机

从机用UART+Break中断,收到帧头后按PID判断是否响应:

typedef enum{ S_IDLE,S_ID,S_DATA,S_CS } lin_st_t;

lin_st_t st=S_IDLE; uint8_t rx[8],n,exp;

void lin_isr(uint8_t b, int is_break){

   static uint8_t pid;

   if(is_break){ st=S_ID; return; }

   switch(st){

   case S_ID:

       pid=b&0x3F; st=S_DATA; n=0;

       exp = (pid==MY_STATUS_ID)?2:0; break;

   case S_DATA:

       if(pid==MY_CMD_ID) cmd_buf[n]=b;

       else if(pid==MY_STATUS_ID) rx[n]=b;

       if(++n>=exp) st=S_CS; break;

   case S_CS:

       if(lin_checksum_ok(pid,rx,n,b)){

           if(pid==MY_CMD_ID) pending_cmd=1;   // 主循环执行,别在ISR动电机

       }

       st=S_IDLE; break;

   default: st=S_IDLE;

   }

}

ISR只拷贝、置标志;车窗升降、锁电机动作放主循环,避免中断里占时间长导致下一帧丢Break。

四、增强校验和+错误丢弃

LIN 2.x用增强校验和,把PID也算进去,能防“数据对但ID错”:

uint8_t lin_checksum(uint8_t pid,uint8_t*d,uint8_t n){

   uint16_t s=pid;

   for(uint8_t i=0;i<n;i++){ s+=d[i]; if(s>255)s-=255; }

   return (uint8_t)(0xFF - (s&0xFF));

}

int lin_checksum_ok(uint8_t pid,uint8_t*d,uint8_t n,uint8_t cs){

   return lin_checksum(pid,d,n)==cs;

}

校验错处理原则:

当前帧直接丢弃,不更新应用变量

命令帧出错→不执行电机动作,保持上次安全状态

状态帧出错→主节点沿用上次有效值,错误计数++

连续N次无响应/校验错→标记从节点通信故障,上报BCM

五、无差错交互的三道兜底

1. 命令-确认闭环

主节点发0x10命令后,不在本周期立即认为执行成功;下一周期读0x11状态帧,bit匹配才算生效。车窗防夹、门锁动作都走“发令→状态回读→不一致重试”。

2. 超时机制

主节点WAIT_RESPONSE起定时器,时槽到还没收到响应即判超时:

if(timer_elapsed() > RESP_TIMEOUT_MS){

   slave_err_cnt[pid]++;

   if(slave_err_cnt[pid]>3) set_fault(pid);

}

3. 安全降级

校验错/超时/电机过流时,从节点不盲动:

车窗:停止电机,保持当前位置

门锁:不反转锁舌,等下次合法命令

故障位置1,主节点可发诊断帧读详细码

六、工程落坑

从节点用内部RC也行,但必须靠Sync字节重同步波特率,主节点时钟要稳

Break检测别靠普通UART帧收,开LIN模式或FE标志,否则0x00会被当普通数据

PID奇偶位接收端校验一次,错ID直接忽略

命令帧别每周期发“升”,用边沿触发:按键变化才发,平时发无操作命令

事件触发帧做门把手按键可省带宽,但冲突时要回退轮询无条件帧

休眠/唤醒走LIN sleep命令+唤醒脉冲,从节点别自己随便抢发

按“调度表定周期→主发头从响应→增强校验和→校验错丢弃→命令回读确认→超时计数”落地,车门LIN通信能做到工程意义上的无差错:单帧干扰不误动、从机掉线可发现、锁窗动作有状态闭环。LIN不追求CAN级硬实时,但舒适域车门控制完全够用。



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭