本文中采用stm32f103核心板,自带USB FS接口,板载了Flash W25Q16,将该Flash配置为MSC的存储区,最终实现的效果为:将设备插入电脑,可以识别到WinUSB免驱设备,高速通信,同时也能识别出一个大容量存储区域,方便存放一些设备相关的资料、文档等,非常实用!
本文的方法是在WinUSB工程的基础上增加MSC功能。
首先准备好一个WinUSB工程,配置方法见之前的文章:
https://blog.csdn.net/bingwueyi/article/details/121622001
在准备WinUSB工程的时候,将SPI也配置好,后期增加MSC的时候就不用再去设置SPI相关功能,省去一些麻烦。
1 工程配置
1、通过CubeMX生成一个MSC的工程,设置如下:
2、将下图中框出的几个文件及其头文件拷贝到WinUSB工程中的对应目录中
3、将Flash的操作文件W25QXX.c和复合设备文件usbd_composite.c也放到工程目录中,并且将上述文件添加到Keil工程目录,添加完后的工程目录如下:
Keil工程配置中添加相关路径
Flash操作函数参见:STM32CubeMX系列教程11:串行外设接口SPI(二) - STM32CubeMX系列教程 微雪课堂
头文件中将引用改为
#include "main.h"
同时增加如下定义:
#define SPI_FLASH_REBUILD 1 // 1:使能格式化串行Flash,0:禁用格式化串行Flash
#define SPI_FLASH_SECTOR_SIZE 4096 // 串行Flash扇区大小
#define SPI_FLASH_START_SECTOR 256 // 串行Flash文件系统FatFS偏移量
#define SPI_FLASH_SECTOR_COUNT 256 // 串行Flash文件系统FatFS占用扇区个数
extern SPI_HandleTypeDef hspi1; // 添加SPI定义
usbd_composite.c,usbd_composite.h基于这篇文章修改:https://www.bbsmax.com/A/kjdwBXA5Np/
修改后的文件如下
//usbd_composite.c
/**
* @file usbd_composite.c
* @author Weyne
* @version V01
* @date 2023.09.10
* @brief MSC + WinUSB 复合设备
* @note
* @attention COYPRIGHT WEYNE
*/
#include "usbd_composite.h"
#include "usbd_cdc.h"
#include "usbd_msc.h"
static USBD_CDC_HandleTypeDef *pCDCData;
static USBD_MSC_BOT_HandleTypeDef *pMSCData;
static uint8_t USBD_Composite_Init (USBD_HandleTypeDef *pdev,
uint8_t cfgidx);
static uint8_t USBD_Composite_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx);
static uint8_t USBD_Composite_EP0_RxReady(USBD_HandleTypeDef *pdev);
static uint8_t USBD_Composite_Setup (USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req);
static uint8_t USBD_Composite_DataIn (USBD_HandleTypeDef *pdev,
uint8_t epnum);
static uint8_t USBD_Composite_DataOut (USBD_HandleTypeDef *pdev,
uint8_t epnum);
static uint8_t *USBD_Composite_GetFSCfgDesc (uint16_t *length);
static uint8_t *USBD_Composite_GetDeviceQualifierDescriptor (uint16_t *length);
//-----------------ADD GUOXUAN-----------------
extern uint8_t* USBD_WinUSBOSStrDescriptor(uint16_t *length);
//---------------------------------------------
USBD_ClassTypeDef USBD_COMPOSITE =
{
USBD_Composite_Init,
USBD_Composite_DeInit,
USBD_Composite_Setup,
NULL, /*EP0_TxSent*/
USBD_Composite_EP0_RxReady,
USBD_Composite_DataIn,
USBD_Composite_DataOut,
NULL,
NULL,
NULL,
NULL,
USBD_Composite_GetFSCfgDesc,
NULL,
USBD_Composite_GetDeviceQualifierDescriptor,
//-----------------ADD GUOXUAN----------------
USBD_WinUSBOSStrDescriptor,
//--------------------------------------------
};
/* USB composite device Configuration Descriptor */
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
__ALIGN_BEGIN uint8_t USBD_Composite_CfgFSDesc[USBD_COMPOSITE_DESC_SIZE] __ALIGN_END =
{
0x09, /* bLength: Configuation Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
WBVAL(USBD_COMPOSITE_DESC_SIZE),
USBD_MAX_NUM_INTERFACES , /* bNumInterfaces: */
0x01, /* bConfigurationValue: */
0x00, /* iConfiguration: */
0xC0, /* bmAttributes: */
0x96, /* MaxPower 300 mA */
/****************************CDC************************************/
/* Interface Association Descriptor */
USBD_IAD_DESC_SIZE, // bLength
USBD_IAD_DESCRIPTOR_TYPE, // bDescriptorType
USBD_CDC_FIRST_INTERFACE, // bFirstInterface
USBD_CDC_INTERFACE_NUM, // bInterfaceCount
0x02, // bFunctionClass
0x02, // bFunctionSubClass
0x01, // bInterfaceProtocol
0x02, // iFunction ??
/*Interface Descriptor */
/* Data class interface descriptor */
0x09, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0xFF, /* bInterfaceClass: CDC */
0x00, /* bInterfaceSubClass */
0x00, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Endpoint OUT Descriptor */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_OUT_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval */
/* Endpoint IN Descriptor */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_IN_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval */
/****************************MSC************************************/
/* Interface Association Descriptor */
USBD_IAD_DESC_SIZE, // bLength
USBD_IAD_DESCRIPTOR_TYPE, // bDescriptorType
USBD_MSC_FIRST_INTERFACE, // bFirstInterface
USBD_MSC_INTERFACE_NUM, // bInterfaceCount
0x08, // bFunctionClass
0x06, // bFunctionSubClass
0x50, // bInterfaceProtocol
0x05,
/******************** Mass Storage interface ********************/
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
USBD_MSC_INTERFACE, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints*/
0x08, /* bInterfaceClass: MSC Class */
0x06, /* bInterfaceSubClass : SCSI transparent*/
0x50, /* nInterfaceProtocol */
0x05, /* iInterface: */
/******************** Mass Storage Endpoints ********************/
0x07, /*Endpoint descriptor length = 7*/
0x05, /*Endpoint descriptor type */
MSC_EPIN_ADDR, /*Endpoint address (IN, address 1) */
0x02, /*Bulk endpoint type */
LOBYTE(MSC_MAX_FS_PACKET),
HIBYTE(MSC_MAX_FS_PACKET),
0x01, /*Polling interval in milliseconds */
0x07, /*Endpoint descriptor length = 7 */
0x05, /*Endpoint descriptor type */
MSC_EPOUT_ADDR, /*Endpoint address (OUT, address 1) */
0x02, /*Bulk endpoint type */
LOBYTE(MSC_MAX_FS_PACKET),
HIBYTE(MSC_MAX_FS_PACKET),
0x01, /*Polling interval in milliseconds*/
};
/* USB Standard Device Descriptor */
__ALIGN_BEGIN uint8_t USBD_Composite_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
};
/**
* @brief USBD_Composite_Init
* Initialize the Composite interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_Composite_Init (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
uint8_t res = 0;
pdev->pUserData = &USBD_Interface_fops_FS;
res += USBD_CDC.Init(pdev,cfgidx);
pCDCData = pdev->pClassData;
pdev->pUserData = &USBD_Storage_Interface_fops_FS;
res += USBD_MSC.Init(pdev,cfgidx);
pMSCData = pdev->pClassData;
return res;
}
/**
* @brief USBD_Composite_DeInit
* DeInitilaize the Composite configuration
* @param pdev: device instance
* @param cfgidx: configuration index
* @retval status
*/
static uint8_t USBD_Composite_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
uint8_t res = 0;
pdev->pClassData = pCDCData;
pdev->pUserData = &USBD_Interface_fops_FS;
res += USBD_CDC.DeInit(pdev,cfgidx);
pdev->pClassData = pMSCData;
pdev->pUserData = &USBD_Storage_Interface_fops_FS;
res += USBD_MSC.DeInit(pdev,cfgidx);
return res;
}
static uint8_t USBD_Composite_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
return USBD_CDC.EP0_RxReady(pdev);
}
/**
* @brief USBD_Composite_Setup
* Handle the Composite requests
* @param pdev: device instance
* @param req: USB request
* @retval status
*/
static uint8_t USBD_Composite_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
switch (req->bmRequest & USB_REQ_RECIPIENT_MASK)
{
case USB_REQ_RECIPIENT_INTERFACE:
switch(req->wIndex)
{
case USBD_CDC_DATA_INTERFACE:
pdev->pClassData = pCDCData;
pdev->pUserData = &USBD_Interface_fops_FS;
return(USBD_CDC.Setup(pdev, req));
case USBD_MSC_INTERFACE:
pdev->pClassData = pMSCData;
pdev->pUserData = &USBD_Storage_Interface_fops_FS;
return(USBD_MSC.Setup (pdev, req));
default:
break;
}
break;
case USB_REQ_RECIPIENT_ENDPOINT:
switch(req->wIndex)
{
case CDC_IN_EP:
case CDC_OUT_EP:
case CDC_CMD_EP:
pdev->pClassData = pCDCData;
pdev->pUserData = &USBD_Interface_fops_FS;
return(USBD_CDC.Setup(pdev, req));
case MSC_EPIN_ADDR:
case MSC_EPOUT_ADDR:
pdev->pClassData = pMSCData;
pdev->pUserData = &USBD_Storage_Interface_fops_FS;
return(USBD_MSC.Setup (pdev, req));
default:
break;
}
break;
}
return USBD_OK;
}
/**
* @brief USBD_Composite_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
uint8_t USBD_Composite_DataIn (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
switch(epnum)
{
case CDC_INDATA_NUM:
pdev->pClassData = pCDCData;
pdev->pUserData = &USBD_Interface_fops_FS;
return(USBD_CDC.DataIn(pdev,epnum));
case MSC_INDATA_NUM:
pdev->pClassData = pMSCData;
pdev->pUserData = &USBD_Storage_Interface_fops_FS;
return(USBD_MSC.DataIn(pdev,epnum));
default:
break;
}
return USBD_FAIL;
}
/**
* @brief USBD_Composite_DataOut
* handle data OUT Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
uint8_t USBD_Composite_DataOut (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
switch(epnum)
{
case CDC_OUTDATA_NUM:
case CDC_OUTCMD_NUM:
pdev->pClassData = pCDCData;
pdev->pUserData = &USBD_Interface_fops_FS;
return(USBD_CDC.DataOut(pdev,epnum));
case MSC_OUTDATA_NUM:
pdev->pClassData = pMSCData;
pdev->pUserData = &USBD_Storage_Interface_fops_FS;
return(USBD_MSC.DataOut(pdev,epnum));
default:
break;
}
return USBD_FAIL;
}
/**
* @brief USBD_Composite_GetHSCfgDesc
* return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_Composite_GetFSCfgDesc (uint16_t *length)
{
*length = sizeof (USBD_Composite_CfgFSDesc);
return USBD_Composite_CfgFSDesc;
}
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_Composite_GetDeviceQualifierDescriptor (uint16_t *length)
{
*length = sizeof (USBD_Composite_DeviceQualifierDesc);
return USBD_Composite_DeviceQualifierDesc;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT WEYNE *****END OF FILE****/
//usbd_composite.h
/**
* @file usbd_composite.h
* @author Weyne
* @version V01
* @date 2016.10.28
* @brief MSC + CDC 复合设备
* @note
* @attention COYPRIGHT WEYNE
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_COMPOSITE_H
#define __USBD_COMPOSITE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_msc.h"
#include "usbd_cdc.h"
#include "usbd_storage_if.h"
#include "usbd_cdc_if.h"
#define WBVAL(x) (x & 0xFF),((x >> 8) & 0xFF)
#define DBVAL(x) (x & 0xFF),((x >> 8) & 0xFF),((x >> 16) & 0xFF),((x >> 24) & 0xFF)
#define USBD_IAD_DESC_SIZE 0x08
#define USBD_IAD_DESCRIPTOR_TYPE 0x0B
#define USBD_CDC_FIRST_INTERFACE 0 /* CDC FirstInterface */
#define USBD_CDC_INTERFACE_NUM 1 /* winusb Interface NUM */
#define USBD_CDC_DATA_INTERFACE 0
#define USBD_MSC_FIRST_INTERFACE 1 /* MSC FirstInterface */
#define USBD_MSC_INTERFACE_NUM 1 /* MSC Interface NUM */
#define USBD_MSC_INTERFACE 1
#define MSC_INDATA_NUM (MSC_EPIN_ADDR & 0x0F)
#define MSC_OUTDATA_NUM (MSC_EPOUT_ADDR & 0x0F)
#define CDC_INDATA_NUM (CDC_IN_EP & 0x0F)
#define CDC_OUTDATA_NUM (CDC_OUT_EP & 0x0F)
#define CDC_OUTCMD_NUM (CDC_CMD_EP & 0x0F)
#define USBD_COMPOSITE_DESC_SIZE (71)
extern USBD_ClassTypeDef USBD_COMPOSITE;
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_MSC_H */
/**
* @}
*/
/************************ (C) COPYRIGHT WEYNE *****END OF FILE****/
2 修改工程文件
2.1 修改usbd_storage_if.c
1、添加Flash操作函数头文件
#include "W25QXX.h"
2、根据Flash容量修改block数量,例如此处我用的时2MB的Flash,Flash需要划分一部分空间存文件系统信息,此处Block大小为4K,数量为256,总容量为1M,修改如下
#define STORAGE_LUN_NBR 1
#define STORAGE_BLK_NBR 256
#define STORAGE_BLK_SIZ 0x1000
3、在STORAGE_Init_FS中加入Flash初始化函数BSP_W25Qx_Init(),在初始化中可以执行唤醒、读写使能、三四字节模式切换等操作。
int8_t STORAGE_Init_FS(uint8_t lun)
{
/* USER CODE BEGIN 2 */
BSP_W25Qx_Init();
return (USBD_OK);
/* USER CODE END 2 */
}
4、在读写函数中分别加入对Flash的操作
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 6 */
blk_addr+=SPI_FLASH_START_SECTOR;
BSP_W25Qx_Read(buf, blk_addr*SPI_FLASH_SECTOR_SIZE, blk_len*SPI_FLASH_SECTOR_SIZE);
return (USBD_OK);
/* USER CODE END 6 */
}
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 7 */
uint32_t write_addr;
blk_addr+=SPI_FLASH_START_SECTOR;
write_addr = blk_addr*SPI_FLASH_SECTOR_SIZE;
BSP_W25Qx_Erase_Block(write_addr);
BSP_W25Qx_Write((uint8_t *)buf,write_addr,blk_len*SPI_FLASH_SECTOR_SIZE);
return (USBD_OK);
/* USER CODE END 7 */
}
2.2 修改usbd_msc.h
查看MSC_EPIN_ADDR的值为0x81,与WinUSB的端点重复了,此处将MSC的端点改为0x83和0x03:
#define MSC_EPIN_ADDR 0x83U
#define MSC_EPOUT_ADDR 0x03U
2.3 修改usb_device.c
1、添加复合设备头文件引用
#include "usbd_composite.h"
2、将初始化函数中的设备注册修改注册为复合设备
void MX_USB_DEVICE_Init(void)
{
/* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */
/* USER CODE END USB_DEVICE_Init_PreTreatment */
/* Init Device Library, add supported class and start the library. */
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
USBD_RegisterClass(&hUsbDeviceFS, &USBD_COMPOSITE);
// if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK)
// {
// Error_Handler();
// }
// if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK)
// {
// Error_Handler();
// }
if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */
/* USER CODE END USB_DEVICE_Init_PostTreatment */
}
2.4 修改usbd_conf.c
1、添加msc的头文件引用
#include "usbd_msc.h"
2、在USBD_LL_Init函数中增加MSC的内存区间定义
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
/* Init USB Ip. */
uint32_t addr = 0x20;
/* Link the driver to the stack. */
hpcd_USB_FS.pData = pdev;
pdev->pData = &hpcd_USB_FS;
hpcd_USB_FS.Instance = USB;
hpcd_USB_FS.Init.dev_endpoints = 8;
hpcd_USB_FS.Init.speed = PCD_SPEED_FULL;
hpcd_USB_FS.Init.low_power_enable = DISABLE;
hpcd_USB_FS.Init.lpm_enable = DISABLE;
hpcd_USB_FS.Init.battery_charging_enable = DISABLE;
if (HAL_PCD_Init(&hpcd_USB_FS) != HAL_OK)
{
Error_Handler( );
}
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
/* Register USB PCD CallBacks */
HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_SOF_CB_ID, PCD_SOFCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_SETUPSTAGE_CB_ID, PCD_SetupStageCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_RESET_CB_ID, PCD_ResetCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_SUSPEND_CB_ID, PCD_SuspendCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_RESUME_CB_ID, PCD_ResumeCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_CONNECT_CB_ID, PCD_ConnectCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_DISCONNECT_CB_ID, PCD_DisconnectCallback);
HAL_PCD_RegisterDataOutStageCallback(&hpcd_USB_FS, PCD_DataOutStageCallback);
HAL_PCD_RegisterDataInStageCallback(&hpcd_USB_FS, PCD_DataInStageCallback);
HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_FS, PCD_ISOOUTIncompleteCallback);
HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_FS, PCD_ISOINIncompleteCallback);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
/* USER CODE BEGIN EndPoint_Configuration */
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, addr); addr = addr + 0x40;
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, addr); addr = addr + 0x40;
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , MSC_EPIN_ADDR , PCD_SNG_BUF, addr); addr = addr + 0x40;
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , MSC_EPOUT_ADDR , PCD_SNG_BUF, addr); addr = addr + 0x40;
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP , PCD_SNG_BUF, addr); addr = addr + 0x40;
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP , PCD_SNG_BUF, addr); addr = addr + 0x40;
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_CMD_EP , PCD_SNG_BUF, addr); addr = addr + 0x40;
/* USER CODE END EndPoint_Configuration_MSC */
return USBD_OK;
}
3、修改USBD_static_malloc函数,增加MSC的存储空间:
void *USBD_static_malloc(uint32_t size)
{
static uint32_t mem2[(sizeof(USBD_MSC_BOT_HandleTypeDef)/4)+1];/* On 32-bit boundary */
static uint32_t mem[(sizeof(USBD_CDC_HandleTypeDef)/4)+1];/* */
if(size == sizeof(USBD_MSC_BOT_HandleTypeDef))
return mem2;
else return mem;
}
2.5 修改usbd_conf.h
1、将USBD_MAX_NUM_INTERFACES定义为2个接口:
#define USBD_MAX_NUM_INTERFACES 2
2、添加MSC_MEDIA_PACKET定义:
#define MSC_MEDIA_PACKET 4096
3 测试
完成上述修改(建议随意修改一个PID VID),编译-->下载-->插入电脑,将会枚举出一个usb复合设备,并且识别到一个WinUSB设备和一个大容量存储设备:
查看识别到的U盘,容量与2.1章节第2小节设置的一致,打开U盘创建文件、导入、导出等功能一切正常。
使用WinUSB通用调试软件,可以识别到刚插入的设备,并且通信正常,此处WinUSB为回环模式,收到数据原包回复。