|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
对USB的初步了解0 s" [- e3 h( g6 M4 U
1、USB的优点:
' B! f; \% b3 K" R# ?可以热插拔,即插上后可以自动识别; ! @* L8 v7 x$ A* ]* Y h1 D$ s; W7 g3 T" e# ~; c
! p# o, Z! `5 C0 P! t3 ]" ?" a( A. m, x6 o+ u# B" X3 d7 x
系统总线供电,USB共有四根线,一根电源线,一根地线,一根D+线,一根D-线,D+和D-线是差分输入线;! L1 O9 y2 U! e8 C
+ n% V s$ e* e
$ O: ?$ g7 C. ? y6 E2 m( o7 y- I2 ^ m
可以支持多种设备,且扩展容易,通过HUB可以再一个主机上连接多个设备0 O2 p5 f% A/ w' z% `! P8 A0 i/ Z6 L8 I$ r& j0 G
传输数据的速度快,最快可达480Mbit/s5 r* M- b7 ^9 o% `( [- g$ W7 z! ~2 R9 u
$ Z, W, v4 {0 q% G. c/ a; C
% e, D6 { x9 {# m) c+ ?方便的设备互联:在没有主机的情况下,实现点到点的通信(还可以实现主从互换)(USB OTG)7 {& k* v4 o/ ^+ z" r1 z x
4 D) x# j" M9 g4 `& J; \) z1 |# [, I$ m
' ^/ C" S% `! w5 O
2、USB的基本规范:0 ?# g+ x6 W2 W8 a" I7 {" }
" v* r1 s- `& M: n' h uUSB1.0/1.1 & ~& g }) u( M+ p5 d8 G0 h+ e$ P2 m6 y. C8 i
低速情况下1.5Mbit/s:键盘、鼠标等) d7 [- ]: T; B9 F9 [: j [0 m+ w
全速情况下12Mbit/s:U盘、CD-ROM1 u; Z% c! f: }3 M% [" Y" G: F$ Z8 @
" d2 c. o/ l( V& |+ w8 v) d) Q
+ O! `+ G& W1 h7 {
USB2.0 $ @/ v) Q3 g0 Q( ^) [9 Q; L" S- T/ H7 O) ?2 t- y- z, a
高速达到480Mbit/s:音频设备、显示器等$ r& i5 x: l2 ]' ~5 e, i) u q% g8 L8 C: T5 h# I" R; i
) a `9 O, t! v1 O' v
6 H. o) p2 T/ K2 E3 u' ]$ Q2 ]% [! A) |; _+ Q6 {
USB OTG
6 b5 r$ @( k, m设备到设备的传输# f* d8 {/ S# R3 T' b5 L- h; e
; W3 b1 x$ u9 Q- K* t" O" E4 Y* @3 J; h+ V- d0 F7 _
0 e7 l8 J+ f0 ~/ W2 d0 | _5 p! {2 b! x8 u
( d+ m0 G; j w: f+ m4 [3、USB设备类规范:
' e+ p, c0 K% K/ H) y% G& c% Y+ B. _* o5 D大容量存储设备类(Mass Storage Device)U盘、CD-ROM等
# l+ j) k" M6 O% o, J& ]; e0 U人机交互设备类(Human InteRFace Device)键盘、鼠标、游戏手柄
4 ?6 Y4 A1 x. r7 O: f# a/ t语音设备类(Audio Device)麦克风、音响等& H8 s3 {+ k, d$ W8 d! t
通信设备类(Communication Device)电话、调制解调器等
7 X, }9 [4 t8 G6 f打印机设备类(Printer Device)打印机
0 p% ]* X C: N2 B) u监视设备类(Monitor Device)显示器、摄像头等# R7 ^6 D( V9 v3 `/ Z/ `' J
/ \3 E# w/ n, B: B% h; K; b
9 H4 A( u9 J% V: P" k/ d$ X! o& |6 D k3 H/ \# V/ b/ ^% Z
4、USB逻辑上分为3:信号层,协议层,数据传输层+ D% i' w$ a4 }: |5 V* [
+ m: Z' r6 _2 i协议层:包是USB系统中信息传输的基本单位,所有的数据都是经过打包后在总线上传输的。& Y4 m0 I4 Z6 b# b
4 `- e- U. f$ H4 S" G' a6 _& R0 x2 @3 h& b# o* B5 N
+ b/ ~. U N" r0 j' m5 {. `% H包由6部分组成:同步字段(SYNC);包标识符(PID);地址字段(ADDR);数据字段(DATA);检验字段(CRC);包结束(EOP)% s% z4 l6 A$ q4 o& P4 v: w# z) f( s3 ]* _! Q
3 ~6 ?1 G$ q& r8 R$ o S: d. O! u0 I6 ~ `0 E
4 b6 U" J/ z# Y4 s8 r$ j3 I- e) a9 |+ P+ C4 Y8 z% H7 T
包标识符(PID):令牌包(Token)(输出,输入,帧起始,建立),数据包(DATA)(数据,数据1),握手包(Handsnake)(确认,不确认,停止),专用包(Special)(前同步)5 K/ m, Z" {/ p8 J3 n
0 c0 N& W# K" T, n8 f I5 S- z) i' K& m) [2 O! J$ z
! L1 [% Z( Z' R/ q0 W$ I) ]! g8 M1 A5 l6 ]' I$ G
5、USB协议提供4种数据传输方式: f1 ^! X/ V y
3 I4 [8 X/ ~6 j# ]; {控制传输:突发,非周期性,由主机发起,用于命令和状态的传输
# S' |& F: q; v0 q' j, }' | A& W. W. m& [+ G# O$ K6 q; C) @5 T; B) _+ {. @. V' y
0 v" a! A: A; p8 R6 ~1 A9 Y; P0 Z同步传输:周期性,持续性的传输,用于传输与时效相关的信息,并且在数据中保存时间戳的信息6 j7 |) P: u5 H' Y
F9 F6 ]" b4 m! @) ^
$ p# u7 e0 f) k1 N u6 a+ i4 B. b, }% h% R4 S @4 J
中断传输:周期性,低频率,允许有限延迟的通信: r y' ]$ C0 a$ J
7 R7 }& K5 |; m! F2 E1 \' F
! L$ v" g; M7 r Z
大容量的数据传输:非周期性,大容量突发数据的通信/ C3 l+ a; j# d$ A! b8 s- D' i
+ M$ V# r3 W3 D) D. L
/ ~' @8 f) {% Y+ r s4 r% c5 |
6、USB描述符:
& |& A/ R1 z# Y a! |0 h1)设备描述符:描述设备的类型、厂商信息、USB的协议类型、端点的报数据的最大长度等,每个USB设备只有一个Device Descriptor: K! m/ z2 l4 N1 A! `. J& u: o8 S1 W7 T" Y1 e* ^
3 N1 U; z6 i( w* h& o* ] W! R7 V& b' D2 o% x& v! }3 X& P
2)配置描述符:每个配置描述符提供了设备特定的配置,描述了设备的接口和端点的性质、供电模式、设备的耗电: [4 ~& P2 U" x/ d
2 q) n L% x% K# i8 h
" Y2 q8 o4 b9 H9 C/ \$ g$ G9 n
3)接口描述符:描述了设备的不同接口的特性,例如,一个设备U盘的功能,又有键盘的功能,用两个接口描述符分别描述两个功能
/ k, }, L1 _! S8 r. C5 W& T5 X9 D+ d
3 t+ P+ q0 P# G( M& X8 {: f5 x$ R6 W9 T0 P: R" D% A9 g8 K9 m, `0 w- H) v0 ~' j9 h, R
4)字符串描述符:描述了设备制造商、设备名称、何序列号等信息. }, l% N; u" l5 R
4 ~' e5 v4 H8 ?$ b$ k: F4 e, \# `
) X. T' M) O# m, d6 B( J V3 ^5 R2 O) R, ?
基于STM32制作USB的过程" Y& N! v* i' ~
3 b) N* E9 [! v; [STM32的USB模块特性:# x: V: A. R% X8 o) g/ r
8 n/ f. F' y$ J9 g- \4 e6 [) ?
# d" f6 W6 j7 f- q/ p遵循USB2.0全速设备标准
k6 N% ^! ~) M q6 R+ b8 G& Y/ `* O" u8 Q6 l/ x& Q# c+ b- b( y
7 g4 ~% K c+ |8 _% I* V支持双向8个端点,8个IN端点和8个OUT端点(每个端点最大可使用512字节)
% Z: w* s* b& a0 g) D( [- u" w8 H% b2 F6 Y D, g4 z) `: V# K5 {% X
& |) K& W0 @# Z
[ 每个端点都有一个缓冲区描述块,描述该端点使用的缓冲区地址、大小和需要传输的字节数]
& x& N2 I6 y; T8 Q1 \9 c5 J, F8 Y6 P ~8 }
9 w( `, n8 H8 h+ n Z8 t. x/ _! j, @8 x6 W. C; N/ z f+ B! l; x5 `
硬件实现CRC自动生成/校验,NRZI编码/解码和bit-stuffing(位插入,位填充)' s" O: P: a$ m5 k( k0 m, I" d+ X% r5 M& e: Z1 I. o+ }
1 G9 A5 u; t- O$ Q' r7 `8 p5 h" ~) ~$ V8 J
" ~+ H0 ~# a3 D) p
支持控制传输、中断传输、大容量传输和同步传输四种传输方式0 v6 A7 M+ L d- K8 l+ P+ j5 a( G
. ^' N8 D9 E3 d! e( ^$ D. Q k3 ^+ j* B/ B& { c: h1 ^6 I& c0 ]8 F3 o- f7 M% R0 S
; B7 q4 H0 |! u3 U( [
支持USB的挂起和/唤醒
& H: ]0 Y! n. ^1 A; {, l* L8 p$ } G3 o6 ?
USB设备的实现过程& t/ G& w/ M& A8 d- r3 E
系统初始化4 b/ e3 P7 c. g/ ?, ^! {/ k% V' i( k& m* |7 R8 w
1、 初始化系统时钟,设置USB时钟. O, d' s! X7 |8 m
$ W; q5 l# g8 z# b% s' g2、 配置USB中断,选择通道,设置优先级,使能中断! f$ W: I. M) V0 @' B+ E W0 ~* \
3、 配置GPIO
# o5 {0 F& [% r! S5 E4、 USB的初始化,对描述符、设备的端点接口等的初始化3 A$ @* P" |" k7 R+ d7 b
5、 FLASH的初始化, q' w; S/ d" V) R
8 L2 [) l& u' j+ T: s% e/ i5 @+ _1 U8 a) p& i/ c( e
; d y! H- Y7 D; T% ]
/ m; f7 E o2 d; f一、 USB的枚举; N1 C0 v7 [5 m1 Q, ?
枚举过程就相当于主机和设备建立连接的过程(接头),Host向Device询问一些东西,Device将自身的设备类型,如何进行通信报告给Host,这样,Host就知道怎么对Device进行操作。: M- c% `% @6 s7 [( I% V. C+ ~
7 t* U: ]7 S5 E; p
0 T$ o# R. J/ h7 Q, t在枚举过程中就是如何处理好SETUP事件,如果STM32 USB接收到正确的SETUP事件,将响应函数CTR_SETUP0(),此事件是特殊的OUT事件,数据方向Host->Device,SETUP事件数据长度固定为8。
" G& N+ z* X v. r$ l9 n X" H# A/ N: B s. l
* X& G. l f5 k4 z! J% w! E
% N7 g ?% r+ l& H! M( l0 ]1、 在USB插入主机时,主机首先需要先对USB设备进行供电
6 X* i8 {! ~: ~9 V. E$ S3 p) e
( l( K K7 T$ c6 `/ i; j4 Q M9 C2 }; w- k8 ]! N2 |1 t
2、 接着USB总线复位:6 O; t6 f, d7 G: U
~3 }! {7 W8 B! n: [6 w设置分组缓冲区描述表起始地址;( s9 X+ I9 s' W7 O) @! O! j; |0 q! v' j4 n! k3 |: P: q9 n; C; k
初始化端点0,设置发送和接收状态。默认所有的设备地址和端口地址都会初始化为0.8 r2 N. [0 X# v" L* ?; T0 w" T! t$ C! v
m6 {( a$ Z3 @6 L: r' [/ [5 \5 S$ `3 C2 G- A% ]( a. P# [8 x: J/ |8 \1 `
3、 USB主机往端点0的0地址位置发送获取设备描述符的请求。$ w% D$ V6 F- o* v$ H8 J
U3 ~/ K! u) w/*发送请求属于控制传输的建立过程,控制传输包括建立过程,可选数据过程及状态过程,首先是主机发送一个令牌,其次是发送的数据,最后设备回应一个应答(握手包)*/$ `5 n8 I2 ?. b; N. U/ Y$ C* d6 R' R- ?0 o: |* l7 Q
g" z( M8 w* ?8 Y/ g
+ e- Y! C w' o$ b& S% d( B0 q
4、获取设备描述符信息( ~* ], Q# n, \" v- a" \) ]
设备在接收到请求以后,首先需要对主机发送来的命令进行解析,并将要发送给主机的描述符信息填入USB缓冲区中,等待USB主机发送IN命令,主机在接收到设备发送来的ACK回应以后,发送IN令牌包,从而进入到数据过程,之前存储在USB缓冲区中的描述符信息发给主机,并等待主机的应答。主机在正确接收到设备描述符的信息时会返回一个确认信息。3 [6 r! S k" G# [
- ]; N5 p! h/ S% e k9 D' y; R
* O4 x% ~" s7 h. i
# X7 P' [+ M$ r4 g4 R7 Q0 x% U5、主机给设备分配一个新的地址+ A: X4 u$ H2 L3 d+ z+ E, T; s$ d; R) ]& w
该阶段是一个没有数据过程的控制传输。首先,在建立过程中主机往设备的端点0发送一个设备地址的请求,新地址在建立过程的数据包中。在建立过程之后直接进入到状态过程,在状态过程中,设备等待主机发送一个IN令牌包,收到IN令牌包后,设备就会返回一个数据包,如果主机确认该数据包正确接收,就会回应设备一个ACK,设备收到ACK之后启用新的设备地址
. w! j9 t0 ]3 t* z! R" \ p! _# j" C" F( q5 a. Z
0 G2 P* ~8 {, I, e' i& o7 F H
/ K _! C! D1 A0 m" y$ D8 j6、 主机重新获取设备描述符,配置描述符和字符串描述符(如果是HID还要获取报告描述符等) L6 ~$ S1 l9 R+ N6 L! R
至此USB的枚举过程完成,主机可以根据枚举的过程了解到的设备信息对USB安装驱动程序,并对USB进行操作。9 _2 f1 n1 n* Q7 V
7 a4 |- p- I& B2 V K
$ l- c' v3 A4 H二、 对程序的分析9 E4 L7 M( o! N8 @% _: L9 x4 H$ N" h3 Y: x% b" G% V
1、 在Set_System()中首先配置了RCC时钟,在设置并开启USB的时钟RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
% a" }& g2 G z6 D5 C
3 G5 S. F% ?3 R. O# D0 f" O5 V& n3 u+ c: }, @& K$ G& e% K7 I
2、 对USB的引脚的设置,主要设置上拉电阻,对于此STM32板子而言是设置PC13为开漏输出(GPIO_Mode_Out_OD)1 Q7 H7 o: |% W3 t% {. O
5 p" ], M% O0 ]; X x+ `- ` V7 g" g- \3 X" F+ ]
! g) Y8 m( _7 M" r$ I: P) V7 S9 b8 q/ R; \0 }! x; }8 ^, B& G
3、 USB中断的设置,设置了USB_LP_CAN_RX0_IRQChannel中断,因为在USB传输的过程中使用的是控制传输过程: z, R5 f; l8 a8 }5 l* @
( b( Y- y8 }; S5 x, C# j
3 ?' \. W, ^# _: e4 ?0 B# L( d
- i9 x. ~( z8 n6 u* l2 \, p4、 最后对USB的初始化,初始化USB的控制状态为IN_DATA状态,对一些需要使用的指针的初始化,包括设备信息,设备标准请求,设备的支持等的初始化,供枚举过程的使用
/ d6 y8 o9 z, b7 B& r
0 z, D* V) E6 p4 M: Y9 s# r# s! q4 {! j/ K
至此,对于USB设备的初始化过程已经完成,接下来进行USB的主要程序部分,也就是枚举过程。
5 o1 n+ @6 s4 w8 |) v$ W+ X# a+ F# [8 }$ B+ M8 F# |
* E, V, h; \7 O+ o4 H( y5 J
( k6 P; f5 U/ r- Z6 k9 I& ^插上USB之后首先会进入中断过程,执行USB_Istr()函数中的操作,逐步进入枚举过程,接下来从中断操作开始分析6 t: `4 d* {/ \+ z& z% x9 Y: h. ]' X7 c/ F b
" i, {* [3 _; j, ^8 y d1 p, f; o6 y- O& @' }
7 r5 ^& G9 ~0 k6 {9 d1、 进入中断执行USB_Istr()函数后,首先获得中断的状态,因为在初始化阶段,首先先对USB进行了复位操作,所以直接可以进入Device_Property.Reset()函数进行复位操作。6 s9 E( R% A$ x' n6 ?- s- p* V3 O8 o' i! c* S/ d: w/ K
2 U" S* _3 `% Z
得到USB的各类描述符值,设置报表地址为0x00,端点地址为0x00,又对USB的端点0和端点1的进行了初始化设置/*在usb_prop.c文件中*/7 e- n( {3 H- L. ~7 X3 G7 u2 Y% I6 @) }7 B$ M
- |, }0 x- Z# V1 L
0 X- S5 o h& H* W7 O; B( Y% O3 U8 w* Q9 ] u( |" m8 X, Q Z2 s) m1 q8 ~8 N2 q* Y" J! |
2、因为在USB枚举的阶段是通过控制传输的传输过程来实现的,所以数据的发送接收,通过CTR_LP()中断进入的1 x4 T I) c6 k1 A% k4 I. D
) t0 I. P; ~8 ~% w3 G$ } 8 {, _' A" W+ Z5 r' A# |8 ^2 ~
在这个函数中等待中断状态设置好,并且数据发送正确。然后检查是不是端点0的收发数据,因为在一开始枚举阶段首先是通过端点0来接收主机发来的数据,所以直接进入端点0的函数中if (EPindex == 0)。等地啊主机的IN命令if ((wIstr & ISTR_DIR) == 0),接着进入In0_Process();函数往主机中发送数据。进入In0_Process()函数以后首先要判断控制状态是IN_DATA、LAST_IN_DATA 、WAIT_STATUS_IN中的哪一个或者都不是。+ L$ T! W" m* T7 \7 S; l0 s$ F* I2 Y2 ?3 G1 Z- k0 g
7 a. l5 X& f/ R4 R: `% n& f) P0 J! }, h: U9 k' [( l& O
2 I8 k8 W8 @! W% z, S
等待数据的发送,假设是IN_DATA或LAST_IN_DATA,则进入数据发送阶段DataStageIn()函数,主要是发送开始存入缓存区中的数据,以描述符为主,发送给主机。
/ ] I1 x& Y+ Z/ t& k. K1 g! z; m/ f$ O @" r: p$ p/ F# R, b! T) O
) c. ]2 R/ z5 A3、在主机接收到USB发送来的数据之后,主机会重新给USB分配新地址,这是进入中断在轮询时会检测到((wEPVal & EP_CTR_RX) != 0)进入到USB的接收状态,接着会执行Out0_Process();的主机输出,USB接收状态。此数据输出主机的过程与上面数据输入主机的过程相类似。也会初始化数据包长,并根据数据长度来进行数据的接收状态。
k+ o) W% \0 Y; W
4 C, _# X1 g! T& O* F* G" T
' @% f% E r$ P数据从主机SB和数据从USB写入主机主要由UserToPMABufferCopy()MAToUserBufferCopy()两个函数来完成& j6 J! Z% c/ d: g* J, n; o6 {" O) L9 l4 K& @( K' I+ Y
$ v' \( [ ^5 M( h# [
1 E: o- w* W2 u# L. r/ z" t6 D* f7 C+ U) S1 D0 z; V3 }
4、接下来主机会以分配给USB的新地址来与USB进行数据通信。通信过程与之前相类似,只是不再使用端点0,而是使用新地址,非0端点的处理。9 m8 I6 _8 d! v
/ k- Z' n6 ^; t, ^6 t7 a! P. a! G+ d
接下来说一下USB不同的c文件的功能:) p& n! {9 a! ]5 j( @
Usb_core.c枚举过程重要的函数在此列出,包括数据输出主机的函数DataStageOut()数据输入主机的函数DataStageIn(),非0数据包的建立Data_Setup0(),0数据包的建立NoData_Setup0(),还有主机发送的IN进程In0_Process(),主机发送的Out进程Out0_Process()。还有一些标准的配置函数,接口设置函数等等。1 G7 q& i: W" R$ U& [6 t" e! `' o7 C' f
* g7 b2 Y( j, t% n$ f3 d) ]0 M0 Y1 | e/ h) T9 @7 |6 N
Usb_init.c这个c文件中只包含一个主要的函数USB_Init(),这里主要是对在usb_core.c中使用的重要指针的初始化,包括pinformation,pProperty和pUser_Standard_Requests这三个指针,另外就是在初始化状态时已经将usb的控制状态设置为IN_DATA状态。并将USB初始化为初始配置,上电,开始设备的状态为未连接状态等 ?9 e) K8 G0 Q+ r) y$ l4 p" I( n+ L7 G" a R7 p
% s1 v, {0 j1 O' C" b2 k5 Y+ C5 C0 ^1 c
9 |: L" Y% W6 T' ?& K- X; t5 b1 U7 f! h1 `9 q; C
Usb_int.c包含两个主要函数CTR_HP()和CTR_LP(),CTR_HP()用于处理高优先级中断,用于同步传输模式和批量模式(双缓冲区),CTR_LP()用于处理低优先级中断,用于控制传输,中断传输和批量传输(单缓冲区)。
* R* ]( T1 V0 [& A' v* `" K1 {* ?6 x/ t5 x% {
$ x) e8 b+ }1 `% Q. T0 V
Usb_mem.c包含两个函数PMAToUserBufferCopy()和UserToPMABufferCopy(),是将PMA缓冲区的数据传给用户,和将用户缓冲区数据传给PMA缓冲区的主要数据传输过程。- I: c0 G' z- K! `+ f8 g
% C% d' k4 f# s+ o9 P; {( h! w9 \; l) \& j& r+ `( ?& K- `7 Y/ `* k( a( Q4 s
# P0 L6 X/ j3 G0 m& Q! ~: N
Usb_regs.c主要是调用宏,实现寄存器的操作,但是上层函数很少调用这些函数直接就是用宏。& O2 F& U6 Q. V, u
+ p& H6 q; l4 l0 y7 c7 ^/ G: t3 V$ [& h2 y
$ Q& r# V# i3 R5 k) a
Usb_pwr.c主要是包括对一些电源的配置,包括USB上电PowerOn(),USB断电PowerOff(),挂起函数Suspend(),处理唤醒恢复操作Resume_Init(),状态机处理和恢复函数Resume(); h: K/ _. g8 |9 n- _6 Y+ I" m
: B' T8 m" i8 C- a6 L% hUsb_desc.c主要是对描述符的定义,有CustomHID_DeviceDescriptor[18],CustomHID_ConfigDescriptor[],CustomHID_ReportDescriptor[],CustomHID_StringLangID[],CustomHID_StringVendor[],CustomHID_StringProduct[],CustomHID_StringSerial[]。
- @0 {% _- Q7 O9 u3 XUsb_prop.c是对一些获得描述符的设置,还有复位和初始化的设置,主要的函数是CustomHID_init()和CustomHID_Reset()两个函数: z! E+ h1 q- r
|
|