3、FlexRay协议基础:帧结构、符号、编码方式(NRZ)

好,咱们今天聊聊FlexRay协议最核心的几个东西——帧结构、符号和编码方式。说实话,搞车载网络这么多年,我见过不少工程师一上来就啃协议栈,结果被帧头里的保留位和填充位搞得一头雾水。我个人习惯是,先搞明白数据在线上到底长什么样,再去琢磨上层怎么调度。

3.1 FlexRay帧结构:一个数据包的解剖

FlexRay的帧,说白了就是一段有固定格式的二进制串。它不像CAN那样只有11位或29位ID,FlexRay的帧结构要复杂得多。你想想看,一个帧要承载静态段和动态段两种数据,还要支持多种校验和同步机制,结构自然就大了。

一个完整的FlexRay帧由三部分组成:帧头(Header)、有效载荷(Payload)和帧尾(Trailer)。我习惯把帧头比作快递单,有效载荷是包裹里的东西,帧尾就是收件人的签名确认。

3.1.1 帧头(Header)—— 5个字节的“身份证”

帧头固定为5个字节(40位)。嗯,这里要注意,FlexRay的字节序是Motorola格式(大端),跟CAN的Intel格式不一样。我在项目中遇到过团队把字节序搞反,结果解析出来的帧ID全是错的,排查了一整天。

位域 长度(位) 说明
保留位 1 必须为0,接收方忽略
载荷长度 7 有效载荷的字数(2字节为单位),范围0-127
帧ID 11 唯一标识,范围1-2047
周期计数 6 当前通信周期编号,0-63循环
数据位 1 1表示有效载荷包含数据,0表示空
同步帧位 1 1表示该帧用于时钟同步
启动帧位 1 1表示该帧用于冷启动
保留位 1 必须为0
头部CRC 11 覆盖帧头前29位的校验
周期计数重复 6 与周期计数位相同,用于冗余校验

关键点:帧ID不是地址,而是时隙编号。静态段中,帧ID与时隙号一一对应。动态段中,帧ID决定优先级(越小越高)。

3.1.2 有效载荷(Payload)—— 最多254字节的数据区

有效载荷的长度由帧头中的“载荷长度”字段决定。注意,这个字段的单位是“字”(word),1个字=2字节。所以最大载荷是127字×2字节=254字节。

我曾经在一个ADAS项目中,需要传输摄像头预处理后的目标列表,每个目标占8字节,最多32个目标。算下来刚好256字节,但FlexRay最大只有254字节。最后只能压缩成30个目标,留2字节做校验和。所以设计阶段一定要算好带宽和载荷的匹配。

3.1.3 帧尾(Trailer)—— 3字节的CRC校验

帧尾只有一个字段:帧CRC,长度为24位(3字节)。它覆盖整个帧(帧头+有效载荷),生成多项式是标准化的。FlexRay的CRC算法比CAN的15位CRC强很多,能检测出3位以内的随机错误和所有奇数位错误。

我的小技巧:在测试阶段,可以用示波器抓取FlexRay总线上的波形,然后手动计算CRC来验证硬件实现是否正确。虽然现在工具链很成熟,但亲手算一次能加深理解。

3.2 FlexRay符号:不只是数据,还有“暗号”

FlexRay除了传输数据帧,还会在总线上发送一些特殊的符号。这些符号不是普通的数据,而是用于网络管理和状态指示的“暗号”。

3.2.1 媒体接入测试符号(MTS)

MTS用于冷启动过程中的冲突检测。当一个节点想成为冷启动节点时,它会先发送MTS来探测总线上是否有其他节点也在尝试启动。如果检测到冲突,就退避等待。

3.2.2 唤醒符号(WUS)

WUS用于将节点从睡眠模式唤醒。它是一段特定长度的低电平脉冲。我记得在某个项目中,因为总线终端电阻匹配不当,导致WUS的脉冲宽度被拉长,部分节点无法被正常唤醒。排查了三天,最后发现是PCB走线寄生电容太大。

3.2.3 冲突避免符号(CAS)

CAS用于动态段的冲突解决。当两个节点在同一个动态时隙发送数据时,优先级低的节点会检测到CAS并主动退让。这有点像CAN的仲裁机制,但实现方式完全不同。

3.3 编码方式:NRZ(不归零编码)

FlexRay物理层采用NRZ(Non-Return-to-Zero)编码。说白了,就是高电平代表1,低电平代表0,电平在比特边界保持不变。你想想看,NRZ的优点是带宽利用率高——每个比特只需要一个电平状态,不像曼彻斯特编码那样需要跳变。

但NRZ有个致命缺点:没有内置的时钟同步机制。如果连续传输多个相同的比特(比如00000000),接收方就无法判断每个比特的边界在哪里。为什么会这样?因为电平一直不变,接收方的采样时钟会逐渐漂移。

3.3.1 字节起始序列(BSS)—— 解决同步问题

为了解决NRZ的同步问题,FlexRay在每个字节前插入一个字节起始序列(BSS)。BSS由两个位组成:一个高电平的“起始位”和一个低电平的“结束位”。接收方通过检测BSS的跳变来重新同步时钟。

嗯,这里要注意:BSS是插入在数据流中的,不是帧结构的一部分。所以实际传输的比特数会比原始数据多。我算过一笔账:一个254字节的有效载荷,加上帧头和帧尾,再算上BSS的开销,实际传输效率大概在80%左右。

3.3.2 帧起始序列(FSS)—— 帧的“前导码”

在每个帧的最前面,还有一个帧起始序列(FSS)。FSS是一个高电平位,用于通知接收方“准备接收新帧”。接收方在检测到FSS后,会启动帧接收逻辑。

3.3.3 动作点偏移(APO)—— 微调采样点

FlexRay还引入了一个叫动作点偏移(APO)的概念。它允许每个节点在BSS之后微调采样点的位置,以补偿不同节点的时钟偏差。APO的单位是“微时隙”(Microtick),通常为12.5ns或25ns。

避坑指南:我曾经在一个项目中,因为APO配置不当,导致两个ECU之间的采样点偏差超过了容忍范围。结果就是,明明物理层信号是好的,但接收方就是解不出正确的数据。后来我把APO从默认的2个微时隙调整到4个微时隙,问题就解决了。所以,APO不是越大越好,也不是越小越好,要根据总线长度和节点时钟精度来算。

3.4 编码效率与带宽计算

咱们来算一笔账,看看FlexRay的实际带宽到底有多少。假设总线速率为10Mbps,一个典型的数据帧包含:

  • 帧头:5字节(40位)
  • 有效载荷:16字节(128位)
  • 帧尾:3字节(24位)
  • BSS开销:每个字节2位,共(5+16+3)×2 = 48位
  • FSS:1位
  • 帧间间隔(IT):11位(静态段)或动态计算

总比特数 = 40 + 128 + 24 + 48 + 1 + 11 = 252位

传输时间 = 252 / 10Mbps = 25.2μs

有效数据率 = 128位 / 25.2μs ≈ 5.08Mbps

你看,实际有效带宽只有标称速率的一半左右。这就是NRZ编码加上各种同步开销的代价。但FlexRay的设计目标不是追求极致带宽,而是确定性可靠性

3.5 小结

这一章咱们把FlexRay的帧结构、符号和编码方式捋了一遍。我个人觉得,理解NRZ编码和BSS的配合机制,是掌握FlexRay物理层的关键。很多工程师只关注上层协议,忽略了物理层的细节,结果在实车测试时被各种信号完整性问题搞得焦头烂额。

下一章,咱们会深入FlexRay的通信周期和时序同步,那才是真正体现FlexRay“确定性”精髓的地方。


公众号:蓝海资料掘金营,微信deep3321