
USB设备能否工作,枚举步骤,用“乡村爱情”里的话说,“必须的!”,网上也有很多资料,圈圈就提供了一份详细的枚举过程,但对STM32是怎么响应的没有说明,一会详细道来,先上圈圈的提供的那个枚举图示,希望圈圈支持,如果不妥,请与我联系,谢谢。 我将此转换成了PDF文件,方便查看。8 l: ~2 }9 j2 P" I: D0 C 首先说明一个变量,定义在usb_core.c中: volatile DEVICE_INFO vsDeviceInfo; ' J ]& s; |) L) J& M7 A5 M 看意思就知道他的作用了,DEVICE_INFO是个结构,定义在usb_type.h中: // ***************************************************************************** ( D3 }% y: F+ | t4 X( h% O // DEVICE_INFO // ***************************************************************************** 2 I. Q3 z$ v+ D& z1 ^/ \, ^ typedef struct _DEVICE_INFO { unsigned char bDeviceAddress; $ ] |" H9 b1 K unsigned char bCurrentFeature; $ u3 J! q. i, h) ?0 u8 V unsigned char bCurrentConfiguration; % m$ p7 t! H) T0 y unsigned char bCurrentInterface; ; ]! ?& a1 N5 A, ^ unsigned char bCurrentAlternateSetting; # P' M$ N0 X) e9 Y2 l7 w0 s+ S$ ]9 S1 g WORD_2BYTE uStatusInfo; / @2 K/ K# A/ j H' ?0 A2 V DEVICE_STATE eDeviceState; ( g0 w, E9 _4 L6 W RESUME_STATE eResumeState; CONTROL_STATE eControlState; SETUP_DATA SetupData; TRANSFER_INFO TransInfo; } i$ z4 d) B+ j3 ^- P DEVICE_INFO, 3 t( Y0 g6 F0 V- L# h *PDEVICE_INFO; 在枚举过程中,就是如何处理好SETUP事件,如果STM32 USB接收到正确的SETUP事件,将响应函数CTR_SETUP0(),SETUP事件是特殊的OUT事件,数据方向 Host->Device,SETUP事件数据长度固定为8,数据定义在DEVICE_INFO.SetupData,其数据结构是(定义在 usb_type.h中): & m4 Y0 ^4 q. D, m: |7 C, v$ u typedef struct _SETUP_DATA { unsigned char bmRequestType; // request type " m3 k. V/ T8 D- k' o( A% q, F4 c I( F unsigned char bRequest; // request code ' {* v1 ^4 f2 d# M% k' F WORD_2BYTE wValue; : J8 y! v0 o" U' V WORD_2BYTE wIndex; WORD_2BYTE wLength; } SETUP_DATA, *PSETUP_DATA; WORD_2BYTE是定义的一个共用体: typedef union _WORD_2BYTE 2 p. u8 w7 J' B! o G3 `8 `( O { unsigned short w; struct { 9 b* I1 O1 ]$ l$ L2 x' M0 b unsigned char LSB; / H. q! p& V) e unsigned char MSB; }b; } Y" Q! \" v0 ?3 E0 p% G WORD_2BYTE; ! l0 }6 n- N$ ~6 O1 O 为什么将SETUP数据结构中的wValue,wIndex,wLength如此定义? % i$ j8 T% `: @! ]2 C4 [% L5 c" [3 L 1:USB协议中所有数据传输都是依照低位在先的原则 0 C7 X8 r0 f+ i5 S) o) S 2:高地位字节可能功能复用 这样在后续的程序编写中就变得十分方便,ST提供的USB固件方法同样如此,但这方面的处理让人有些摸不着头脑,详情可参阅。至于具体的SETUP数据结构含义如何,还是要具备基本知识:了解USB协议 CTR_SETUP0() 函数将SETUP数据提取出来,SETUP数据结构有0长度和非0长度的数据结构,详细参阅USB2.0官方协议第9章。在这将两种区别开来分别执行 SETUP0_NoData()和SETUP0_Data()函数,并返回结果,根据返回结果再响应USB主机 // ***************************************************************************** 2 y6 l2 U. ~/ E6 Q9 g: z // Function Name : CTR_SETUP0 ; P6 o7 _# G. m2 K // Description : // Input : 9 O- P, K! ^, {+ ^* [ // Output : // Return : / h5 e r8 V' ~- r% h // ***************************************************************************** 1 y0 m/ Y+ l1 K: r/ x! x void CTR_SETUP0(void) { ; o3 x5 M; n3 r5 ?% Z' P: }- r( \4 O RESULT eResult; BufferCopy_PMAToUser( (unsigned char *)&vsDeviceInfo.SetupData, GetBuffDescTable_RXAddr(ENDP0), 4 _" E: C6 _) M; G GetBuffDescTable_RXCount(ENDP0)); + R, x3 T0 v* [/ I! _ if(vsDeviceInfo.SetupData.wLength.w == 0) 7 }2 w5 |3 F+ K { eResult = SETUP0_NoData(); + l: x# ^1 v) j& d# j2 m: e% ~ } 8 Z1 v& I9 G! D) \8 k+ p else { eResult = SETUP0_Data(); } - i) N! U0 S1 h: L) ^! c$ J switch(eResult) 0 N; i r7 m9 t. P8 f$ z0 g { * E: W. }7 a" h' k6 R* s1 W( G case RESULT_SUCCESS: X( L9 w8 N9 k% V) E ' _2 {! s6 M) y- ]; w9 ~. K- p* O break; case RESULT_LASTDATA: 8 }6 n/ x% u1 P+ l# A7 h * R+ s) Q0 L! C break; - A7 D/ H; ^5 a \) N case RESULT_ERROR: case RESULT_UNSUPPORT: SetEPR_RXStatus(ENDP0, EP_RX_VALID); SetEPR_TXStatus(ENDP0, EP_TX_STALL); break; } } SETUP0_Data() 和SETUP0_NoData()函数支持的所有USB请求类型只有罗列的这些,有多少种组合都定义在USB协议中,程序根据请求代码,再去执行对应函数,这样做的目的就是让程序结构明了。其中注释为"// done"的部分表明此部分功能已完成。对于未完成部分,希望大家在交流中完善。 ! {/ ^7 T2 G/ H R. v, z ; }' n2 P6 _; _0 n L // ***************************************************************************** // Routine Groups: SETUP_Data // ***************************************************************************** . w# m* M2 C8 B% c RESULT SETUP0_Data(void) 4 c: L, ?" ?* I$ i# p) Q9 n { // SetupData.bRequest: request code # s) w# A2 f) Q7 T. H+ g6 ?& A switch(vsDeviceInfo.SetupData.bRequest) + r* Q5 i8 ^; \ { case SR_GET_STATUS: return SR_GetStatus(); // done case SR_GET_DESCRIPTOR: return SR_GetDescriptor(); // done & l8 v9 ?7 y; s, r case SR_SET_DESCRIPTOR: return SR_SetDescriptor(); // unsupport case SR_GET_CONFIGURATION: return SR_GetConfiguration(); // done 9 O: }3 o# D7 M9 W+ \/ q! [ case SR_GET_INTERFACE: return SR_GetInterface(); // unsupport case SR_SYNCH_FRAME: return SR_SynchFrame(); // unsupport 5 U: U7 @) H8 @$ i( v9 J5 s% U- y default: return RESULT_UNSUPPORT; } } 4 ^0 Q7 g% a+ T5 D 0 N+ w0 ~* r0 L$ j) ^$ {& J" B // ***************************************************************************** 5 R H# n4 k/ V( K% T2 K // Routine Groups: SETUP_NoData * R) ~9 H, k; E6 d6 {3 E" Q // ***************************************************************************** RESULT SETUP0_NoData(void) { ) O' i5 W- \0 |& d( w // SetupData.bRequest: request code ( [% y2 x8 t; i/ H4 k! r( R( Z switch(vsDeviceInfo.SetupData.bRequest) { case SR_CLEAR_FEATURE: return SR_ClearFeature(); // unsupport ! a0 N9 g! W: \8 `4 E case SR_SET_FEATURE: return SR_SetFeature(); // unsupport case SR_SET_ADDRESS: return SR_SetAddress(); // done / r$ {# o; L1 t- B/ H case SR_SET_CONFIGURATION: return SR_SetConfiguration(); // done case SR_SET_INTERFACE: return SR_SetInterface(); // unsupport 6 r& d+ L/ \% U- f( G0 v default: return RESULT_UNSUPPORT; } / ? h* y+ c$ e# B } 0 j; z, M* B+ p3 Z, i8 F) f: \ 下篇将介绍上述的各个请求函数如何响应主机。 |
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设备的枚举(上)