STM32 UVC学习笔记1

主机环境:Windows 7 SP1

开发环境:MDK5.18

目标板:STM32F103C8T6

开发库:STM32F1Cube库和STM32_USB_Device_Library

距离之前的STM32 USB学习又过去了N个月,想起最初想学习USB的初衷就是学习一下UVC协议,了解一下图像的传输,在逛STM32社区的时候有看到一句话:以前使用单片机必须熟悉I2C、SPI、UART等通信协议,但现在也必须熟悉USB通信协议了,因为目前主流的设备几乎都是USB接口的,在USB接口上又可以实现I2C、SPI、UART等协议,USB不可谓不强大。废话就到这吧。

经过之前的USB学习,基本上了解了STM32的USB外设,因此开始了USB接口之上的UVC的学习,中间可以说是一波三折,其中芯片还烧坏了一次,又买的新的芯片焊上去的,历史的经验告诉我们,学习一个新的东西,总不是一帆风顺的,UVC全程为USB Video Class--USB视频设备类,用于实现在USB接口上传输视频的功能,目前的UVC规范版本是1.5,可以从USB官网下载,其清单如下:


其中我们需要熟悉的是UVC 1.5 Class Specification文档,USB_Video_Example 1.5文档以及USB_Video_Payload_XX_1.5(一种)文档,由于是初学者因此这里我看的是USB_Video_Payload_MJPEG_1.5文档,也建议大家先学习该文档,毕竟新东西要从简单的开始学起。USB_Video_Example_1.5文档给出了使用MJPEG负载的示例,我们敲代码时可以用到其中的描述符。

UVC规范中说明了一个UVC设备需要实现一个VC(Video Control)接口和若干个VS(Video Streaming)接口,其中VC接口用于控制设备的功能,而VS接口用于传输视频数据流。在最简单的情况下,有一个VC接口和一个VS接口,这就是接下来我们需要实现的。在未熟悉UVC规范的情况下我们也可以把代码框架搭建起来,STM32_USB_Device_Library库是一个很方便扩展的库,因为它把内核和设备类区分出来了,我们要想实现UVC就要新建一个设备类文件夹,刚好UVC和UAC有那么一点类似之处,我们可以把AUDIO中的文件拷贝一份到UVC文件夹下并修改文件名,这样我们就有了usbd_uvc以及usbd_uvc_if文件了,至于usbd_conf,usbd_desc文件只要把之前的VCP例程中的文件稍作修改就可以使用了,这样我们的UVC代码框架就算完成了,在代码实现中就要参看Example文档一步步来完善就可以了,由于是首次学习,UVC的代码框架并不是很好,因此usbd_uvc_if文件其实是没有用到的,在以后再修改吧。因为在实现中,我们只需要把视频流数据发往USB主机即可,没有什么其他的功能要实现,当然在以后有更多功能要求时类接口文件就需要好好实现了,其中usbd_uvc_if.h文件内容如下:

[cpp]  view plain  copy
  1. /** 
  2.   ****************************************************************************** 
  3.   * @file    USB_Device/UVC_Standalone/Inc/usbd_uvc_if.h 
  4.   * @author  MCD Application Team 
  5.   * @version V1.2.0 
  6.   * @date    19-June-2015 
  7.   * @brief   Header for usbd_uvc_if.c file. 
  8.   ****************************************************************************** 
  9.   * @attention 
  10.   * 
  11.   * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2> 
  12.   * 
  13.   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); 
  14.   * You may not use this file except in compliance with the License. 
  15.   * You may obtain a copy of the License at: 
  16.   * 
  17.   *        http://www.st.com/software_license_agreement_liberty_v2 
  18.   * 
  19.   * Unless required by applicable law or agreed to in writing, software  
  20.   * distributed under the License is distributed on an "AS IS" BASIS,  
  21.   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  22.   * See the License for the specific language governing permissions and 
  23.   * limitations under the License. 
  24.   * 
  25.   ****************************************************************************** 
  26.   */   
  27.   
  28. /* Define to prevent recursive inclusion -------------------------------------*/  
  29. #ifndef __USBD_UVC_IF_H  
  30. #define __USBD_UVC_IF_H  
  31.   
  32. /* Includes ------------------------------------------------------------------*/  
  33. #include "usbd_uvc.h"  
  34.   
  35. /* Exported types ------------------------------------------------------------*/  
  36. /* Exported constants --------------------------------------------------------*/  
  37.   
  38. extern USBD_UVC_ItfTypeDef  USBD_UVC_fops;  
  39.   
  40. /* Exported macro ------------------------------------------------------------*/  
  41. /* Exported functions ------------------------------------------------------- */  
  42.   
  43. #endif /* __USBD_UVC_IF_H */  
  44.   
  45. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/  
可以看到文件基本上是空的,而usbd_uvc_if.c文件内容如下:

[cpp]  view plain  copy
  1. /** 
  2.   ****************************************************************************** 
  3.   * @file    usbd_uvc_if.c 
  4.   * @author  MCD Application Team 
  5.   * @version V2.4.1 
  6.   * @date    19-June-2015 
  7.   * @brief   Generic media access Layer. 
  8.   ****************************************************************************** 
  9.   * @attention 
  10.   * 
  11.   * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2> 
  12.   * 
  13.   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); 
  14.   * You may not use this file except in compliance with the License. 
  15.   * You may obtain a copy of the License at: 
  16.   * 
  17.   *        http://www.st.com/software_license_agreement_liberty_v2 
  18.   * 
  19.   * Unless required by applicable law or agreed to in writing, software  
  20.   * distributed under the License is distributed on an "AS IS" BASIS,  
  21.   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  22.   * See the License for the specific language governing permissions and 
  23.   * limitations under the License. 
  24.   * 
  25.   ****************************************************************************** 
  26.   */   
  27.   
  28. /* Includes ------------------------------------------------------------------*/  
  29. #include "main.h"  
  30.   
  31. /** @addtogroup STM32_USB_DEVICE_LIBRARY 
  32.   * @{ 
  33.   */  
  34.   
  35.   
  36. /** @defgroup USBD_UVC  
  37.   * @brief usbd core module 
  38.   * @{ 
  39.   */   
  40.   
  41. /** @defgroup USBD_UVC_Private_TypesDefinitions 
  42.   * @{ 
  43.   */   
  44. /** 
  45.   * @} 
  46.   */   
  47.   
  48.   
  49. /** @defgroup USBD_UVC_Private_Defines 
  50.   * @{ 
  51.   */   
  52. /** 
  53.   * @} 
  54.   */   
  55.   
  56. /** @defgroup USBD_UVC_Private_Macros 
  57.   * @{ 
  58.   */   
  59. /** 
  60.   * @} 
  61.   */   
  62.   
  63.   
  64. /** @defgroup USBD_UVC_Private_FunctionPrototypes 
  65.   * @{ 
  66.   */  
  67.   
  68. static int8_t UVC_Itf_Init     (void);  
  69. static int8_t UVC_Itf_DeInit   (void);  
  70. static int8_t UVC_Itf_Control  (uint8_t cmd, uint8_t* pbuf, uint16_t length);  
  71.   
  72.   
  73. USBD_UVC_ItfTypeDef USBD_UVC_fops =   
  74. {  
  75.   UVC_Itf_Init,  
  76.   UVC_Itf_DeInit,  
  77.   UVC_Itf_Control,  
  78. };  
  79.   
  80. /* TIM handler declaration */  
  81. /* USB handler declaration */  
  82. /* Private functions ---------------------------------------------------------*/  
  83.   
  84. /** 
  85.   * @brief  TEMPLATE_Init 
  86.   *         Initializes the UVC media low layer 
  87.   * @param  None 
  88.   * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL 
  89.   */  
  90. static int8_t UVC_Itf_Init(void)  
  91. {  
  92.   /* 
  93.      Add your initialization code here  
  94.   */    
  95.     
  96.   return (0);  
  97. }  
  98.   
  99. /** 
  100.   * @brief  TEMPLATE_DeInit 
  101.   *         DeInitializes the UVC media low layer 
  102.   * @param  None 
  103.   * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL 
  104.   */  
  105. static int8_t UVC_Itf_DeInit(void)  
  106. {  
  107.   /* 
  108.      Add your deinitialization code here  
  109.   */    
  110.   return (0);  
  111. }  
  112.   
  113.   
  114. /** 
  115.   * @brief  TEMPLATE_Control 
  116.   *         Manage the UVC class requests 
  117.   * @param  Cmd: Command code             
  118.   * @param  Buf: Buffer containing command data (request parameters) 
  119.   * @param  Len: Number of data to be sent (in bytes) 
  120.   * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL 
  121.   */  
  122. static int8_t UVC_Itf_Control  (uint8_t cmd, uint8_t* pbuf, uint16_t length)  
  123. {   
  124.   
  125.   return (0);  
  126. }  
  127.   
  128. /** 
  129.   * @} 
  130.   */   
  131.   
  132. /** 
  133.   * @} 
  134.   */   
  135.   
  136. /** 
  137.   * @} 
  138.   */   
  139.   
  140. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/  
该文件也是空,但我们在UVC类文件中需要用到这个接口(为了日后扩展使用),当然如果闲麻烦的话这两个文件可以直接删除的。代码实现还是从最简单的开始即usbd_desc文件,头文件当然不需要改动了,我们改动的只有usbd_desc.c文件,在该文件中我们改动的也只是描述符而已,如下:

[cpp]  view plain  copy
  1. /** 
  2.   ****************************************************************************** 
  3.   * @file    USB_Device/UVC_Standalone/Src/usbd_desc.c 
  4.   * @author  MCD Application Team 
  5.   * @version V1.2.0 
  6.   * @date    19-June-2015 
  7.   * @brief   This file provides the USBD descriptors and string formating method. 
  8.   ****************************************************************************** 
  9.   * @attention 
  10.   * 
  11.   * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2> 
  12.   * 
  13.   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); 
  14.   * You may not use this file except in compliance with the License. 
  15.   * You may obtain a copy of the License at: 
  16.   * 
  17.   *        http://www.st.com/software_license_agreement_liberty_v2 
  18.   * 
  19.   * Unless required by applicable law or agreed to in writing, software  
  20.   * distributed under the License is distributed on an "AS IS" BASIS,  
  21.   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  22.   * See the License for the specific language governing permissions and 
  23.   * limitations under the License. 
  24.   * 
  25.   ****************************************************************************** 
  26.   */  
  27.   
  28. /* Includes ------------------------------------------------------------------*/  
  29. #include "usbd_core.h"  
  30. #include "usbd_desc.h"  
  31. #include "usbd_conf.h"  
  32.   
  33. /* Private typedef -----------------------------------------------------------*/  
  34. /* Private define ------------------------------------------------------------*/  
  35. #define USBD_VID                      0x1985      
  36. #define USBD_PID                      0x1707      
  37. #define USBD_LANGID_STRING            0x409     //English(United States)  
  38. #define USBD_MANUFACTURER_STRING      "ANOBODYKEY"  
  39. #define USBD_PRODUCT_FS_STRING        "STM32 Video Streaming in FS Mode"  
  40. #define USBD_CONFIGURATION_FS_STRING  "UVC Config"  
  41. #define USBD_INTERFACE_FS_STRING      "UVC Interface"  
  42.   
  43. /* Private macro -------------------------------------------------------------*/  
  44. /* Private function prototypes -----------------------------------------------*/  
  45. uint8_t *USBD_UVC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);  
  46. uint8_t *USBD_UVC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);  
  47. uint8_t *USBD_UVC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);  
  48. uint8_t *USBD_UVC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);  
  49. uint8_t *USBD_UVC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);  
  50. uint8_t *USBD_UVC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);  
  51. uint8_t *USBD_UVC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);  
  52. #ifdef USB_SUPPORT_USER_STRING_DESC  
  53. uint8_t *USBD_UVC_USRStringDesc(USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length);    
  54. #endif /* USB_SUPPORT_USER_STRING_DESC */    
  55.   
  56. /* Private variables ---------------------------------------------------------*/  
  57. USBD_DescriptorsTypeDef UVC_Desc = {  
  58.   USBD_UVC_DeviceDescriptor,  
  59.   USBD_UVC_LangIDStrDescriptor,   
  60.   USBD_UVC_ManufacturerStrDescriptor,  
  61.   USBD_UVC_ProductStrDescriptor,  
  62.   USBD_UVC_SerialStrDescriptor,  
  63.   USBD_UVC_ConfigStrDescriptor,  
  64.   USBD_UVC_InterfaceStrDescriptor,   
  65. };  
  66.   
  67. const uint8_t hUSBDDeviceDesc[USB_LEN_DEV_DESC]= {  
  68.   0x12,                       /* bLength */  
  69.   USB_DESC_TYPE_DEVICE,       /* bDescriptorType */  
  70.   0x00,                       /* bcdUSB */  
  71.   0x02,  
  72.   0xEF,                       /* bDeviceClass */  
  73.   0x02,                       /* bDeviceSubClass */  
  74.   0x01,                       /* bDeviceProtocol */  
  75.   USB_MAX_EP0_SIZE,           /* bMaxPacketSize*/  
  76.   LOBYTE(USBD_VID),           /* idVendor */  
  77.   HIBYTE(USBD_VID),           /* idVendor */  
  78.   LOBYTE(USBD_PID),           /* idVendor */  
  79.   HIBYTE(USBD_PID),           /* idVendor */  
  80.   0x00,                       /* bcdDevice rel. 2.00 */  
  81.   0x02,  
  82.   USBD_IDX_MFC_STR,           /* Index of manufacturer string */  
  83.   USBD_IDX_PRODUCT_STR,       /* Index of product string */  
  84.   USBD_IDX_SERIAL_STR,        /* Index of serial number string */  
  85.   USBD_MAX_NUM_CONFIGURATION  /* bNumConfigurations */  
  86. }; /* USB_DeviceDescriptor */  
  87.   
  88. /* USB Standard Device Descriptor */  
  89. const uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC]= {  
  90.   USB_LEN_LANGID_STR_DESC,           
  91.   USB_DESC_TYPE_STRING,         
  92.   LOBYTE(USBD_LANGID_STRING),  
  93.   HIBYTE(USBD_LANGID_STRING),   
  94. };  
  95.   
  96. uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] =  
  97. {  
  98.   USB_SIZ_STRING_SERIAL,        
  99.   USB_DESC_TYPE_STRING,      
  100. };  
  101.   
  102. uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ];  
  103.   
  104. /* Private functions ---------------------------------------------------------*/  
  105. static void IntToUnicode (uint32_t value , uint8_t *pbuf , uint8_t len);  
  106. static void Get_SerialNum(void);  
  107. /** 
  108.   * @brief  Returns the device descriptor.  
  109.   * @param  speed: Current device speed 
  110.   * @param  length: Pointer to data length variable 
  111.   * @retval Pointer to descriptor buffer 
  112.   */  
  113. uint8_t *USBD_UVC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)  
  114. {  
  115.   *length = sizeof(hUSBDDeviceDesc);  
  116.   return (uint8_t *)hUSBDDeviceDesc;  
  117. }  
  118.   
  119. /** 
  120.   * @brief  Returns the LangID string descriptor.         
  121.   * @param  speed: Current device speed 
  122.   * @param  length: Pointer to data length variable 
  123.   * @retval Pointer to descriptor buffer 
  124.   */  
  125. uint8_t *USBD_UVC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)  
  126. {  
  127.   *length = sizeof(USBD_LangIDDesc);    
  128.   return (uint8_t *)USBD_LangIDDesc;  
  129. }  
  130.   
  131. /** 
  132.   * @brief  Returns the product string descriptor.  
  133.   * @param  speed: Current device speed 
  134.   * @param  length: Pointer to data length variable 
  135.   * @retval Pointer to descriptor buffer 
  136.   */  
  137. uint8_t *USBD_UVC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)  
  138. {  
  139.   USBD_GetString((uint8_t *)USBD_PRODUCT_FS_STRING, USBD_StrDesc, length);      
  140.   return USBD_StrDesc;  
  141. }  
  142.   
  143. /** 
  144.   * @brief  Returns the manufacturer string descriptor.  
  145.   * @param  speed: Current device speed 
  146.   * @param  length: Pointer to data length variable 
  147.   * @retval Pointer to descriptor buffer 
  148.   */  
  149. uint8_t *USBD_UVC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)  
  150. {  
  151.   USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);  
  152.   return USBD_StrDesc;  
  153. }  
  154.   
  155. /** 
  156.   * @brief  Returns the serial number string descriptor.         
  157.   * @param  speed: Current device speed 
  158.   * @param  length: Pointer to data length variable 
  159.   * @retval Pointer to descriptor buffer 
  160.   */  
  161. uint8_t *USBD_UVC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)  
  162. {  
  163.   *length = USB_SIZ_STRING_SERIAL;  
  164.     
  165.   /* Update the serial number string descriptor with the data from the unique ID*/  
  166.   Get_SerialNum();  
  167.     
  168.   return USBD_StringSerial;  
  169. }  
  170.   
  171. /** 
  172.   * @brief  Returns the configuration string descriptor.     
  173.   * @param  speed: Current device speed 
  174.   * @param  length: Pointer to data length variable 
  175.   * @retval Pointer to descriptor buffer 
  176.   */  
  177. uint8_t *USBD_UVC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)  
  178. {  
  179.   USBD_GetString((uint8_t *)USBD_CONFIGURATION_FS_STRING, USBD_StrDesc, length);   
  180.   return USBD_StrDesc;    
  181. }  
  182.   
  183. /** 
  184.   * @brief  Returns the interface string descriptor.         
  185.   * @param  speed: Current device speed 
  186.   * @param  length: Pointer to data length variable 
  187.   * @retval Pointer to descriptor buffer 
  188.   */  
  189. uint8_t *USBD_UVC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)  
  190. {  
  191.   USBD_GetString((uint8_t *)USBD_INTERFACE_FS_STRING, USBD_StrDesc, length);  
  192.   return USBD_StrDesc;    
  193. }  
  194.   
  195. /** 
  196.   * @brief  Create the serial number string descriptor  
  197.   * @param  None  
  198.   * @retval None 
  199.   */  
  200. static void Get_SerialNum(void)  
  201. {  
  202.   uint32_t deviceserial0, deviceserial1, deviceserial2;  
  203.     
  204.   deviceserial0 = *(uint32_t*)DEVICE_ID1;  
  205.   deviceserial1 = *(uint32_t*)DEVICE_ID2;  
  206.   deviceserial2 = *(uint32_t*)DEVICE_ID3;  
  207.     
  208.   deviceserial0 += deviceserial2;  
  209.     
  210.   if (deviceserial0 != 0)  
  211.   {  
  212.     IntToUnicode (deviceserial0, &USBD_StringSerial[2] ,8);  
  213.     IntToUnicode (deviceserial1, &USBD_StringSerial[18] ,4);  
  214.   }  
  215. }  
  216.   
  217. /** 
  218.   * @brief  Convert Hex 32Bits value into char  
  219.   * @param  value: value to convert 
  220.   * @param  pbuf: pointer to the buffer  
  221.   * @param  len: buffer length 
  222.   * @retval None 
  223.   */  
  224. static void IntToUnicode (uint32_t value , uint8_t *pbuf , uint8_t len)  
  225. {  
  226.   uint8_t idx = 0;  
  227.     
  228.   for( idx = 0 ; idx < len ; idx ++)  
  229.   {  
  230.     if( ((value >> 28)) < 0xA )  
  231.     {  
  232.       pbuf[ 2* idx] = (value >> 28) + '0';  
  233.     }  
  234.     else  
  235.     {  
  236.       pbuf[2* idx] = (value >> 28) + 'A' - 10;   
  237.     }  
  238.       
  239.     value = value << 4;  
  240.       
  241.     pbuf[ 2* idx + 1] = 0;  
  242.   }  
  243. }  
  244.   
  245. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/  
这是从之前的VCP例程中的文件修改过来的,其中VID和PID自己随便修改吧,其中的设备描述符就需要我们注意了,这里面的内容就是我从Example文件中拷贝的,Example文档中提供了2个示例,这里我参考的是第一个示例Destop Video Camera Example,当然参考哪个示例都是可以的,该示例的框架图如下所示:




图中的概念缩写大家可以去看UVC1.5的协议规范,都有介绍的,该图只是作为参考,我在实现中省略了很多中间环节的,为了简洁而已。设备描述符的简介如下:


可以看到代码中的实现跟示例是一致的,接下来就是配置描述符,也是重中之重,也是我们修改较多的地方,描述符如下

[cpp]  view plain  copy
  1. /* USB UVC device Configuration Descriptor */  
  2. static uint8_t USBD_UVC_CfgDesc[USB_UVC_CONFIG_DESC_SIZ] =  
  3. {  
  4.   /*Configuration Descriptor*/    
  5.   0x09, /* bLength: Configuation Descriptor size */  
  6.   USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */  
  7.   LOBYTE(USB_UVC_CONFIG_DESC_SIZ),     /* wTotalLength: Bytes returned */  
  8.   HIBYTE(USB_UVC_CONFIG_DESC_SIZ),  
  9.   0x02,         /*bNumInterfaces: 2 interface*/  
  10.   0x01,         /*bConfigurationValue: Configuration value*/  
  11.   USBD_IDX_CONFIG_STR,         /*iConfiguration: Index of string descriptor describing the configuration*/  
  12.   0x80,         /*bmAttributes: bus powered device */  
  13.   0xFA,         /*MaxPower 500 mA: this current is used for detecting Vbus*/  
  14.   /* 09 */  
  15.   /*---------------------------------------------------------------------------*/  
  16.   
  17.   /*Interface Association Descriptor*/  
  18.   0x08, /* bLength: Interface Association Descriptor size */  
  19.   USB_DESC_TYPE_INTERFACE_ASSOCIATION, /* bDescritorType: Interface Association */  
  20.   0x00,         /* bFirstInterface: VideoControl Interface ID */  
  21.   0x02,         /* bInterfaceCount: 2 Video Interface */  
  22.   0x0E,         /* bFunctionClass: CC_VIDEO */  
  23.   0x03,         /* bFunctionSubClass: SC_VIDEO_INTERFACE_COLLECTION */  
  24.   0x00,         /* bFunctionProtocol: PC_PROTOCOL_UNDEFINED */  
  25.   USBD_IDX_INTERFACE_STR,           /* iFunction: Index of string descriptor descripting the function */  
  26.   
  27.   /*Standard VC Interface Descriptor*/  
  28.   0x09, /* bLenght: Standard VC Interface Descriptor size */  
  29.   USB_DESC_TYPE_INTERFACE,  /*bDescriptorType: interface */  
  30.   0x00,         /* bInterfaceNumber: interface ID */  
  31.   0x00,         /* bAlternateSetting: Alternate setting */  
  32.   0x00,         /* bNumEndpoints: no endpoint */  
  33.   0x0E,         /* bInterfaceClass: CC_VIDEO */  
  34.   0x01,         /* bInterfaceSubClass: SC_VIDEOCONTROL */  
  35.   0x00,         /* bInterfacePortocol: PC_PROTOCOL_15 */  
  36.   USBD_IDX_INTERFACE_STR,           /*iInterface: Index of string descriptor descripting the interface */  
  37.   
  38.   /*Class-specific VC Interface Header Descriptor*/  
  39.   0x0D, /* bLength: Class-specific VC Interface Header Descriptor size */  
  40.   0x24,         /* bDescriptorType: CS_INTERFACE */  
  41.   0x01,         /* bDescriptorSubType: VC_HEADER */  
  42.   0x10,         /* bcdUVC: UVC1.5 revision */  
  43.   0x01,  
  44.   0x27,         /* wTotalLength: total size of class-specific descriptors */  
  45.   0x00,  
  46.   0x80,         /* dwClockFrequency: deprecated */  
  47.   0x8D,  
  48.   0x5B,  
  49.   0x00,  
  50.   0x01,         /* bInCollection: number of streaming interfaces */  
  51.   0x01,         /* baInterfaceNr(1): VideoStreaming interface 1 belongs to VC interface */  
  52.   
  53.   /*Input Terminal Descriptor Composite*/  
  54.   0x11, /* bLength: Input Terminal Descriptor size */  
  55.   0x24,         /* bDescriptorType: CS_INTERFACE */  
  56.   0x02,         /* bDescriptorSubType: VC_INPUT_TERMINAL */  
  57.   0x01,         /* bTerminalID: Terminal ID */  
  58.   0x01,         /* wTerminalType: ITT_CAMERA */  
  59.   0x02,  
  60.   0x00,         /* bAssocTerminal: no association */  
  61.   0x00,         /*iTerminal: index of string descriptor descripting the terminal */  
  62.   0x00,         /* wObjectiveFocalLengthMin: No optical zoom supported */  
  63.   0x00,  
  64.   0x00,         /* wObjectiveFocalLengthMax: No optical zoom supported */  
  65.   0x00,  
  66.   0x00,         /* wOcularFocalLength: No optical zoom supported */  
  67.   0x00,  
  68.   0x02,         /* bControlSize: this terminal doesn't implement any controls */  
  69.   0x00,         /* bmControls: No controls are supported */  
  70.   0x00,  
  71.   
  72.   /*Output Terminal Descriptor*/  
  73.   0x09, /* bLength: Output Terminal Descriptor size */  
  74.   0x24,         /* bDescriptorType: CS_INTERFACE */  
  75.   0x03,         /* bDescriptorSubType: VC_OUTPUT_TERMINAL */  
  76.   0x02,         /* bTerminalID: Terminal ID */  
  77.   0x01,         /* wTerminalType: TT_STREAMING */  
  78.   0x01,  
  79.   0x00,         /* bAssocTerminal: no association */  
  80.   0x01,         /* bSourceID: connect to the input terminal output pin */  
  81.   0x00,         /*iTerminal: index of string descriptor descripting the terminal */  
  82.   
  83.   /*---------------------------------------------------------------------------*/     
  84.   /*Standard VS Interface Alternate 0 setting Descriptor*/  
  85.   0x09, /* bLength: Standard VS Interface Descriptor size */  
  86.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: INTERFACE */  
  87.   0x01,         /* bInterfaceNumber: Interface ID */  
  88.   0x00,         /* bAlternateSetting: index of this alternate setting */  
  89.   0x00,         /* bNumEndpoints: 0 endpoint */  
  90.   0x0E,         /* bInterfaceClass: CC_VIDEO */  
  91.   0x02,         /* bInterfaceSubClass: SC_VIDEOSTREAMING */  
  92.   0x00,         /* bInterfaceProtocol: PC_PROTOCOL_15 */  
  93.   USBD_IDX_INTERFACE_STR,           /*iInterface: Index of string descriptor descripting the interface */  
  94.   
  95.   /*Class-specific VS Header Descriptor*/  
  96.   0x0E, /* bLength: Class-specific VS Header Descriptor size */  
  97.   0x24,         /* bDescriptorType: CS_INTERFACE */  
  98.   0x01,         /* bDescriptorSubType: VS_INPUT_HEADER */  
  99.   0x01,         /* bNumFormats: one format descriptor follows */  
  100.   0x3F,//0x45,          /* wTotalLength: Total size of class-specific VS interface descriptors */  
  101.   0x00,  
  102.   UVC_ISO_DATA_EP,          /* bEndpointAddress: address of isochronour video data endpoint */  
  103.   0x00,         /* bmInfo: no dynamic format change supported */  
  104.   0x02,         /* bTerminalLink: the terminal ID of output Terminal */  
  105.   0x00,         /* bStillCaptureMethod: no supports still image capture method */  
  106.   0x00,         /* bTriggerSupport: no supports hardware trigger */  
  107.   0x00,         /* bTriggerUsage: initiate still image capture */  
  108.   0x01,         /* bControlSize: the size of bmaControls field */  
  109.   0x00,         /* bmaControls: no VS specific controls are supported */  
  110.   
  111.   /*Payload Format Descriptor*/  
  112.   0x0B, /* blength: Payload Format Descriptor size */  
  113.   0x24,         /* bDescriptorType: CS_INTERFACE */  
  114.   0x06,         /* bDescriptorSubType: VS_FORMAT_MJPEG */  
  115.   0x01,         /* bFormatIndex: index of the format descriptor */  
  116.   0x01,         /* bNumFrameDescriptor: number of frame descriptors */  
  117.   0x01,         /* bmFlags: FixedSizeSamples */  
  118.   0x01,         /* bDefaultFrameIndex: */  
  119.   0x00,         /* bAspectRatioX: not required */  
  120.   0x00,         /* bAspectRatioY: not required */  
  121.   0x00,         /* bInterlaceFlags: non-interlaced stream */  
  122.   0x00,         /* bCopyProtect: no restrictions */  
  123.   
  124.   /*Class-specific VS Frame Descriptor*/  
  125.   0x26, /* bLength: Class-specific VS Frame Descriptor size */  
  126.   0x24,         /* bDescriptorType: CS_INTERFACE */  
  127.   0x07,         /* bDescriptorSubType: VS_FRAME_MJPEG */  
  128.   0x01,         /* bFrameIndex: index of frame descriptor */  
  129.   0x02,         /* bmCapabilities:still image capture method 0 supported,fixed frame-rate */  
  130.   0x80,         /* wWidth: frame width */  
  131.   0x00,  
  132.   0xA0,         /* wHeight: frame height */  
  133.   0x00,  
  134.   0x00,         /* dwMinBitRate: */  
  135.   0xB0,  
  136.   0x04,  
  137.   0x00,  
  138.   0x00,         /* dwMaxBitRate: */  
  139.   0x00,  
  140.   0x4B,  
  141.   0x00,  
  142.   0x00,         /* dwMaxVideoFrameBufSize: in bytes */  
  143.   0xA0,  
  144.   0x00,  
  145.   0x00,  
  146.   0x2A,         /* dwDefaultFrameInterval: */  
  147.   0x2C,  
  148.   0x0A,  
  149.   0x00,  
  150.   0x00,         /* bFrameIntervalType: Continuous frame interval */  
  151.   0x2A,         /* dwMinFrameInterval: */  
  152.   0x2C,  
  153.   0x0A,  
  154.   0x00,  
  155.   0x2A,         /* dwMaxFrameInterval: */  
  156.   0x2C,  
  157.   0x0A,  
  158.   0x00,  
  159.   0x00,         /* dwFrameIntervalSetp: no frame interval step supported */  
  160.   0x00,  
  161.   0x00,  
  162.   0x00,  
  163.    
  164.   /*---------------------------------------------------------------------------*/     
  165.   /*Standard VS Interface  Alternate setting 1 Descriptor*/  
  166.   0x09, /* bLength: Standard VS Interface Descriptor size */  
  167.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: INTERFACE */  
  168.   0x01,         /* bInterfaceNumber: Interface ID */  
  169.   0x01,         /* bAlternateSetting: index of this alternate setting */  
  170.   0x01,         /* bNumEndpoints: 1 endpoint */  
  171.   0x0E,         /* bInterfaceClass: CC_VIDEO */  
  172.   0x02,         /* bInterfaceSubClass: SC_VIDEOSTREAMING */  
  173.   0x00,         /* bInterfaceProtocol: PC_PROTOCOL_15 */  
  174.   USBD_IDX_INTERFACE_STR,           /*iInterface: Index of string descriptor descripting the interface */  
  175.   
  176.   /*Endpoint Descriptor*/  
  177.   0x07, /* bLength: Endpoint Descriptor size */  
  178.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: ENDPOINT */  
  179.   UVC_ISO_DATA_EP,          /* bEndpointAddress: address of isochronour video data endpoint */  
  180.   0x05,         /* bmAttributes: Isochronous transfer Asynchronous data type */  
  181.   LOBYTE(UVC_ISO_DATA_PACKET_SIZE),     /* wMaxPacketSize: */  
  182.   HIBYTE(UVC_ISO_DATA_PACKET_SIZE),   
  183.   0x01,         /* bInterval: */  
  184.   /**********  Descriptor of UVC interface 0 Alternate setting 0 **************/    
  185.    
  186. };  
对比之前的拓扑图就可以知道这里使用到了CT(相机终端),去掉了SU(选择单元)和PU(处理单元),CT直接连至OT(输出终端),这里虽然是参考的UVC1.5的文档,但最后我给改成了UVC1.1,UVC1.5其实和UVC1.1相差不多,可以使用UVCView软件来检查描述符是否正确,配置的具体含义看代码中的注释即可明白。目前UVCView只能检查UVC1.1协议,如果使用的是UVC1.5协议,该软件会提示错误,但其实并没有错误。这里是使用端点0作为默认的控制端点,使用端点1来发送视频数据流,且端点配置成同步端点。端点大小的取值在后面会解释,这里需要注意的是使用同步端点的话就一定要使用两种接口配置,默认情况下使用接口配置0,默认接口配置中不能包含数据负载非0的同步端点,只能在交替配置中包含同步端点,关于USB不同的传输类型的详细说明可以查看USB2.0协议规范的第5章节,该章节我可是仔细阅读了一下,还试着翻译了一下便于理解。也希望大家可以看看该章节以便对各个传输类型有所了解。STM32的USB模块支持全速模式即通信速率为12MBit/s,也就是1.5MByte/s,由于我的单板啥外设也没得,因此图像数据只能存储在单片机中,从STM32F1Cube中找了一张128*160的图片,来实现以15fps帧传输该图片到USB主机,该图片经过压缩成jpeg格式大概为9K字节,每秒15帧的话也就是每秒传输9K*15=135K字节,USB2.0全速模式下把1S分成了1000个微帧,即1ms为一个微帧,视频数据流在微帧内传输,全速设备在每个微帧内可以进行一次同步传输,由此得知,一次微帧我们需要传输135个字节,这里我把同步端点的最大包大小设置成150字节,足以传输这张图片了,有关为什么这里是那一张JPEG图片来传输可以查看USB_Video_Payload_MJPEG文档,MJPEG就是把一幅幅JPEG格式的帧连续的播放,因此为了简介,这里就是把一张JPEG图片连续发送到USB主机。对了,在配置描述符中有用到一个接口连接描述符,在USB设备库中是没有定义,因此把该定义加到USB设备库中,即usbd_def.h文件中,如下:

[cpp]  view plain  copy
  1. #define  USB_DESC_TYPE_DEVICE                              1  
  2. #define  USB_DESC_TYPE_CONFIGURATION                       2  
  3. #define  USB_DESC_TYPE_STRING                              3  
  4. #define  USB_DESC_TYPE_INTERFACE                           4  
  5. #define  USB_DESC_TYPE_ENDPOINT                            5  
  6. #define  USB_DESC_TYPE_DEVICE_QUALIFIER                    6  
  7. #define  USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION           7  
  8. #define  USB_DESC_TYPE_BOS                                 0x0F  
  9. #define  USB_DESC_TYPE_INTERFACE_ASSOCIATION               11  
至此,我们知道了所用的端点数:2个,端点类型:一个控制端点和一个同步端点,我们就可以修改usbd_conf文件了,usbd_conf.h文件如下:

[cpp]  view plain  copy
  1. /** 
  2.   ****************************************************************************** 
  3.   * @file    USB_Device/UVC_Standalone/Inc/usbd_conf.h 
  4.   * @author  MCD Application Team 
  5.   * @version V1.2.0 
  6.   * @date    19-June-2015 
  7.   * @brief   General low level driver configuration 
  8.   ****************************************************************************** 
  9.   * @attention 
  10.   * 
  11.   * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2> 
  12.   * 
  13.   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); 
  14.   * You may not use this file except in compliance with the License. 
  15.   * You may obtain a copy of the License at: 
  16.   * 
  17.   *        http://www.st.com/software_license_agreement_liberty_v2 
  18.   * 
  19.   * Unless required by applicable law or agreed to in writing, software  
  20.   * distributed under the License is distributed on an "AS IS" BASIS,  
  21.   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  22.   * See the License for the specific language governing permissions and 
  23.   * limitations under the License. 
  24.   * 
  25.   ****************************************************************************** 
  26.   */  
  27.   
  28. /* Define to prevent recursive inclusion -------------------------------------*/  
  29. #ifndef __USBD_CONF_H  
  30. #define __USBD_CONF_H  
  31.   
  32. /* Includes ------------------------------------------------------------------*/  
  33. #include "stm32f1xx_hal.h"  
  34. #include <stdio.h>  
  35. #include <stdlib.h>  
  36. #include <string.h>  
  37.   
  38. /* Exported types ------------------------------------------------------------*/  
  39. /* Exported constants --------------------------------------------------------*/  
  40. /* Common Config */  
  41. #define USBD_MAX_NUM_INTERFACES               1  
  42. #define USBD_MAX_NUM_CONFIGURATION            1  
  43. #define USBD_MAX_STR_DESC_SIZ                 0x100  
  44. #define USBD_SUPPORT_USER_STRING              0   
  45. #define USBD_SELF_POWERED                     0  
  46. #define USBD_DEBUG_LEVEL                      0  
  47.   
  48. /* VIDEO Class Config */  
  49. #define USBD_VIDEO_FPS                        15  
  50. #define ENDP1_BUF0ADDR                        (0xC0)  
  51. #define ENDP1_BUF1ADDR                        (0xC0)  
  52. #define VIDEO_IN_TX_ADDRESS                   (ENDP1_BUF0ADDR | (ENDP1_BUF1ADDR<<16))   
  53.   
  54. /* Exported macro ------------------------------------------------------------*/  
  55. /* Memory management macros */     
  56.   
  57. /* For footprint reasons and since only one allocation is handled in the AUDIO class  
  58.    driver, the malloc/free is changed into a static allocation method */  
  59.   
  60. void *USBD_static_malloc(uint32_t size);  
  61. void USBD_static_free(void *p);  
  62.   
  63. #define MAX_STATIC_ALLOC_SIZE     40 /*Video Class Driver Structure size*/  
  64.   
  65. #define USBD_malloc              (uint32_t *)USBD_static_malloc  
  66. #define USBD_free                 USBD_static_free  
  67. #define USBD_memset               /* Not used */  
  68. #define USBD_memcpy               /* Not used */  
  69.   
  70. /* DEBUG macros */    
  71. #if (USBD_DEBUG_LEVEL > 0)  
  72. #define  USBD_UsrLog(...)   printf(__VA_ARGS__);\  
  73.                             printf("\n");  
  74. #else  
  75. #define USBD_UsrLog(...)  
  76. #endif  
  77.   
  78. #if (USBD_DEBUG_LEVEL > 1)  
  79.   
  80. #define  USBD_ErrLog(...)   printf("ERROR: ") ;\  
  81.                             printf(__VA_ARGS__);\  
  82.                             printf("\n");  
  83. #else  
  84. #define USBD_ErrLog(...)  
  85. #endif  
  86.   
  87. #if (USBD_DEBUG_LEVEL > 2)  
  88. #define  USBD_DbgLog(...)   printf("DEBUG : ") ;\  
  89.                             printf(__VA_ARGS__);\  
  90.                             printf("\n");  
  91. #else  
  92. #define USBD_DbgLog(...)  
  93. #endif  
  94.   
  95. /* Exported functions ------------------------------------------------------- */  
  96.   
  97. #endif /* __USBD_CONF_H */  
  98.   
  99. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/  
该文件修改不大,首先是修改端点的缓冲区地址,这里是参考UAC文件来修改的,使用双缓冲,因为STM32在把端点配置成同步端点时就自动启用了双缓冲,一开始我还想着,不使用双缓冲而使用单缓冲结构发送视频数据流,结果在测试时一直有包相同的数据跟在我发送的有效数据后面,后来在查看STM32F103C8T6参考文档时才发现,使用同步端点必须要使用双缓冲,因此,这里要配置BUF0和BUF1地址,这两个地址配成一样或不一样都不影响,因为Cube库中只对外提供了一个接口USBD_LL_Transmit,因此在USB模块使用其中一个缓冲时,应用程序也无法灵活使用另一段缓冲,再有一个修改就是MAX_STATIC_ALLOC_SIZE把值改小了,因为这里是把数据发往USB主机并不需要接口很多数据,因此,UVC的类结构并不需要使用太多的内存,usbd_conf.c文件如下:

[cpp]  view plain  copy
  1. /** 
  2.   ****************************************************************************** 
  3.   * @file    USB_Device/UVC_Standalone/Src/usbd_conf.c 
  4.   * @author  MCD Application Team 
  5.   * @version V1.2.0 
  6.   * @date    31-July-2015 
  7.   * @brief   This file implements the USB Device library callbacks and MSP 
  8.   ****************************************************************************** 
  9.   * @attention 
  10.   * 
  11.   * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2> 
  12.   * 
  13.   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); 
  14.   * You may not use this file except in compliance with the License. 
  15.   * You may obtain a copy of the License at: 
  16.   * 
  17.   *        http://www.st.com/software_license_agreement_liberty_v2 
  18.   * 
  19.   * Unless required by applicable law or agreed to in writing, software  
  20.   * distributed under the License is distributed on an "AS IS" BASIS,  
  21.   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  22.   * See the License for the specific language governing permissions and 
  23.   * limitations under the License. 
  24.   * 
  25.   ****************************************************************************** 
  26.   */  
  27.   
  28. /* Includes ------------------------------------------------------------------*/  
  29. #include "main.h"  
  30.   
  31. /* Private typedef -----------------------------------------------------------*/  
  32. /* Private define ------------------------------------------------------------*/  
  33. /* Private macro -------------------------------------------------------------*/  
  34. /* Private variables ---------------------------------------------------------*/  
  35. PCD_HandleTypeDef hpcd;  
  36.   
  37. /* Private function prototypes -----------------------------------------------*/  
  38. /* Private functions ---------------------------------------------------------*/  
  39.   
  40. /******************************************************************************* 
  41.                        PCD BSP Routines 
  42. *******************************************************************************/  
  43.   
  44. /** 
  45.   * @brief  Initializes the PCD MSP. 
  46.   * @param  hpcd: PCD handle 
  47.   * @retval None 
  48.   */  
  49. void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)  
  50. {  
  51.   GPIO_InitTypeDef  GPIO_InitStruct;  
  52.      
  53.   /* Enable the GPIOA clock */  
  54.   __HAL_RCC_GPIOA_CLK_ENABLE();  
  55.     
  56.   /* Configure USB DM/DP pins */  
  57.   GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);  
  58.   GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT;  
  59.   GPIO_InitStruct.Pull = GPIO_PULLUP;  
  60.   GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;  
  61.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);  
  62.     
  63.   /* Enable USB Clock */  
  64.   __HAL_RCC_USB_CLK_ENABLE();  
  65.       
  66.   /* Set USB Interrupt priority */  
  67.   HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 7, 0);  
  68.   
  69.   /* Enable USB Interrupt */  
  70.   HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);  
  71. }  
  72.   
  73. /** 
  74.   * @brief  De-Initializes the PCD MSP. 
  75.   * @param  hpcd: PCD handle 
  76.   * @retval None 
  77.   */  
  78. void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)  
  79. {  
  80.   /* Disable USB FS Clock */  
  81.   __HAL_RCC_USB_CLK_DISABLE();  
  82. }  
  83.   
  84. /******************************************************************************* 
  85.                        LL Driver Callbacks (PCD -> USB Device Library) 
  86. *******************************************************************************/  
  87.   
  88. /** 
  89.   * @brief  SetupStage callback. 
  90.   * @param  hpcd: PCD handle 
  91.   * @retval None 
  92.   */  
  93. void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)  
  94. {  
  95.   USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup);  
  96. }  
  97.   
  98. /** 
  99.   * @brief  DataOut Stage callback. 
  100.   * @param  hpcd: PCD handle 
  101.   * @param  epnum: Endpoint Number 
  102.   * @retval None 
  103.   */  
  104. void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)  
  105. {  
  106.   USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);  
  107. }  
  108.   
  109. /** 
  110.   * @brief  DataIn Stage callback. 
  111.   * @param  hpcd: PCD handle 
  112.   * @param  epnum: Endpoint Number 
  113.   * @retval None 
  114.   */  
  115. void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)  
  116. {  
  117.   USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);  
  118. }  
  119.   
  120. /** 
  121.   * @brief  SOF callback. 
  122.   * @param  hpcd: PCD handle 
  123.   * @retval None 
  124.   */  
  125. void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)  
  126. {  
  127.   USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData);  
  128. }  
  129.   
  130. /** 
  131.   * @brief  Reset callback. 
  132.   * @param  hpcd: PCD handle 
  133.   * @retval None 
  134.   */  
  135. void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)  
  136. {  
  137.   USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, USBD_SPEED_FULL);  
  138.   /* Reset Device */  
  139.   USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData);  
  140. }  
  141.   
  142. /** 
  143.   * @brief  Suspend callback. 
  144.   * @param  hpcd: PCD handle 
  145.   * @retval None 
  146.   */  
  147. void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)  
  148. {  
  149.   /* Inform USB library that core enters in suspend Mode */  
  150.   USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData);  
  151. }  
  152.   
  153. /** 
  154.   * @brief  Resume callback. 
  155.   * @param  hpcd: PCD handle 
  156.   * @retval None 
  157.   */  
  158. void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)  
  159. {  
  160.   USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData);  
  161. }  
  162.   
  163. /** 
  164.   * @brief  ISOOUTIncomplete callback. 
  165.   * @param  hpcd: PCD handle 
  166.   * @param  epnum: Endpoint Number 
  167.   * @retval None 
  168.   */  
  169. void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)  
  170. {  
  171.   USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);  
  172. }  
  173.   
  174. /** 
  175.   * @brief  ISOINIncomplete callback. 
  176.   * @param  hpcd: PCD handle 
  177.   * @param  epnum: Endpoint Number 
  178.   * @retval None 
  179.   */  
  180. void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)  
  181. {  
  182.   USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);  
  183. }  
  184.   
  185. /** 
  186.   * @brief  ConnectCallback callback. 
  187.   * @param  hpcd: PCD handle 
  188.   * @retval None 
  189.   */  
  190. void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)  
  191. {  
  192.   USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData);  
  193. }  
  194.   
  195. /** 
  196.   * @brief  Disconnect callback. 
  197.   * @param  hpcd: PCD handle 
  198.   * @retval None 
  199.   */  
  200. void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)  
  201. {  
  202.   USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData);  
  203. }  
  204.   
  205. /******************************************************************************* 
  206.                        LL Driver Interface (USB Device Library --> PCD) 
  207. *******************************************************************************/  
  208.   
  209. /** 
  210.   * @brief  Initializes the Low Level portion of the Device driver. 
  211.   * @param  pdev: Device handle 
  212.   * @retval USBD Status 
  213.   */  
  214. USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)  
  215. {  
  216.   /* Set LL Driver parameters */  
  217.   hpcd.Instance = USB;  
  218.   hpcd.Init.dev_endpoints = 8;  //STM32F103C8T6支持8个双向端点  
  219.   hpcd.Init.ep0_mps = PCD_EP0MPS_64;    //端点0支持的最大分组字节为64  
  220.   hpcd.Init.phy_itface = PCD_PHY_EMBEDDED;  
  221.   hpcd.Init.speed = PCD_SPEED_FULL;     //USB2.0全速设备  
  222.   hpcd.Init.low_power_enable = 0;   //不使能低功耗模式  
  223.     
  224.   /* Link The driver to the stack */  
  225.   hpcd.pData = pdev;  
  226.   pdev->pData = &hpcd;  
  227.     
  228.   /* Initialize LL Driver */  
  229.   HAL_PCD_Init((PCD_HandleTypeDef*)pdev->pData);  
  230.   
  231.   HAL_PCDEx_PMAConfig(pdev->pData , 0x00 , PCD_SNG_BUF, 0x40);   //OUT端点  
  232.   HAL_PCDEx_PMAConfig(pdev->pData , 0x80 , PCD_SNG_BUF, 0x80);   //IN端点  
  233.   HAL_PCDEx_PMAConfig(pdev->pData , UVC_ISO_DATA_EP, PCD_DBL_BUF, VIDEO_IN_TX_ADDRESS);  
  234.   
  235.   return USBD_OK;  
  236. }  
  237.   
  238. /** 
  239.   * @brief  De-Initializes the Low Level portion of the Device driver. 
  240.   * @param  pdev: Device handle 
  241.   * @retval USBD Status 
  242.   */  
  243. USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)  
  244. {  
  245.   HAL_PCD_DeInit((PCD_HandleTypeDef*)pdev->pData);  
  246.   return USBD_OK;  
  247. }  
  248.   
  249. /** 
  250.   * @brief  Starts the Low Level portion of the Device driver. 
  251.   * @param  pdev: Device handle 
  252.   * @retval USBD Status 
  253.   */  
  254. USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)  
  255. {  
  256.   HAL_PCD_Start((PCD_HandleTypeDef*)pdev->pData);  
  257.   return USBD_OK;  
  258. }  
  259.   
  260. /** 
  261.   * @brief  Stops the Low Level portion of the Device driver. 
  262.   * @param  pdev: Device handle 
  263.   * @retval USBD Status 
  264.   */  
  265. USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev)  
  266. {  
  267.   HAL_PCD_Stop((PCD_HandleTypeDef*)pdev->pData);  
  268.   return USBD_OK;  
  269. }  
  270.   
  271. /** 
  272.   * @brief  Opens an endpoint of the Low Level Driver. 
  273.   * @param  pdev: Device handle 
  274.   * @param  ep_addr: Endpoint Number 
  275.   * @param  ep_type: Endpoint Type 
  276.   * @param  ep_mps: Endpoint Max Packet Size 
  277.   * @retval USBD Status 
  278.   */  
  279. USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev,  
  280.                                   uint8_t ep_addr,  
  281.                                   uint8_t ep_type,  
  282.                                   uint16_t ep_mps)  
  283. {  
  284.   HAL_PCD_EP_Open((PCD_HandleTypeDef*)pdev->pData,  
  285.                   ep_addr,  
  286.                   ep_mps,  
  287.                   ep_type);  
  288.   
  289.   return USBD_OK;  
  290. }  
  291.   
  292. /** 
  293.   * @brief  Closes an endpoint of the Low Level Driver. 
  294.   * @param  pdev: Device handle 
  295.   * @param  ep_addr: Endpoint Number 
  296.   * @retval USBD Status 
  297.   */  
  298. USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)  
  299. {  
  300.   HAL_PCD_EP_Close((PCD_HandleTypeDef*)pdev->pData, ep_addr);  
  301.   return USBD_OK;  
  302. }  
  303.   
  304. /** 
  305.   * @brief  Flushes an endpoint of the Low Level Driver. 
  306.   * @param  pdev: Device handle 
  307.   * @param  ep_addr: Endpoint Number 
  308.   * @retval USBD Status 
  309.   */  
  310. USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)  
  311. {  
  312.   HAL_PCD_EP_Flush((PCD_HandleTypeDef*)pdev->pData, ep_addr);  
  313.   return USBD_OK;  
  314. }  
  315.   
  316. /** 
  317.   * @brief  Sets a Stall condition on an endpoint of the Low Level Driver. 
  318.   * @param  pdev: Device handle 
  319.   * @param  ep_addr: Endpoint Number 
  320.   * @retval USBD Status 
  321.   */  
  322. USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)  
  323. {  
  324.   HAL_PCD_EP_SetStall((PCD_HandleTypeDef*)pdev->pData, ep_addr);  
  325.   return USBD_OK;  
  326. }  
  327.   
  328. /** 
  329.   * @brief  Clears a Stall condition on an endpoint of the Low Level Driver. 
  330.   * @param  pdev: Device handle 
  331.   * @param  ep_addr: Endpoint Number 
  332.   * @retval USBD Status 
  333.   */  
  334. USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)  
  335. {  
  336.   HAL_PCD_EP_ClrStall((PCD_HandleTypeDef*)pdev->pData, ep_addr);  
  337.   return USBD_OK;  
  338. }  
  339.   
  340. /** 
  341.   * @brief  Returns Stall condition. 
  342.   * @param  pdev: Device handle 
  343.   * @param  ep_addr: Endpoint Number 
  344.   * @retval Stall (1: Yes, 0: No) 
  345.   */  
  346. uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)  
  347. {  
  348.   PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*)pdev->pData;  
  349.   
  350.   if ((ep_addr & 0x80) == 0x80)  
  351.   {  
  352.     return hpcd->IN_ep[ep_addr & 0x7F].is_stall;  
  353.   }  
  354.   else  
  355.   {  
  356.     return hpcd->OUT_ep[ep_addr & 0x7F].is_stall;  
  357.   }  
  358. }  
  359.   
  360. /** 
  361.   * @brief  Assigns a USB address to the device. 
  362.   * @param  pdev: Device handle 
  363.   * @param  ep_addr: Endpoint Number 
  364.   * @retval USBD Status 
  365.   */  
  366. USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr)  
  367. {  
  368.   HAL_PCD_SetAddress((PCD_HandleTypeDef*)pdev->pData, dev_addr);  
  369.   return USBD_OK;  
  370. }  
  371.   
  372. /** 
  373.   * @brief  Transmits data over an endpoint. 
  374.   * @param  pdev: Device handle 
  375.   * @param  ep_addr: Endpoint Number 
  376.   * @param  pbuf: Pointer to data to be sent 
  377.   * @param  size: Data size 
  378.   * @retval USBD Status 
  379.   */  
  380. USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev,  
  381.                                     uint8_t ep_addr,  
  382.                                     uint8_t *pbuf,  
  383.                                     uint16_t size)  
  384. {  
  385.   HAL_PCD_EP_Transmit((PCD_HandleTypeDef*)pdev->pData, ep_addr, pbuf, size);  
  386.   return USBD_OK;  
  387. }  
  388.   
  389. /** 
  390.   * @brief  Prepares an endpoint for reception. 
  391.   * @param  pdev: Device handle 
  392.   * @param  ep_addr: Endpoint Number 
  393.   * @param  pbuf: Pointer to data to be received 
  394.   * @param  size: Data size 
  395.   * @retval USBD Status 
  396.   */  
  397. USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev,  
  398.                                           uint8_t ep_addr,  
  399.                                           uint8_t *pbuf,  
  400.                                           uint16_t size)  
  401. {  
  402.   HAL_PCD_EP_Receive((PCD_HandleTypeDef*)pdev->pData, ep_addr, pbuf, size);  
  403.   return USBD_OK;  
  404. }  
  405.   
  406. /** 
  407.   * @brief  Returns the last transferred packet size. 
  408.   * @param  pdev: Device handle 
  409.   * @param  ep_addr: Endpoint Number 
  410.   * @retval Recived Data Size 
  411.   */  
  412. uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr)  
  413. {  
  414.   return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*)pdev->pData, ep_addr);  
  415. }  
  416.   
  417. /** 
  418.   * @brief  Delays routine for the USB Device Library. 
  419.   * @param  Delay: Delay in ms 
  420.   * @retval None 
  421.   */  
  422. void USBD_LL_Delay(uint32_t Delay)  
  423. {  
  424.   HAL_Delay(Delay);  
  425. }  
  426.   
  427. /** 
  428.   * @brief  static single allocation. 
  429.   * @param  size: size of allocated memory 
  430.   * @retval None 
  431.   */  
  432. void *USBD_static_malloc(uint32_t size)  
  433. {  
  434.   static uint32_t mem[MAX_STATIC_ALLOC_SIZE];  
  435.   return mem;  
  436. }  
  437.   
  438. /** 
  439.   * @brief  Dummy memory free 
  440.   * @param  *p pointer to allocated  memory address 
  441.   * @retval None 
  442.   */  
  443. void USBD_static_free(void *p)  
  444. {  
  445.   
  446. }  
  447.   
  448. /** 
  449.   * @brief  Software Device Connection 
  450.   * @param  hpcd: PCD handle 
  451.   * @param  state: connection state (0 : disconnected / 1: connected) 
  452.   * @retval None 
  453.   */  
  454. void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state)  
  455. {  
  456.       
  457. }  
  458.   
  459. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/  
这里至改动了USBD_LL_Init()函数,配置端点1为双缓冲模式。同时在usbd_uvc.c文件中修改USBD_UVC_Init()函数打开所需的端点,如下:

[cpp]  view plain  copy
  1. /** 
  2.   * @brief  USBD_UVC_Init 
  3.   *         Initialize the UVC interface 
  4.   * @param  pdev: device instance 
  5.   * @param  cfgidx: Configuration index 
  6.   * @retval status 
  7.   */  
  8. static uint8_t  USBD_UVC_Init (USBD_HandleTypeDef *pdev,   
  9.                                uint8_t cfgidx)  
  10. {  
  11.   uint8_t ret = 0;  
  12.   USBD_UVC_HandleTypeDef *huvc;  
  13.   
  14.   USBD_LL_OpenEP(pdev, UVC_ISO_DATA_EP, USBD_EP_TYPE_ISOC, UVC_ISO_DATA_PACKET_SIZE);  
  15.   
  16.   pdev->pClassData = USBD_malloc(sizeof (USBD_UVC_HandleTypeDef));  
  17.     
  18.   if(pdev->pClassData == NULL)  
  19.   {  
  20.     ret = 1;   
  21.   }  
  22.   else  
  23.   {  
  24.     huvc = (USBD_UVC_HandleTypeDef*) pdev->pClassData;  
  25.       
  26.     /* Init  physical Interface components */  
  27.     ((USBD_UVC_ItfTypeDef *)pdev->pUserData)->Init();  
  28.   }  
  29.   
  30.   return ret;  
  31. }  
  32.   
  33. /** 
  34.   * @brief  USBD_UVC_Init 
  35.   *         DeInitialize the UVC layer 
  36.   * @param  pdev: device instance 
  37.   * @param  cfgidx: Configuration index 
  38.   * @retval status 
  39.   */  
  40. static uint8_t  USBD_UVC_DeInit (USBD_HandleTypeDef *pdev,   
  41.                                  uint8_t cfgidx)  
  42. {  
  43.   /* Close EP 1 */  
  44.   USBD_LL_CloseEP(pdev,UVC_ISO_DATA_EP);  
  45.     
  46.   /* DeInit  physical Interface components */  
  47.   if(pdev->pClassData != NULL)  
  48.   {  
  49.     ((USBD_UVC_ItfTypeDef *)pdev->pUserData)->DeInit();  
  50.     USBD_free(pdev->pClassData);  
  51.     pdev->pClassData = NULL;  
  52.   }  
  53.   
  54.   return USBD_OK;  
  55. }  
至此,我们就可以实现UVC设备的枚举过程了。先到这吧,未完待续。。。

PS:网上也有一些关于STM32+UVC的例子,一个是使用STM32玩俄罗斯方块,这个比较有意思,它是用STM32标准库和旧的usb设备库实现的连接如下:http://bbs.21ic.com/icview-163992-1-1.html

还有一个是一个俄罗斯人用STM32F4实现的视频传输,使用的是USBOTG模块,它的工程如下:

https://github.com/iliasam/STM32F4_UVC_Camera

该示例的说明地址如下,使用俄文写的:https://geektimes.ru/post/255316/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值