2. LIN协议规范:版本、帧结构与报文类型
好,咱们进入正题。
LIN协议,说白了就是汽车里那些“不太重要”的节点之间的通信方式。比如车窗、座椅、后视镜这些。它们不需要CAN那么高的速率,成本也敏感。我最早接触LIN是在做车门控制器的时候,那时候还踩过不少坑。
2.1 LIN协议版本
LIN协议从1.0开始,到现在主流是2.1和2.2。2.0之后基本稳定了。
我个人习惯,新项目直接上2.1或2.2。为什么?因为2.0之前的版本,诊断功能太弱。你想想看,车厂现在都要求支持诊断,你总不能为了省那点资源,把自己逼到墙角。
几个版本的关键区别,我列个表:
| 版本 | 主要变化 | 我的建议 |
|---|---|---|
| LIN 1.0 / 1.1 | 最早版本,基本功能 | 别用了,兼容性差 |
| LIN 1.2 | 引入配置命令 | 老项目可能见到 |
| LIN 2.0 | 帧结构大改,增加诊断 | 勉强能用 |
| LIN 2.1 | 完善诊断,增加偶发帧 | 推荐 |
| LIN 2.2 | 小修小补,兼容2.1 | 当前主流 |
嗯,这里要注意:版本向下兼容,但主节点和从节点的版本最好一致。我曾经遇到过主节点用2.1,从节点用1.3,结果配置命令死活不认。折腾了两天才发现是版本不匹配。
2.2 LIN帧结构
LIN的帧结构,其实不复杂。它不像CAN那样有那么多仲裁场、控制场。LIN帧就两部分:报头和响应。
报头由主节点发出,响应可以由主节点或从节点发出。这个设计很有意思——主节点掌握着总线的“话语权”。
具体来看:
- 同步间隔场:至少13个显性位。这是用来让从节点“醒过来”的。我调试时经常用示波器看这个间隔,如果小于13位,从节点根本不理你。
- 同步场:0x55。说白了就是让从节点校准自己的时钟。LIN是低成本方案,从节点常用内部RC振荡器,精度差。靠这个同步场,大家才能对上节奏。
- 标识符场:6位ID + 2位奇偶校验。这里有个坑——ID范围是0x00到0x3F,但0x3C和0x3D被保留给诊断帧。你设计节点时,别把这两个ID分配给普通报文。
- 数据场:1到8字节。注意,LIN的数据场长度是可变的,不像CAN固定8字节。这个灵活性很好,但也会带来问题。我后面会讲。
- 校验和场:经典校验和或增强型校验和。2.0以后推荐用增强型,把标识符也参与校验。安全一些。
来个代码示例,看看从节点怎么解析标识符:
// 解析LIN标识符
uint8_t lin_parse_id(uint8_t id_byte) {
uint8_t id = id_byte & 0x3F; // 取低6位
// 校验奇偶位(简化版)
uint8_t p0 = ((id & 0x01) ^ ((id & 0x02) >> 1) ^ ((id & 0x04) >> 2) ^ ((id & 0x10) >> 4)) & 0x01;
uint8_t p1 = ~(((id & 0x02) >> 1) ^ ((id & 0x08) >> 3) ^ ((id & 0x10) >> 4) ^ ((id & 0x20) >> 5)) & 0x01;
// 如果校验失败,返回0xFF
if (p0 != ((id_byte >> 6) & 0x01) || p1 != ((id_byte >> 7) & 0x01)) {
return 0xFF;
}
return id;
}
2.3 报文类型
LIN的报文类型,一共四种。我一个个说。
2.3.1 无条件帧
这是最常用的。主节点发出报头,指定ID,然后对应的从节点必须响应。说白了就是“点对点”的强制通信。
比如,主节点发ID=0x01的报头,从节点A收到后,必须把自己的数据发出来。没有商量的余地。
我在做车窗控制器时,大部分控制信号都用无条件帧。简单、可靠、实时性好。
2.3.2 事件触发帧
这个就有意思了。它用来处理“偶尔发生”的事件。比如,某个开关被按下。
主节点发一个事件触发帧的报头,多个从节点都可以响应。但为了避免冲突,每个从节点在响应前会先判断自己的数据有没有变化。如果没变化,就不响应。
你可能会问:如果两个从节点同时响应怎么办?
嗯,这就是设计上的妥协。LIN协议允许冲突,冲突后主节点会改用无条件帧轮询。说白了,事件触发帧是“优化手段”,不是“可靠手段”。
2.3.3 偶发帧
偶发帧,名字听着玄乎,其实很简单。它是主节点发出的,但数据内容可以来自多个从节点。主节点在发送前,会检查哪个从节点有数据更新,然后只发送那个节点的数据。
说白了,偶发帧是“主节点主动问,但只问有变化的”。
这个在2.1版本才引入。我一般用它来传输一些状态信息,比如温度、电压等。这些数据变化慢,没必要每个周期都发。
2.3.4 诊断帧
诊断帧,ID固定为0x3C和0x3D。0x3C是主节点发请求,0x3D是从节点发响应。
诊断帧的格式遵循ISO 15765-2(也就是UDS over LIN)。数据场第一个字节是诊断服务ID,后面跟着参数。
比如,读取从节点的软件版本:
// 主节点发送诊断请求:读取数据标识符 0xF1(软件版本)
// 数据场: 0x22 0xF1 0x00 0x00 0x00 0x00 0x00 0x00
// 0x22 = 读取数据标识符服务
// 0xF1 0x00 = 数据标识符
// 从节点响应:
// 数据场: 0x62 0xF1 0x00 0x01 0x02 0x03 0x00 0x00
// 0x62 = 读取数据标识符响应
// 0xF1 0x00 = 数据标识符
// 0x01 0x02 0x03 = 版本号 V1.2.3
诊断帧是强制实现的。车厂验收时,一定会用诊断工具读你的节点信息。所以,哪怕你的节点功能再简单,诊断部分也得做全。
好了,这一章就到这里。LIN协议规范,说白了就是这些内容。版本选2.1以上,帧结构记清楚,报文类型用对地方。下一章,我会讲从节点的硬件设计,包括收发器选型和电源管理。到时候见。