
lbxxx原创 7 T. D; Q7 Y# _7 N5 M) M: \. c - @0 R1 r3 @' ~) g6 F, e! H" E3 | 基于STM32的USB程序开发笔记(一) ; @7 o3 ]8 D% F7 m; r' D 第一篇:需要准备的一些资料 1:STM32的参考手册,这对于设备底层USB的硬件配置以及事件驱动机制的了解尤为重要,你需要了解各个寄存器的功能以及如何操作,比如CNTR、ISTR、EPnR、DADDR等等,如果你想学习USB,这个手册是必须的。 d; M! P5 b- T% F! z( ~ 2:USB2.0 协议,这个资料同样必不可少,如果因为英语阅读能力而苦苦寻找中文版的USB2.0协议,建议不要这么做,现在网络中的所谓的中文版的USB2.0协议不是官方撰写的,大多数是一些热心朋友自己翻译的,却不是很全面,如果你在为寻找这类的资料而无所获时,建议认真塌实的看看官方英文版的USB2.0协议,官方协议阐述的十分详细,650多页,一字一句的了解全部协议不太可行,可针对性的重点理解,比如对第9章USB Device Framework的详细理解对于你的USB Device固件开发不可缺少(这里就是STM32)。 " s: T/ N" i8 G* A8 W 3:ST提供的USB固件库,这个类库较为散乱,但不可不参考 : Q2 E+ h0 u& v$ l4 E# z7 Q 以下是最近这段时间的成果,包含固件、驱动以及应用程序,固件部分有些功能是不被支持的,如SR_SetDescriptor()、 SR_SynchFrame()等等,在此说明战士不支持非故意如此,而是还没时间仔细深入编写完善,因为这些目前不被支持的部分目前不被使用到。 7 C) S1 B/ @4 L$ n 后序将接着对各个部分进行一些说明,希望朋友们多多支持,同时欢迎朋友们讨论。 0 w' ^! x- j0 r6 [7 m+ _: j7 ? 如果你使用的是万利的STM3210B-LK1开发板,则可以烧写hex文件后进行测试。 下载该文件请参阅: 4 G2 R$ h+ m4 ] http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=1808061&bbs_page_no=1&bbs_id=3020 % t1 `3 c9 s3 N9 Q) Z / W4 d8 } `4 H 第2篇:STM32 USB固件函数的驱动原理 首先需要了解一个概念: 2 `# |& @1 l V6 a V- P {5 D USB 设备(DEVICE)从来只是被动触发,USB主机(HOST)掌握主动权,发送什么数据,什么时候发送,是给设备数据还是从设备请求数据,都是由USB 主机完成的,USB设备只是配合主机完成设备的枚举、数据方向和大小。根据数据特性再决定该不该回复该如何回复、该不该接收该如何接收这些动作。 了解这些,再仔细查看STM32的参考手册USB部分以及STM32的中断向量表,从中可以找到两个中断: 7 Y( t- F% y$ M& u# J /******************************************************************************* * Function Name : USB_HP_CAN_TX_IRQHandler " E3 s& A3 D+ e4 L* }1 b: } * Description : This function handles USB High Priority or CAN TX interrupts ( k# C( D: [% }$ U* j0 R * requests. * Input : None " k( y0 h# Y8 R/ A * Output : None ; G& w8 Q/ Z9 w1 E4 [$ a * Return : None *******************************************************************************/ ; k5 _1 Y+ _$ h- ^' |/ ] void USB_HP_CAN_TX_IRQHandler(void) / n, G1 Q/ ?6 S. d- a$ p { {4 K( b& t1 P T4 e6 _( m USB_HPI(); ) Q3 O1 a5 w. R5 w% g# u7 C. `! P } /******************************************************************************* * Function Name : USB_LP_CAN_RX0_IRQHandler * a9 p- D& F& B: ~. [; [ * Description : This function handles USB Low Priority or CAN RX0 interrupts $ ?) H1 J& x7 Q * requests. ) V$ R/ T1 C6 g8 o- i * Input : None * Output : None * _* d1 M0 k: A' b/ ^8 P! t6 h * Return : None ( w! T# o, y: a *******************************************************************************/ 3 C0 ]4 P) Q8 I" ^ void USB_LP_CAN_RX0_IRQHandler(void) { ( A/ d" e& u) e: Z5 g! q) k3 b USB_LPI(); ( ~) X, @( m; z, I } 即 USB的高、低优先权中断处理函数,这也是整个STM32 USB的事件驱动源,USB_HPI()与USB_LPI()既而转向usb_core(.c,.h)进行相关处理。中断传输(interrupt)、控制传输(control)、大流量传输(bulk)由USB_LPI()响应,大流量传输(bulk)同样可能响应USB_HPI(),同步传输 (isochronous)只响应USB_HPI()。 % U/ W1 P" Z3 j# C4 J 这样响应USB的所有请求只需要关注usb_core.c文件中的 USB_LPI()与USB_HPI()函数。由于本人也是对USB刚刚有所了解,因而在本例笔记中USB_HPI()函数未做任何处理,在此开源希望大家能完善与纠正错误并能共享喜悦。以下是USB_LPI()函数: // ***************************************************************************** 7 D6 ]* n1 b2 w( y0 f" l2 M1 H // Function Name : USB_LPI. ) l- m) C- S5 { // Description : Low Priority Interrupt's service routine. - w0 {. D& b5 x( z% `: j( o& h // Input : // Output : // Return : & ]1 m- t& ^1 b5 @$ k4 u // ***************************************************************************** void USB_LPI(void) { ; s( F* b7 E0 j! y unsigned short wValISTR = GetISTR(); & R& {1 y+ t8 @6 V4 A6 w 9 U3 b8 ^& K @4 _( U #if(CNTR_MASK & ISTR_RESET) // Reset if(wValISTR & ISTR_RESET & vwInterruptMask) { , F! t9 n9 p" f9 T- V* O, g& b SetISTR(CLR_RESET); 2 Z, |: W( V! K7 Z3 L INT_ISTR_RESET(); " n0 d( j$ i" A } 1 D6 }5 f% u' E4 T6 I/ U% J; x% e #endif ! J+ N+ |( J1 T1 `# S8 ?; u #if(CNTR_MASK & ISTR_DOVR) // DMA Over/Underrun if(wValISTR & ISTR_DOVR & vwInterruptMask) 8 X9 |# R5 S, ?7 k; L, B. [ { : z/ C, p; p2 Y/ g, z& }5 l SetISTR(CLR_DOVR); : f: O" [" x! o% s INT_ISTR_DOVR(); ) ], r% H' H$ o1 U/ \1 d; U } 0 r, `( n/ Q5 e. u; j2 `) S# P #endif #if(CNTR_MASK & ISTR_ERR) // Error + q- I* H1 x8 p if(wValISTR & ISTR_ERR & vwInterruptMask) { 4 z& j$ U- j9 F, w. O( {9 M8 C SetISTR(CLR_ERR); INT_ISTR_ERROR(); + Q1 ^* G6 M4 V5 E7 u } 8 W* ?$ }) M: W. [8 {$ | #endif * F2 l1 W0 ^) S" {8 @ #if(CNTR_MASK & ISTR_WKUP) // Wakeup if(wValISTR & ISTR_WKUP & vwInterruptMask) ; D! U3 j/ h8 W6 {2 U* d; N- e8 b { SetISTR(CLR_WKUP); 5 e( G9 A/ J8 k: K) B INT_ISTR_WAKEUP(); ) N8 C0 o0 p- A! c9 m. b } #endif . k5 g6 v7 X! f+ O0 E6 C: K9 D' K 1 e8 E/ @; C5 ^5 T #if(CNTR_MASK & ISTR_SUSP) // Suspend ! x6 X/ q/ f `6 o+ X; n if(wValISTR & ISTR_SUSP & vwInterruptMask) { + g* s$ j+ h) `2 v INT_ISTR_SUSPEND(); SetISTR(CLR_SUSP); // must be done after setting of CNTR_FSUSP } #endif % h0 `% \1 G& [! s4 D 1 b" m4 k9 L5 N #if(CNTR_MASK & ISTR_SOF) // Start Of Frame " ~5 U( ~8 m5 D; m7 h ?. I. i5 b if(wValISTR & ISTR_SOF & vwInterruptMask) " g4 J3 q5 j t/ _% M" E { . @) ^: F: R+ D) G SetISTR(CLR_SOF); : w2 b/ b9 S: A3 X, U/ l F8 ? INT_ISTR_SOF(); } #endif ! D6 J. K: J6 j: H7 }0 A- e. c; y #if(CNTR_MASK & ISTR_ESOF) // Expected Start Of Frame + Y, V! W) P/ { if(wValISTR & ISTR_ESOF & vwInterruptMask) { 0 ?0 J- m9 U0 }' ?* m+ X SetISTR(CLR_ESOF); ( e: |* L, p5 r; E/ C/ C# f INT_ISTR_ESOF(); } #endif #if(CNTR_MASK & ISTR_CTR) // Correct Transfer if(wValISTR & ISTR_CTR & vwInterruptMask) 6 ^0 Y. T3 Y7 f1 F { & p' d& l& e, r: W$ z/ {8 Z5 G INT_ISTR_CTR(); U$ h" d6 l5 `( t, \* l } #endif } ' H: j2 P: g( ^9 I // ***************************************************************************** , R6 `/ p$ c' M // Function Name : USB_HPI. 0 p! ^2 }# x M, \ // Description : High Priority Interrupt's service routine. // Input : 5 d& q3 x- g/ F // Output : // Return : // ***************************************************************************** void USB_HPI(void) " O; o$ ]& l3 I$ Z% B1 C: y- W7 d { } 9 B! c; C2 x+ v : g0 a6 R* z( F4 S3 j4 C# `: Y 可以看出,在USB_LPI()函数中,根据STM32 USB的中断状态寄存器(ISTR)的标志位的状态以及定义的USB控制寄存器中断事件屏蔽码,响应各自的中断事件,比如 INT_ISTR_RESET()响应USB的复位中断,一般可在此函数内进行USB的寄存器的初始化;INT_ISTR_CTR()响应一次正确的数据传输中断,故名思意,在完成一次正确的数据传输操作后,就会响应此函数。 具体含义请仔细查阅STM32参考手册,下篇将针对这些响应函数进行逐一的详细介绍。 |
![]() |
谢谢分享 |
最全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设计与实现