
USB设备能否工作,枚举步骤,用“乡村爱情”里的话说,“必须的!”,网上也有很多资料,圈圈就提供了一份详细的枚举过程,但对STM32是怎么响应的没有说明,一会详细道来,先上圈圈的提供的那个枚举图示,希望圈圈支持,如果不妥,请与我联系,谢谢。 我将此转换成了PDF文件,方便查看。) Y6 t! R* i g( u( s7 o# c 首先说明一个变量,定义在usb_core.c中: volatile DEVICE_INFO vsDeviceInfo; 看意思就知道他的作用了,DEVICE_INFO是个结构,定义在usb_type.h中: . j: R7 _* I8 r4 A4 F // ***************************************************************************** ! c8 w0 J. Q; z // DEVICE_INFO 7 h7 O+ U6 z* V; Q2 c$ q4 o! a. F5 i" u // ***************************************************************************** typedef struct _DEVICE_INFO " E7 R( L5 x V/ w4 m, x% s { 3 r. r9 T/ C- B6 r: l1 n unsigned char bDeviceAddress; 3 Q/ \6 ^) z0 {+ G unsigned char bCurrentFeature; unsigned char bCurrentConfiguration; unsigned char bCurrentInterface; 4 R7 U$ t5 t- N! Y \5 @ unsigned char bCurrentAlternateSetting; WORD_2BYTE uStatusInfo; DEVICE_STATE eDeviceState; RESUME_STATE eResumeState; 9 s1 n4 [" X& W' C3 s2 e CONTROL_STATE eControlState; # G* E3 U. n0 d* c0 r8 }3 ~ ! O" z) R i8 M5 k: o& R SETUP_DATA SetupData; TRANSFER_INFO TransInfo; } DEVICE_INFO, *PDEVICE_INFO; ; D& R' ]# c: x. C7 m' c0 N9 y ; e3 K( A* |: m: Q8 p 在枚举过程中,就是如何处理好SETUP事件,如果STM32 USB接收到正确的SETUP事件,将响应函数CTR_SETUP0(),SETUP事件是特殊的OUT事件,数据方向 Host->Device,SETUP事件数据长度固定为8,数据定义在DEVICE_INFO.SetupData,其数据结构是(定义在 usb_type.h中): ; ~0 z; D5 o- v3 `# m: ]5 ^; @7 C# V typedef struct _SETUP_DATA 7 ~ W* @1 W* l5 T ?0 h9 n { 5 W5 w8 n, l. _! L( O+ y unsigned char bmRequestType; // request type unsigned char bRequest; // request code ; J; p3 s7 ~) W) ]# T WORD_2BYTE wValue; 8 b" F3 i! V( M/ ^: a8 s X$ ?3 @ WORD_2BYTE wIndex; ' b! W6 O l: J4 p WORD_2BYTE wLength; 4 g# b1 G9 L- b1 @4 N } " Q( }6 _6 A. c+ S. i3 [* |: D- l SETUP_DATA, $ h2 t4 g0 u+ D( z& y *PSETUP_DATA; $ y5 w3 Z' t& A+ l6 M* e- p 0 V" `; F" T9 I! D: G( L2 ~ WORD_2BYTE是定义的一个共用体: typedef union _WORD_2BYTE { 4 Z+ P7 [% y& N# X. e" \ unsigned short w; struct ( G3 \( i' C) l* x+ Q7 ^, I { unsigned char LSB; 2 F: q) n+ \, {7 P" x( B0 F, m0 c6 V unsigned char MSB; }b; } 4 F1 x/ E# i, T1 i WORD_2BYTE; ! @3 |3 O& n3 l- M1 d3 H% q3 O 为什么将SETUP数据结构中的wValue,wIndex,wLength如此定义? 9 R: H; F- ~& _* _% p 1:USB协议中所有数据传输都是依照低位在先的原则 2:高地位字节可能功能复用 这样在后续的程序编写中就变得十分方便,ST提供的USB固件方法同样如此,但这方面的处理让人有些摸不着头脑,详情可参阅。至于具体的SETUP数据结构含义如何,还是要具备基本知识:了解USB协议 CTR_SETUP0() 函数将SETUP数据提取出来,SETUP数据结构有0长度和非0长度的数据结构,详细参阅USB2.0官方协议第9章。在这将两种区别开来分别执行 SETUP0_NoData()和SETUP0_Data()函数,并返回结果,根据返回结果再响应USB主机 // ***************************************************************************** // Function Name : CTR_SETUP0 ) r5 C( k5 @7 d6 b5 J // Description : // Input : + w6 B: l/ u* A- `7 P! @ // Output : // Return : & a( ?5 A. l# X7 D9 U# I // ***************************************************************************** " r/ e8 D8 k( Z" C void CTR_SETUP0(void) { # F6 m' Z# D f$ A RESULT eResult; + `- Z) @, o/ ?, P/ ~ BufferCopy_PMAToUser( (unsigned char *)&vsDeviceInfo.SetupData, GetBuffDescTable_RXAddr(ENDP0), 3 `/ A% M, G2 T* D4 G2 B GetBuffDescTable_RXCount(ENDP0)); if(vsDeviceInfo.SetupData.wLength.w == 0) * z6 u$ A: ?# a( e! F+ H { eResult = SETUP0_NoData(); } else + `# a" f7 O1 G: Q3 ~ { eResult = SETUP0_Data(); } ; {5 ~2 }3 Y, u4 j switch(eResult) , V, n; E0 Z, w# k8 R$ f { case RESULT_SUCCESS: , G* x6 M5 D* }! u2 e break; case RESULT_LASTDATA: 7 q6 V0 n; }9 r5 ?6 g$ B break; + z6 u2 \3 i2 C% K case RESULT_ERROR: h/ E# ~5 j" ?8 s: ] case RESULT_UNSUPPORT: 5 _7 j5 l+ u$ l! z SetEPR_RXStatus(ENDP0, EP_RX_VALID); * q1 E6 s& b2 ]3 P, U6 V SetEPR_TXStatus(ENDP0, EP_TX_STALL); . R& O; h* W5 q0 N! ]* r& ` break; } } . `; C* J, Q) }0 X SETUP0_Data() 和SETUP0_NoData()函数支持的所有USB请求类型只有罗列的这些,有多少种组合都定义在USB协议中,程序根据请求代码,再去执行对应函数,这样做的目的就是让程序结构明了。其中注释为"// done"的部分表明此部分功能已完成。对于未完成部分,希望大家在交流中完善。 // ***************************************************************************** $ \% `$ U+ ~2 U9 \2 o, D // Routine Groups: SETUP_Data . X+ X7 J. c/ J" v9 I* { // ***************************************************************************** RESULT SETUP0_Data(void) { // SetupData.bRequest: request code switch(vsDeviceInfo.SetupData.bRequest) { case SR_GET_STATUS: return SR_GetStatus(); // done case SR_GET_DESCRIPTOR: return SR_GetDescriptor(); // done * V% k, X: u# m$ { case SR_SET_DESCRIPTOR: return SR_SetDescriptor(); // unsupport case SR_GET_CONFIGURATION: return SR_GetConfiguration(); // done case SR_GET_INTERFACE: return SR_GetInterface(); // unsupport # w* d# m: x$ ^8 _2 S) v5 M case SR_SYNCH_FRAME: return SR_SynchFrame(); // unsupport default: return RESULT_UNSUPPORT; } . t4 p/ v: U$ m6 i9 q } ; z1 r# v3 }- s- R Q6 u8 z% Z! U( H 1 e) z& t( I0 q# ~ // ***************************************************************************** # L0 V0 b& A( T2 ~ // Routine Groups: SETUP_NoData // ***************************************************************************** RESULT SETUP0_NoData(void) 0 s( T o0 p- {7 m! B! P/ R7 d { 8 ^/ Z3 B7 G6 [0 b // SetupData.bRequest: request code switch(vsDeviceInfo.SetupData.bRequest) $ [/ r+ |4 C* p" G( j { $ S0 T! p! ^& D case SR_CLEAR_FEATURE: return SR_ClearFeature(); // unsupport case SR_SET_FEATURE: return SR_SetFeature(); // unsupport case SR_SET_ADDRESS: return SR_SetAddress(); // done ; ~( V. y( w" X4 j X case SR_SET_CONFIGURATION: return SR_SetConfiguration(); // done case SR_SET_INTERFACE: return SR_SetInterface(); // unsupport default: return RESULT_UNSUPPORT; } } 下篇将介绍上述的各个请求函数如何响应主机。3 a2 a" O1 L; P8 @# T |
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设备的枚举(上)