
USB设备能否工作,枚举步骤,用“乡村爱情”里的话说,“必须的!”,网上也有很多资料,圈圈就提供了一份详细的枚举过程,但对STM32是怎么响应的没有说明,一会详细道来,先上圈圈的提供的那个枚举图示,希望圈圈支持,如果不妥,请与我联系,谢谢。 f* {4 T. I. ~ 我将此转换成了PDF文件,方便查看。* M- ~/ L7 }1 o- c* e 首先说明一个变量,定义在usb_core.c中: volatile DEVICE_INFO vsDeviceInfo; 7 ]2 S- @+ C# ^ 看意思就知道他的作用了,DEVICE_INFO是个结构,定义在usb_type.h中: // ***************************************************************************** % R: A0 O5 w* f. P* ] // DEVICE_INFO ! {4 t: z' H8 I; ^: H8 | // ***************************************************************************** ( T8 f/ p2 }( O) u$ U, p7 N typedef struct _DEVICE_INFO { unsigned char bDeviceAddress; ' F5 P- H% I! U* K9 a2 E9 D- ~ unsigned char bCurrentFeature; unsigned char bCurrentConfiguration; 6 m- _ Y' n$ ^/ z; V/ ]" N unsigned char bCurrentInterface; unsigned char bCurrentAlternateSetting; . ^ ?% K6 ^% X( H9 ^. [& K* b WORD_2BYTE uStatusInfo; DEVICE_STATE eDeviceState; 7 v1 \! o& @" O' q ~* W; t. x' W RESUME_STATE eResumeState; 8 i: C0 |" p: Q; _& ~6 T CONTROL_STATE eControlState; SETUP_DATA SetupData; " N. C% l$ o# o . n: a# X2 s' `- R TRANSFER_INFO TransInfo; } DEVICE_INFO, *PDEVICE_INFO; 8 N+ c; o. E- _# Y 在枚举过程中,就是如何处理好SETUP事件,如果STM32 USB接收到正确的SETUP事件,将响应函数CTR_SETUP0(),SETUP事件是特殊的OUT事件,数据方向 Host->Device,SETUP事件数据长度固定为8,数据定义在DEVICE_INFO.SetupData,其数据结构是(定义在 usb_type.h中): ! B8 W7 i j6 q; @6 X m4 k9 ? typedef struct _SETUP_DATA { ( q7 x6 b" X. ?7 Z! x6 [ unsigned char bmRequestType; // request type . h/ R3 ]$ p; o' F* e unsigned char bRequest; // request code WORD_2BYTE wValue; - D9 s9 y4 I! | WORD_2BYTE wIndex; 1 h7 z ]8 R6 e& C- { O5 [ WORD_2BYTE wLength; } SETUP_DATA, *PSETUP_DATA; WORD_2BYTE是定义的一个共用体: : Z3 A. l& d5 b# b# N; } { typedef union _WORD_2BYTE { unsigned short w; struct { unsigned char LSB; unsigned char MSB; 0 n/ G: s0 p- p, Q }b; } ( T. b4 h; K: E! r8 }) S WORD_2BYTE; - d) c- R6 r5 l4 Q" G) q4 Y m* E 0 G, q' E+ n. S3 F- i4 O1 x) {+ z$ T 为什么将SETUP数据结构中的wValue,wIndex,wLength如此定义? ( z. E2 e5 s0 ?5 b" O4 t8 U 1:USB协议中所有数据传输都是依照低位在先的原则 / k& M# a; A# W' G 2:高地位字节可能功能复用 ' u* ? }- w8 Z x8 x% k 这样在后续的程序编写中就变得十分方便,ST提供的USB固件方法同样如此,但这方面的处理让人有些摸不着头脑,详情可参阅。至于具体的SETUP数据结构含义如何,还是要具备基本知识:了解USB协议 1 n9 H, [% w1 O: j4 i! Z CTR_SETUP0() 函数将SETUP数据提取出来,SETUP数据结构有0长度和非0长度的数据结构,详细参阅USB2.0官方协议第9章。在这将两种区别开来分别执行 SETUP0_NoData()和SETUP0_Data()函数,并返回结果,根据返回结果再响应USB主机 ! D' C, D1 w; j+ h1 o // ***************************************************************************** 4 T( f" d2 i8 b' v // Function Name : CTR_SETUP0 // Description : 5 W; C4 [7 x+ Z8 L // Input : // Output : 9 N" s5 m, D/ s // Return : // ***************************************************************************** void CTR_SETUP0(void) 0 e$ I7 u8 V" J' p { RESULT eResult; ! W# G$ @8 ~* [$ Y. I' N BufferCopy_PMAToUser( (unsigned char *)&vsDeviceInfo.SetupData, GetBuffDescTable_RXAddr(ENDP0), / Y+ J' B* { T/ d- ^ GetBuffDescTable_RXCount(ENDP0)); ; o8 r( } _# C if(vsDeviceInfo.SetupData.wLength.w == 0) , \8 e7 L" J6 B { eResult = SETUP0_NoData(); } , o5 o0 c1 g( v }2 R9 i else + V* ?& r9 a |1 i( q# f+ N& z { eResult = SETUP0_Data(); } / q `& j, K* ^& o7 S) S$ ?8 W( i switch(eResult) . s* B% R! O( S$ D+ |1 A+ Y { case RESULT_SUCCESS: " U+ G& H' ^' R1 f( V; { break; case RESULT_LASTDATA: # `! L& o7 V: M6 l7 G0 K break; 6 M! X. z: l, Y+ \# z: a) I case RESULT_ERROR: / C7 Y+ Z+ W! e3 E; T6 t case RESULT_UNSUPPORT: 9 w: l: S1 K# ?' P1 o5 N) q SetEPR_RXStatus(ENDP0, EP_RX_VALID); 8 c9 u6 F* X: X& S0 c8 Z$ X0 M/ f SetEPR_TXStatus(ENDP0, EP_TX_STALL); 9 |4 v& [7 ~; e+ P: B break; ' e5 s/ e$ u" G. i: v* c } } ' X( K3 A2 g- K3 \& M 1 u0 b! n; j& V ` SETUP0_Data() 和SETUP0_NoData()函数支持的所有USB请求类型只有罗列的这些,有多少种组合都定义在USB协议中,程序根据请求代码,再去执行对应函数,这样做的目的就是让程序结构明了。其中注释为"// done"的部分表明此部分功能已完成。对于未完成部分,希望大家在交流中完善。 7 M( z: X1 c" x9 d0 v! b- t // ***************************************************************************** // Routine Groups: SETUP_Data 1 B+ H! b6 d" v J* ?, ]* e- o // ***************************************************************************** ' H) H* w8 }2 m RESULT SETUP0_Data(void) 1 A( g( Q7 l5 B- k* H$ y$ c { // SetupData.bRequest: request code & x, b* K. z$ Z, O# l) _6 s6 I! b switch(vsDeviceInfo.SetupData.bRequest) * o5 u9 ^# j% f1 q6 h { case SR_GET_STATUS: return SR_GetStatus(); // done 6 F H$ X) l5 ? case SR_GET_DESCRIPTOR: return SR_GetDescriptor(); // done case SR_SET_DESCRIPTOR: return SR_SetDescriptor(); // unsupport case SR_GET_CONFIGURATION: return SR_GetConfiguration(); // done case SR_GET_INTERFACE: return SR_GetInterface(); // unsupport " Q# K3 y# D* ^ case SR_SYNCH_FRAME: return SR_SynchFrame(); // unsupport 7 S+ b2 _( r9 { default: return RESULT_UNSUPPORT; } } $ x- z: d7 e9 k' Q; Z# u, x 9 e6 z3 ~( h2 W) L r // ***************************************************************************** // Routine Groups: SETUP_NoData // ***************************************************************************** RESULT SETUP0_NoData(void) % q' ?, e+ g: E$ g3 J1 C { // SetupData.bRequest: request code switch(vsDeviceInfo.SetupData.bRequest) { case SR_CLEAR_FEATURE: return SR_ClearFeature(); // unsupport & o! Q# P7 ]1 |4 ?( o case SR_SET_FEATURE: return SR_SetFeature(); // unsupport case SR_SET_ADDRESS: return SR_SetAddress(); // done case SR_SET_CONFIGURATION: return SR_SetConfiguration(); // done case SR_SET_INTERFACE: return SR_SetInterface(); // unsupport default: return RESULT_UNSUPPORT; } ! O0 Q) w1 L1 a7 [$ w4 N } 下篇将介绍上述的各个请求函数如何响应主机。 |
USBæä¸¾è¿ç¨å¾è§£.pdf
下载273.09 KB, 下载次数: 202
最全USB HID开发资料,悉心整理一个月,亲自测试
实战经验 | 选择USBX模块生成USB CDC ACM无PD的项目
STM32 USB HID键盘例程
刘氓兔的杂谈【001】-片上USB 高速PHY
【经验分享】在进行 USB CDC 类开发时,无法发送 64整数倍的数据
【源码】STLINK-V3MINI 高速USB仿真器,成功改刷【高速CMSIS-DAP】
在线直播|无需编写任何代码即可在STM32上实现USB-C Power Delivery
STM32 USB CDC 虚拟多串口
圈圈发布USB图书第二版有感,以及分享一些我学习USB过程...
USB Audio设计与实现
回复:基于STM32的USB程序开发笔记(四)——USB设备的枚举(上)
RE:基于STM32的USB程序开发笔记(四)——USB设备的枚举(上)
回复:基于STM32的USB程序开发笔记(四)——USB设备的枚举(上)
RE:基于STM32的USB程序开发笔记(四)——USB设备的枚举(上)
RE:基于STM32的USB程序开发笔记(四)——USB设备的枚举(上)
回复:基于STM32的USB程序开发笔记(四)——USB设备的枚举(上)
回复:基于STM32的USB程序开发笔记(四)——USB设备的枚举(上)
回复:基于STM32的USB程序开发笔记(四)——USB设备的枚举(上)
RE:基于STM32的USB程序开发笔记(四)——USB设备的枚举(上)