USB电气特性与信号编码:电压、电流与NRZI的底层逻辑

说实话,很多做嵌入式开发的朋友,一开始接触USB,往往先被各种协议层、描述符搞得头大。但我个人习惯是,先搞懂最底层的电气特性和信号编码。为什么?因为你在实际项目中遇到的绝大多数硬件问题——设备不枚举、通信不稳定、线长一点就掉线——根源都在这一层。

这一章,我们就来扒一扒USB的“物理层”。电压多高?电流多大?数据是怎么在两根线上“跑”起来的?

1. USB的电压等级:不只是5V那么简单

USB总线电压,大家最熟悉的是VBUS上的5V。但这里有个细节,我当年第一次做USB HUB项目时就踩过坑——VBUS的电压范围是4.75V到5.25V,不是精确的5V。

参数 USB 2.0 规范值 实际工程建议
VBUS 标称电压 5.0 V 4.75 V – 5.25 V
VBUS 最低允许电压(主机端) 4.75 V 4.4 V(考虑线损)
设备端最低工作电压 4.4 V 4.0 V(部分低功耗芯片)
D+/D- 差分信号摆幅 0 – 3.3 V 实际约 0 – 3.6 V
我曾经踩过的坑: 在设计一个USB摄像头时,用了很长的USB线(约5米),结果设备在部分主机上无法识别。排查后发现,设备端VBUS已经跌到4.2V,超出了规范。后来在设备端加了过压欠压保护芯片,并优化了PCB走线,问题才解决。记住,线损和接触电阻是隐形杀手。

2. 电流限制:主机不是无限电源

USB主机对每个端口都有严格的电流限制。你想想看,如果每个设备都随便取电,主机电源早就烧了。

  • USB 2.0 低功耗设备: 最大 100 mA(枚举前) / 150 mA(配置后)
  • USB 2.0 高功耗设备: 最大 500 mA(需配置描述符声明)
  • USB 3.0 / 3.1: 最大 900 mA / 1.5 A(需协商)
  • USB BC 1.2(充电协议): 最大 1.5 A / 3 A(需专用握手)
我建议: 在设计自供电设备时,不要完全依赖VBUS供电。如果设备功耗超过100mA,一定要在配置描述符中正确声明,否则主机可能拒绝供电。我曾经见过一个产品,因为描述符写错了电流值,导致在部分笔记本上无法正常工作。

3. NRZI编码机制:数据是怎么“跑”起来的?

USB的数据传输,用的是NRZI(Non Return to Zero Inverted)编码。说白了,就是“电平翻转表示0,电平不变表示1”。

为什么会用这种编码?因为USB只有两根数据线(D+和D-),没有独立的时钟线。NRZI编码把时钟信息“嵌入”到数据流中,接收端通过检测电平变化来恢复时钟。

举个例子:

  • 发送数据:0 1 0 0 1 1 0
  • NRZI编码:电平在遇到“0”时翻转,遇到“1”时保持不变
  • 起始电平假设为高,编码后:低 低 高 低 低 低 高

你看,连续的“0”会导致电平频繁翻转,接收端很容易同步。但连续的“1”会导致电平长时间不变,接收端就可能失锁。这就是为什么需要位填充(Bit Stuffing)。

4. 位填充(Bit Stuffing):防止“死锁”的妙招

NRZI编码有个致命弱点:如果数据中出现连续6个以上的“1”,电平就会一直不变,接收端的PLL(锁相环)会失锁,导致数据错误。

解决方案很简单:发送端在连续6个“1”之后,强制插入一个“0”。这个“0”会强制电平翻转一次,让接收端重新同步。

位填充规则:
  • 发送端:每检测到连续6个“1”,就在第6个“1”之后插入一个“0”
  • 接收端:每收到连续6个“1”,就自动丢弃后面的那个“0”
  • 注意:这个“0”是填充位,不是有效数据

举个例子:

原始数据:  111111 0101
填充后:    1111110 0101
                    ^ 这个0是填充的

我在调试一个USB键盘时,发现偶尔会丢包。用逻辑分析仪抓波形,发现就是位填充逻辑在FPGA实现时有个边界条件没处理好。嗯,这种问题最头疼,因为不是每次都复现。

5. 同步头(SYNC)与包尾(EOP):包的“身份证”

USB通信是以“包”为单位的。每个包都有固定的开始和结束标志。

5.1 同步头(SYNC)

SYNC字段用于让接收端与发送端时钟同步。USB 2.0的SYNC是8位的特定序列:00000001(注意,这是经过NRZI编码前的数据)。

  • 前7个“0”产生7次电平翻转,让PLL锁定
  • 最后一个“1”作为同步完成标志
  • 接收端检测到SYNC后,开始接收后续数据

5.2 包尾(EOP)

EOP(End of Packet)标志包的结束。USB 2.0的EOP是单端0(SE0)状态,持续2个位时间。

  • SE0:D+和D-同时拉低(差分“0”状态)
  • 持续2个位时间后,进入空闲状态(J状态)
  • 接收端检测到SE0,就知道包结束了
注意: EOP之后,总线会进入空闲状态。如果EOP被噪声干扰,接收端可能误判包的长度。我在一个工业项目中,就因为EOP检测电路抗干扰能力不足,导致频繁的CRC错误。后来在硬件上加了施密特触发器,软件上增加了EOP超时判断,才稳定下来。

6. 知识结构图:USB物理层核心要素

下面这张图,把本章的核心知识点串起来了。你可以把它当作一个快速参考。

USB电气特性与信号编码知识结构图 USB 物理层核心要素 USB 物理层 电气特性 信号编码 包格式 电压等级 电流限制 NRZI编码 位填充 SYNC EOP 关键:NRZI + 位填充 保证了无时钟线的可靠数据传输 SYNC用于同步,EOP用于包边界识别

7. 实战中的几个关键点

最后,分享几个我在项目中积累的经验,希望能帮你少走弯路。

  • 测量VBUS电压: 不要只测主机端,一定要在设备端USB座子处测。线损和接触电阻会让电压掉很多。
  • 电流检测: 如果设备枚举失败,先检查电流是否超标。很多主机在检测到过流时会自动断开端口。
  • 信号完整性: D+/D-走线要等长,阻抗控制在90Ω±15%。我见过一个项目,因为D+和D-走线长度差了2cm,导致高速模式无法工作。
  • 逻辑分析仪: 调试NRZI和位填充问题时,逻辑分析仪是你的好朋友。抓一段波形,对照协议分析,问题往往一目了然。
我建议: 在PCB布局时,把USB接口的ESD保护器件尽量靠近USB座子放置。同时,在D+/D-上加共模扼流圈,可以有效抑制高频噪声。这些细节,往往决定了产品能否通过EMC测试。