大家好,又见面了,我是你们的朋友全栈君。
目录
USB是什么
USB,通用串行总线,是一种计算机与外围设备进行数据交互的通信协议。
任何东西的出现都是有理可循的,在以前计算机刚兴起的时候,要连接一个新的设备,需要断电关闭计算机,连接好设备,配置好硬件,再上电运行,这个过程相当费时费力,为了能拥有随意接入设备这种热拔插特性,USB总线协议应运而生。
USB总线如今已经有USB1.0、USB1.1、USB2.0、USB3.0。
USB协议采用主从工作模式,即只有主机与从机之间才能进行数据通信,也正是这样引发一个缺陷,就是主机与主机、从机与从机之间不能通信。
后来,USB OTG的出现弥补了这一缺陷,USB OTG的特性,就是能将一个设备,在不同的场合进行主机或从机的身份切换,如何做到这一点的,就是USB OTG中增加了一种MINI USB接头,是五线制,跟四线制一样,多出来的一条是ID线,用来标识一个设备是主机还是从机。
尽管如此,还是避免不了USB主从的工作模式,数据永远在主机和从机之间进行,永远是主机发起主动权,从机只是被动的读写。
USB传输如今已经是一种普遍的手段,在USB1.0和USB1.1中,传输速度上有1.5Mb/s的低速模式和12Mb/s的全速模式,之后出了USB2.0,传输速度上就有了480Mb/s的高速模式、在USB3.0上,速度就更快了。
这些低速、全速、高速指的是数据在每秒传输的位数,实际速率要低一点,因为还有同步域、令牌包、CRC校验、位填充、包间隙这些协议开销。
而在传输距离上,建议低速不超过三米,全速不超过5米。
需要走出的一个误区就是:并不是设备拥有越高版本的协议,速度就一定快;就比如说PSIUSBD12这款USB芯片,虽然手册上写了符合USB2.0协议,实际上并没有高速模式,只有12Mb/s的全速模式。
USB协议的传输结构
以下是USB协议的LOGO:
标准的USB协议传输结构是这样子的(设备端):
USB协议采用的是差分传输模式,因而有两条数据线D+和D-,在低速和全速模式下,采用电压传输模式,在高速下,采用电流传输模式。
传输结构之所以采用两长两短的方式,是为了支持热拔插;
当USB设备接入主机时,VCC和GND优先被接通;拔掉设备时,D-和D+数据线优先断电。
原因很简单,如果D-和D+先于电源线被接通,那么此时电源为0,USB芯片的IO口引脚电压很有可能大于电源电压,很容易导致芯片闩锁,轻则无法工作,重则损坏芯片,这时候需要断电重新上电。
在还没有进行配置前,数据线最大电流为100mA,配置后,数据线最大电流为500mA,数据的传输为小端序方式,在国际标准上,甚至对USB协议的四线做了颜色标注,VCC为红色,GND为黑色,D-为白色,D+为绿色。
USB的电气特性
在电气结构上,USB设备与主机的连接也很有讲究:
主机端的D-和D+数据线各自被串联15KR电阻下拉到地,当没有USB设备插入的时候,这两条数据线就一直呈现低电平状态。
设备端的D-或者D+数据线,串联一个1.5KR的电阻上拉到3.3V,一旦设备插入主机,那么当主机捕捉到自身的D-或者D+被拉到高电平时,就知道有USB设备连接进来了,这样就检测到有外来USB设备接入了。
对于从机设备中到底是D-还是D+串联1.5KR电阻,这个就要有传输协议的模式来决定了,当配置成全速或高速时,就由D+串联电阻;当配置成低速时,就是D-串联电阻了。
简单来说就是快的就连D+,慢的就连D-。
拓扑结构
刚才说了,USB是一种主从工作模式,大多数时候主机被叫“Host”,从机被叫“Device”;
主机端具有一个或者多个USB主控制器,每个USB主控制器下带有一条或者多条根集线器,主控制器负责数据处理,根集线器负责提供一条主控制器与设备连通的接口;
当然有这么一种情况,当设备越来越多,接口不够用的时候,就需要一个特殊的USB设备登场了,那就是USB集线器,他可以在原有的USB接口上扩展出更多的接口,当然了,扩展得再多,说白了也是共享一个主控制器,因此带宽是不会变多的。
在PC端的设备管理器中就可以看到主机的USB主控制器和根集线器:
虽然说一个USB主控制器可以连接多个设备,这种连接并不是串联,也不是并联,而是通过集线器来实现的。
如图,主控制器和根集线器后有集线器,集线器将一个或者多个USB接口扩展成更多接口,将更多接口拓展成再多,但是这种拓展并不是无休止进行下去的,USB1.1最多扩展4层,USB2.0最多扩展6层。
因此大概的传输过程是这样的:
首先由主控制器发出数据,通过各层的集线器传送到相对应的某一层的接口给USB设备,设备接收到数据后进行分析处理,然后发送回一组数据或应答,它最先被送至本层的集线器,然后被送到上一层集线器,一直到主控制器为止,最终,主控制器将数据或者应答交给计算机进行处理。
编码方式
无论USB协议再怎么高深,发送端实际上数据传输的本质就是0和1。
USB采用的是NRZI编码方式,数据为0的时候电平翻转,数据为1的时候电平不反转。
当出现连续6位为1的时候,自动填充进一个0,这样做的目的是防止长时间的电平不变化,不利于时钟的提取。而在接收端则完全相反,自动去掉填充的0,还原出原本的数据。
这就是位填充处理了。
当然,这种编码的处理过程,USB芯片都已经自动处理好了,我们只要知道有这些细节便可。
描述符
USB协议只是一条总线,提供了一条通路而已,那么传了那么多0和1的数据,到底传输的是什么数据呢,原来是要告诉主机,这个设备的具体功能、会有什么行为,该设备的出厂商,设备ID号,厂商ID号,版本号,端点情况等等信息。
这些信息,都是由主机从设备那里获取的描述符得知的,因此,USB总线上传输的0和1数据,实际上就组成了描述符数据,发送给了主机。
描述符种类多样:设备描述符、配置描述符、接口描述符、端点描述符、类特殊描述符、字符串描述符·····
一个设备只有一个设备描述符,该设备描述符定义了多种配置;
每一种配置对应一个配置描述符,该配置描述符定义了多种接口;
每一个接口对应一个接口描述符,该接口描述符定义了多个端口;
每个端点对应一个端点描述符,端点描述符定义了该端点的大小、类型等等。
因此可看出来,在主机获取描述符的过程是有顺序的,从设备描述符,到配置描述符,再到接口描述符,最后到端点描述符,如果由类特殊描述符,那就跟在端点描述符之后。
可见,描述符的获取是一层一层来的,不过在获取配置描述符的时候,可以根据配置描述符得到配置集合的总长度,从该集合我们一口气得到配置描述符、接口描述符、端点描述符和类特殊描述符。
这样也就引发了一个疑问,既然可以一口气从配置集合中获取到端点描述符了,那我为什么还要去费劲获取配置描述符和接口描述符呢,理论上讲是可以的。
我们来捋一下各种描述符之间的关系,假如有一个U盘(U盘当然是用USB通信协议啦),它有一个设备描述符,因此也有一个设备地址(USB设备采用7位来表示地址,即0~127,其中0号地址是保留给未初始化的设备用的,因此理论上可以连接127个设备,但实际上并不会接那么多),主机是通过该设备地址找到U盘并与它通信的,但是仅仅只有设备地址是不够的,还要知道主机与U盘中哪一个端点进行通信,因此还需要有一个端点地址,只有知道了设备地址和端点地址,才能实现对设备点对点发送和接收数据。
因此按道理来说,只要知道设备描述符和端点描述符就够了,就好比你要去XX学校找XX人一样,花点时间总会找得到行得通的。
而配置描述符和接口描述符的出现,只是为了能更好的管理端点而抽象出来的概念罢了,就好比指定了XX栋xx室一样,想象一下,你得到了这么一条信息,去深圳大学3栋305室找某某某,这是不是就比单纯告诉你去深圳大学找某某某要效率高很多了?
有这么三条需要注意的点:
1、一个设备可以有多种配置,但同一时刻只能有一种配置模式;
2、同一个端点不能出现在同一个配置下的一个或几个接口中;
3、同一个端点可以出现在不同配置下的一个或几个接口中;
好了说了这么多,到现在只知道有这么几种描述符,通过设备描述符可以知道配置描述符,通过配置描述符可以知道接口描述符,通过接口描述符可以知道端点描述符;从微观上来推理数据传输的过程就很简单了:
设备端USB协议产生0和1数据,在端点出构成一个接口,由接口又构成一种配置,由配置又构成一个设备,最后把这设备的信息交给主机进行数据处理,大概过程就是这样。
当然了,设备描述符中的数据不止有配置描述符,配置描述符中的数据不止有接口描述符,接口描述符中的数据不止有端点描述符,具体有以下的数据:
设备描述符:设备使用的USB协议版本、设备类型,设备版本号,端点0的最大包大小,厂商ID,产品ID,厂商字符串索引,产品字符串索引,设备序列号索引、包含的配置数······
配置描述符:包含的接口熟,配置编号,供电方式,是否支持远程呼唤,电流需求大小·····
接口描述符:接口编号,接口端点数,接口所使用的类、子类、协议······
端点描述符:端点号、方向,端点传输类型,最大包大小,查询时间间隔·······
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/150129.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...