请选择 进入手机版 | 继续访问电脑版
    查看: 198|回复: 1

    [单片机资料] 基于STM32的USB枚举过程经验分享

    [复制链接]

    签到天数: 414 天

    [LV.9]元老将成

    发表于 2018-8-10 20:59:42 | 显示全部楼层 |阅读模式

    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主机复位获取设备描述符将执行的函数。增加打印信息的函数如下:

    1. /*******************************************************************************
    2. * Function Name  : Setup0_Process
    3. * Description    : Get the device request data and dispatch to individual process.
    4. * Input          : None.
    5. * Output         : None.
    6. * Return         : Post0_Process.
    7. *******************************************************************************/
    8. uint8_t Setup0_Process(void)
    9. {

    10.   union
    11.   {
    12.     uint8_t* b;
    13.     uint16_t* w;
    14.   } pBuf;

    15. #ifdef STM32F10X_CL
    16.   USB_OTG_EP *ep;
    17.   uint16_t offset = 0;

    18.   ep = PCD_GetOutEP(ENDP0);
    19.   pBuf.b = ep->xfer_buff;
    20. #else  
    21.   uint16_t offset = 1;
    22.   
    23.   pBuf.b = PMAAddr + (uint8_t *)(_GetEPRxAddr(ENDP0) * 2); /* *2 for 32 bits addr */
    24. #endif /* STM32F10X_CL */

    25. #ifdef  USB_DEBUG0
    26.   printf("\r\nSETUP0中断-->控制传输.建立过程\r\n");
    27. #endif /* #if USB_DEBUG0 */

    28.   if (pInformation->ControlState != PAUSE)
    29.   {
    30. #ifdef USB_DEBUG0
    31.     printf("设备可以接收新的数据\r\n");
    32. #endif /* USB_DEBUG0 */
    33.     pInformation->USBbmRequestType = *pBuf.b++; /* bmRequestType */
    34.     pInformation->USBbRequest = *pBuf.b++; /* bRequest */
    35.     pBuf.w += offset;  /* word not accessed because of 32 bits addressing */
    36.     pInformation->USBwValue = ByteSwap(*pBuf.w++); /* wValue */
    37.     pBuf.w += offset;  /* word not accessed because of 32 bits addressing */
    38.     pInformation->USBwIndex  = ByteSwap(*pBuf.w++); /* wIndex */
    39.     pBuf.w += offset;  /* word not accessed because of 32 bits addressing */
    40.     pInformation->USBwLength = *pBuf.w; /* wLength */

    41. #ifdef USB_DEBUG0
    42.     printf("设备接收数据如下:\r\n");
    43.     printf("0x%x ",pInformation->USBbmRequestType);//用于指定请求的 数据传输反向 请求类型 请求的接收者
    44.     printf("0x%x ",pInformation->USBbRequest);//标准请求及代码

    45.     printf("0x%x ",pInformation->USBwValue0);
    46.     printf("0x%x ",pInformation->USBwValue1);//具体见圈圈书P77页

    47.     printf("0x%x ",pInformation->USBwIndex0);
    48.     printf("0x%x ",pInformation->USBwIndex1);  

    49.     printf("0x%x ",pInformation->USBwLength1);
    50.     printf("0x%x ",pInformation->USBwLength0);

    51.     printf("\r\n");
    52. #endif /* USB_DEBUG0 */
    53.   }
    54. return Post0_Process();
    55. pInformation->ControlState = SETTING_UP;
    56.   if (pInformation->USBwLength == 0)
    57.   {
    58.     /* Setup with no data stage */
    59.     NoData_Setup0();
    60.   }
    61.   else
    62.   {
    63.     /* Setup with data stage */
    64.     Data_Setup0();
    65.   }
    66.   return Post0_Process();
    67. }
    复制代码

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



    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    返回顶部