1. 为什么数据域要提速:经典 CAN 的带宽瓶颈
经典 CAN(2.0)单帧最多 8 字节、全程一个波特率,500kbps 下 8 字节数据帧要占约 230µs 总线时间——其中 帧头、CRC、ACK 等开销占了一半以上。想提高吞吐只有两条路:要么降开销,要么提速。CAN FD(ISO 11898-1:2015)两条都走了:数据最多 64 字节(摊薄开销),并且 BRS 位切换出第二个、更高的数据波特率。
经典:8 帧 × 8 字节,每帧约 230µs(500k)→ 64 字节总耗时 ≈ 1.85ms
CAN FD:1 帧 × 64 字节,数据域 2Mbps → 仲裁段 + 数据域总耗时 ≈ 0.5ms,吞吐提升约 3~4 倍
关键点:提速的只是"数据域"(Data Phase),帧的仲裁段(Arbitration Phase)仍然用慢速——这是由 CAN 的仲裁机制决定的。
2. CAN FD 帧结构:仲裁段、数据域与 BRS 切换位
一个 FD 帧(BRS=1)在时间轴上天然分成两段,中间用 BRS 位衔接:
| 场段 | 包含位 | 波特率 | 作用 |
|---|---|---|---|
| 仲裁段(慢) | SOF、ID(11/29)、RTR/SRR、IDE、FDF、res、BRS、ESI、DLC | 仲裁波特率(如 500k) | 多节点竞争、逐位仲裁、全网同步 |
| 数据域(快) | 数据(≤64B)、CRC(17/21) | 数据波特率(如 2M) | 赢家独占传输,只此一个节点在发 |
| 尾部(慢) | CRC 定界符、ACK、EOF、IFS | 仲裁波特率 | 切回慢速做应答与帧结束 |
三个关键位(都在仲裁段尾部):
- FDF:FD Format 指示位,1 = 这是 FD 帧(经典节点不认识,视为错误)
- res:保留位,固定显性
- BRS:Bit Rate Switch,1 = 从下一位开始数据域切换高速,CRC 定界符处切回
CAN FD 不等于"总线跑 2M"。仲裁段永远是慢速:两个节点同时抢线时,如果采样节奏不一致,仲裁就会判错。所谓"双波特率"是同一根总线上按帧内位置切换,不是整条总线提速。
3. 为什么仲裁段不能提速:多主仲裁与位同步
CAN 是多主逐位仲裁:多个节点可以在同一时刻开始发送,边发边"听",ID 位为显性(0)的节点赢,隐性(1)的节点看到自己被压掉就退出。这个过程要求:
- 所有节点对每一个位在同一时刻采样,才能正确比较 ID 位
- 位时间必须远大于2×传播延迟(最远两节点来回),否则远端节点还没收到前一个位,本地已开始采样下一个位
- 各节点晶振容差要靠 SJW 重同步吸收,位时间越短容差预算越紧
Lmax ≈ (tbit − 2·tprop_phy) × v / 2,v ≈ 5ns/m(线缆单程约 0.2c)
500k(2µs/位)→ 数米到几十米;2M(500ns/位)→ 只剩车内级短距离。所以仲裁段必须保持慢速,数据域提速只影响赢家独占的那一段。
数据域之所以能提速:仲裁已经结束,总线上只有一个节点在发,其余节点只需跟得上采样(BRS 位已提前告知),不需要再逐位比较——同步要求大幅放松。
4. 位时间与采样点:SYNC/PROP/PHASE 与采样点公式
一个 CAN 位时间(Tbit)由若干 时间量子 TQ(Time Quantum)组成,四个段各有分工:
| 段 | 典型长度 | 作用 |
|---|---|---|
| SYNC_SEG | 固定 1 TQ | 接收方检测下降沿/上升沿,同步起点 |
| PROP_SEG | 1~8 TQ | 补偿总线传播延迟与收发器延迟 |
| PHASE_SEG1 | 1~8 TQ | 相位缓冲,采样点前;可被 SJW 拉长(再同步) |
| PHASE_SEG2 | 1~8 TQ | 采样点后,留出采样与建立时间;可被 SJW 缩短 |
Tbit = SYNC_SEG + PROP_SEG + PHASE_SEG1 + PHASE_SEG2
采样点 SP = (SYNC_SEG + PROP_SEG + PHASE_SEG1) / Tbit
采样发生在 PHASE_SEG1 与 PHASE_SEG2 交界处——SP 越接近 1,采样越靠近位末尾
采样点直接决定抗干扰与同步裕量的平衡:靠前(如 70%)留给传播延迟的裕量少、抗长线差;靠后(如 87.5%)对晶振误差和噪声的裕量变紧。业界推荐值:
| 波特率 | 推荐采样点 | 典型场景 |
|---|---|---|
| 125k / 250k | 87.5% | 长线、工业现场(最远节点距离大) |
| 500k | 80% | 汽车/伺服总线最常见配置 |
| 1M | 75% | 短线高速,距离短、节点少 |
| FD 数据域 1M~5M | 75% | 数据域短帧内独占传输,裕量要求低 |
采样点 = "位时间里在哪一刻读电平":低速长线往 87.5% 靠,高速短线往 75% 靠;全网所有节点必须用同一个采样点,否则必然错帧。
5. 采样点怎么选:计算实例与双采样点
以 80MHz 外设时钟、500kbps 仲裁段、80% 采样点为例(每 TQ = 25ns):
TQ/位 = 80MHz ÷ 500k = 160 TQ → 分频 BRP=2 后为 80 TQ
SYNC=1 + PROP=15 + PS1=48 + PS2=16 = 80 → (1+15+48)/80 = 80%
SJW 取 4(≤ PS2)
CAN FD 的双波特率意味着两个采样点要分别配:仲裁段 80%、数据域 75%(2Mbps、40 TQ/位:SYNC=1 + PROP=2 + PS1=27 + PS2=10 → (1+2+27)/40 = 75%)。Linux 下用 ip link 一行配好:
注意 sample-point 与 dsample-point 是两个独立参数——只配波特率不配采样点时,内核用驱动默认值,不同内核/驱动默认可能不一致,这是"两台机器都配 500k 却通信不上"的隐蔽原因之一。
6. 交互式演示:位时间采样点调节与 FD 双速率帧
上半部分调节总 TQ 数与采样点,实时看四段分配和采样时刻;下半部分选仲裁/数据波特率,看一个 64 字节 FD 帧在时间轴上仲裁段慢、数据域快的实际比例,以及 BRS 切换点与两段各自的采样点位置。
观察要点:采样点滑块改变的是 PHASE_SEG1/PHASE_SEG2 的分界;波特率选择改变的是时间轴上仲裁段与数据域的宽度比例——数据域提速越狠,64 字节有效载荷在整帧时间里占比越小,吞吐越高。
7. 配置与位时序计算(C语言)
下面是通用的位时序计算函数:给定目标波特率、采样点与外设时钟,自动搜索分频与段分配,输出可直接映射到 STM32 FDCAN / bxCAN 的 TSEG 寄存器值。
FD 数据域同理调用一次(不同 TQ 与采样点),把结果填进 FDCAN 的 NBTP(仲裁段)与 DBTP(数据域)即可。
8. 工程要点与常见误区
要点 1:采样点是"全网统一"的
同一网段所有节点必须用同一个采样点(仲裁段)与同一种波特率,否则边沿同步后采样时刻不同,长帧必出错。新节点上线前先核对 ip -details link show 的采样点。
要点 2:总线越长,采样点越靠后
传播延迟占位时间比例变大时,把采样点推到 85%~87.5% 能留出更长的采样前窗口;短距离高速网可以放到 75%。采样点不是固定值,要按拓扑实测调。
要点 3:SJW 吸收晶振偏差,别设 0
SYNC 之后各节点晶振有偏差,靠位填充边沿触发重同步,SJW 决定单次能拉长/缩短多少。常见取 SJW = 4 TQ(≤ PS2),晶振容差差或节点多的场合要留足。
要点 4:FD 网段与经典节点要隔离
经典 2.0 节点看到 FDF=1 的帧直接判错。混跑方案:FD 节点只在需要时发经典帧,或把 FD 网段独立;不要指望 2.0 节点"容忍" FD 帧。
误区 1:以为数据域提速 = 总线提速
仲裁段仍是慢速,竞争、广播、ACK 都在慢速段完成。提速收益集中在"长数据帧",短帧(≤8 字节)用 FD 反而可能因帧头开销更慢——选型时按帧长权衡。
误区 2:采样点越靠后越好
87.5% 适合长线,但太靠近位末尾时,PS2 只剩很少 TQ,采样建立时间不足、对边沿噪声更敏感。采样点要按"传播延迟 vs 晶振/噪声"两边算,不是一味后移。
误区 3:双波特率只配波特率不配采样点
bitrate + dbitrate 只定了速率,采样点用驱动默认;不同内核版本默认可能不同,跨主机联调时"波特率明明一样却乱帧"十有八九是这个。
9. 小结
- CAN FD = 仲裁段慢速 + 数据域快速,BRS 位做切换,CRC 定界符切回
- 仲裁段不能提速:多主逐位仲裁要求全网同节奏采样,且位时间受传播延迟约束
- 位时间 = SYNC(1) + PROP + PS1 + PS2,采样点 SP = (1+PROP+PS1)/Tbit
- 采样点经验值:125k~250k 用 87.5%,500k 用 80%,1M 与 FD 数据域用 75%
- 双波特率要双采样点分别配置:
sample-point与dsample-point - 位时序用"TQ 总数 + 采样点"反解段分配,STMFDCAN 映射 NBTP/DBTP
至此 CAN 板块已经形成完整链路:CAN 帧结构(04)→ 双波特率与采样点(本篇)→ CANopen 对象字典与通信对象(01)→ CiA 402 伺服行规(02)→ 从站实现与负载率(03)。