USB 已经发布了五篇文章,如下:
本文主要讲解 USB 电气信号,懂硬件,才能更好的写出软件,否则是空中楼阁。
参考文章如下,本文主要参考百问网-韦东山驱动大全教程:
https://www.jianshu.com/p/3afc1eb5bd32
https://www.jianshu.com/p/cf8e7df5ff09
https://www.jianshu.com/p/2a6e22194cd3
https://zhuanlan.zhihu.com/p/460018993
https://www.usbzh.com/article/detail-459.html
USB 2.0 协议支持 3 种速率:
低速(Low Speed,1.5Mbps)
全速(Full Speed, 12Mbps)
高速(High Speed, 480Mbps)
USB Hub、USB 设备,也分为低速、全速、高速三种类型。一个 USB 设备,可能兼容【低速、全速】,可能兼容【全速、高速】,但是不会同时兼容低速、高速。
下图是兼容高速模式的 USB 收发器电路图:
USB 连接涉及 Hub Port 和 USB 设备,硬件连接如下【注意上下拉电阻位置】:
USB 有 4 条线:5V、D+、D-、GND。
数据线 D+、D-,只能表示 4 种状态。USB 协议中,很巧妙地使用这两条线路实现了空闲(Idle)、开始(SOP)、传输数据(Data)、结束(EOP)等功能。
连接
Hub 端口的 D+、D- 都有 15K 的下拉电阻,平时为低电平。全速设备内部的D+ 有 1.5K 的上拉电阻,低速设备内部的 D- 有 1.5K 的上拉电阻,连接到 Hub 后会导致 Hub 的 D+ 或 D- 电平变化,Hub 根据变化的引脚分辨接进来的是全速设备还是低速设备。
高速设备一开始也是作为全速设备被识别的。
全速设备、高速设备连接时,D+ 引脚的电平由低变高:
低速设备连接时,D- 引脚的电平由低变高:
断开
对于低速、全速设备,接到 Hub 时导致 D- 或 D+ 引脚变为高电平,断开设备后,D- 或 D+ 引脚变为低电平:
对于高速设备,它先作为全速设备被识别出来,然后再被识别为高速设备。工作于高速模式时,D+ 的上拉电阻是断开的,所以对于工作于高速模式的 USB 设备,无法通过 D+ 的引脚电平变化监测到它已经断开。
工作于高速模式的设备,D+、D- 两边有 45 欧姆的下拉电阻,用来消除反射信号:
当断开高速设备后,Hub 发出信号,得到的反射信号无法衰减,Hub 监测到这些信号后就知道高速设备已经断开,内部电路图如下:
从状态切换图上看,一个 USB 设备连接后,它将会被供电,然后被复位。当软件出错时,我们也可以发出复位信号重新驱动设备。
那么,USB Hub 端口或 USB 控制器端口如何发出复位信号?发出 SE0 信号,并维持至少 10ms。
USB 设备看到 Reset 信号后,需要准备接收"SetAddress()"请求;如果它不能回应这个请求,就是"不能识别的设备"。
Hub 端口的 D+、D- 都有 15K 的下拉电阻,平时为低电平。全速设备内部的D+ 有 1.5K 的上拉电阻,低速设备内部的 D- 有 1.5K 的上拉电阻,连接到 Hub 后会导致 Hub 的 D+ 或 D- 电平变化,Hub 根据变化的引脚分辨接进来的是全速设备还是低速设备。
高速设备必定兼容全速模式,所以高速设备内部 D+ 也有 1.5K 的上拉电阻,只不过这个电阻是可以断开的:工作于高速模式时要断开它。
高速设备首先作为全速设备被识别出来,然后 Hub 如何确定它是否支持高速模式?
Hub 端口如何监测一个新插入的 USB 设备能否工作于高速模式?流程如下:
"a high-speed detection handshake"信号,就是"高速设备监测握手信号",既然是握手信号,自然是有来有回:
SOP:Start Of Packet,Hub 驱动 D+、D- 这两条线路从 Idle 状态变为 K 状态。SOP 中的 K 状态就是 SYNC 信号的第 1 位数据,SYNC 格式为 3 对 KJ 外加 2 个 K。
EOP:End Of Packet,由数据的发送方发出 EOP,数据发送方驱动 D+、D- 这两条线路,先设为 SE0 状态并维持 2 位时间,再设置为 J 状态并维持 1 位时间,最后 D+、D- 变为高阻状态,这时由线路的上下拉电阻使得总线进入 Idle 状态。
高速的 EOP 比较复杂,作为软件开发人员无需掌握。
高速模式中,Idle 状态为:D+、D- 接地。SOP 格式为:从 Idle 状态切换为 K 状态。SOP 中的 K 状态就是 SYNC 信号的第 1 位数据。
高速模式中的 SYNC 格式为:KJKJKJKJ KJKJKJKJ KJKJKJKJ KJKJKJKK,即 15 对KJ,外加 2 个 K。
NRZI:Non Return Zero Inverted Code,反向不归零编码。NRZI的编码方位为:对于数据 0,波形翻转;对于数据 1,波形不变。
使用 NRZI,发送端可以很巧妙地把"时钟频率"告诉接收端:只要传输连续的数据 0 即可。在下图中,低速/全速协议中"Sync Pattern"的原始数据是"00000001",接收端从前面的 7 个 0 波形就可以算出"时钟频率"。
使用 NRZI 时,如果传输的数据总是"1",会导致波形维持不变。如果电平长时间维持不变,比如传输 100 位 1 时,如果接收方稍有偏差,就可能认为接收到了 99 位 1、101 位 1。而 USB 中采用了 Bit-Stuffing 位填充处理,即在连续发送 6 个 1 后面会插入 1 个 0,强制翻转发送信号,从而让接收方调整频率,同步接收。而接收方在接收时只要接收到连续的 6 个 1 后,直接将后面的 0 删除即可恢复数据的原貌。
NRZI 不理解的话,请直接看如下文章:
https://zhuanlan.zhihu.com/p/460018993
本文分享自 嵌入式Linux系统开发 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!