微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 基于STM32的USB枚举过程学习笔记(二)

基于STM32的USB枚举过程学习笔记(二)

时间:11-19 来源:互联网 点击:
接下来介绍USB设备的枚举,枚举就是从设备读取各种描述符信息,这样主机就可以根据这些信息来加载合适的驱动,从而知道是什么样的设备,如何进行通信。枚举过程使用的是控制传输。控制传输可以保证数据的正确性。控制传输分三个过程:建立过程,可选数据过程及状态过程。

下面介绍枚举的详细过程。

USB主机检测到USB设备插入后,就会先对设备复位,并通过一个带数据过程的控制传输完成设备描述符的获取。

第一步,USB主机会往地址0的端点0发送获取设备描述符的标准请求,发送请求属于控制传输的建立过程。建立过程是一个事务。首先是令牌包,即主机发送一个SETUP令牌,令牌的格式如上一篇描述的那样,有令牌的PID,地址和端点号等;其次是数据包,SETUP使用DATA0数据包,数据包中包括标准请求的ID;最后是握手包,设备只能使用ACK来应答,除非出错不应答。下面根据网上找的USB协议分析捕捉的图分析该建立过程。

下面通过STM32官方的USB的例子,自己添加打印信息,查看该控制传输的建立工程中USB主机发送的请求。如上一篇介绍,我们只需根据硬件置的标志位来判断USB传输的状态即可。在usb_istr.c的USB_Istr()函数中,根据中断标志,添加打印信息。在正确传输中断的处理函数CTR_LP()中Setup0_Process()函数表示端点0的建立过程,即上面USB主机复位获取设备描述符将执行的函数。增加打印信息的函数如下:

[cpp]view plaincopy

  1. /*******************************************************************************
  2. *FunctionName:Setup0_Process
  3. *Description:Getthedevicerequestdataanddispatchtoindividualprocess.
  4. *Input:None.
  5. *Output:None.
  6. *Return:Post0_Process.
  7. *******************************************************************************/
  8. uint8_tSetup0_Process(void)
  9. {
  10. union
  11. {
  12. uint8_t*b;
  13. uint16_t*w;
  14. }pBuf;
  15. #ifdefSTM32F10X_CL
  16. USB_OTG_EP*ep;
  17. uint16_toffset=0;
  18. ep=PCD_GetOutEP(ENDP0);
  19. pBuf.b=ep->xfer_buff;
  20. #else
  21. uint16_toffset=1;
  22. pBuf.b=PMAAddr+(uint8_t*)(_GetEPRxAddr(ENDP0)*2);/**2for32bitsaddr*/
  23. #endif/*STM32F10X_CL*/
  24. #ifdefUSB_DEBUG0
  25. printf("\r\nSETUP0中断-->控制传输.建立过程\r\n");
  26. #endif/*#ifUSB_DEBUG0*/
  27. if(pInformation->ControlState!=PAUSE)
  28. {
  29. #ifdefUSB_DEBUG0
  30. printf("设备可以接收新的数据\r\n");
  31. #endif/*USB_DEBUG0*/
  32. pInformation->USBbmRequestType=*pBuf.b++;/*bmRequestType*/
  33. pInformation->USBbRequest=*pBuf.b++;/*bRequest*/
  34. pBuf.w+=offset;/*wordnotaccessedbecauseof32bitsaddressing*/
  35. pInformation->USBwValue=ByteSwap(*pBuf.w++);/*wValue*/
  36. pBuf.w+=offset;/*wordnotaccessedbecauseof32bitsaddressing*/
  37. pInformation->USBwIndex=ByteSwap(*pBuf.w++);/*wIndex*/
  38. pBuf.w+=offset;/*wordnotaccessedbecauseof32bitsaddressing*/
  39. pInformation->USBwLength=*pBuf.w;/*wLength*/
  40. #ifdefUSB_DEBUG0
  41. printf("设备接收数据如下:\r\n");
  42. printf("0x%x",pInformation->USBbmRequestType);//用于指定请求的数据传输反向请求类型请求的接收者
  43. printf("0x%x",pInformation->USBbRequest);//标准请求及代码
  44. printf("0x%x",pInformation->USBwValue0);
  45. printf("0x%x",pInformation->USBwValue1);//具体见圈圈书P77页
  46. printf("0x%x",pInformation->USBwIndex0);
  47. printf("0x%x",pInformation->USBwIndex1);
  48. printf("0x%x",pInformation->USBwLength1);
  49. printf("0x%x",pInformation->USBwLength0);
  50. printf("\r\n");
  51. #endif/*USB_DEBUG0*/
  52. }
  53. returnPost0_Process();
  54. pInformation->ControlState=SETTING_UP;
  55. if(pInformation->USBwLength==0)
  56. {
  57. /*Setupwithnodatastage*/
  58. NoData_Setup0();
  59. }
  60. else
  61. {
  62. /*Setupwithdatastage*/
  63. Data_Setup0();
  64. }
  65. returnPost0_Process();
  66. }

在打印信息之后直接就让函数返回,使主机得不到ACK应答,下面根据打印信息看下测试情况。

根据打印信息,由于从机没有ACK应答给PC机的请求,在PC机尝试发了3次请求后,就放弃了。可以在PC机的设备管理器看到,在请求打印3次以后出现了unknown device。

关于8个字节的请求代码的具体含义请参照USB协议,或者在《圈圈教你玩USB》里面对照。

以上就是枚举过程获取设备描述符的第一步控制传输的建立过程,主机发送获取描述符的请求,下一篇我们将代码中ACK返回,使主机接收到建立过程的应答,从而进入到数据过程,即设备响应主机的请求,将设备描述符发送给主机。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top