stm32制作CAN适配器4--WinUsb的使用

前面使用STM32G474芯片的USB模块做了一个CANFD程序,当时用的是HID模式,在实际使用时发现HID模块的通讯速率太慢了,只能1ms传输一帧,就会造成有些掉帧现象。 现在就把HID模块改为在Window下同样免驱的WinUsb来实现CANFD数据的传输。 首先使用STM32CubeMX配置端口与时钟

采用外部晶振12M

USB第三方库选CDC模式
到此配置完成,点击生成代码,在生成的代码中更改以下内容实现WinUSB驱动 。

在usbd_desc.c中增加Winusb的特有字符描述

c 复制代码
#if (USBD_SUPPORT_WINUSB==1)
const uint8_t USBD_OS_STRING[8] = { 
		'M',
		'S',
		'F',
		'T',
		'1',
		'0',
		'0',
		0xA0U,//USB_REQ_MS_VENDOR_CODE,
}; 

uint8_t *USBD_WinUSBOSStrDescriptor(uint16_t *length)
{
	USBD_GetString((uint8_t *)USBD_OS_STRING, USBD_StrDesc, length);
	return USBD_StrDesc;
}

#define USB_LEN_OS_FEATURE_DESC 0x28
__ALIGN_BEGIN uint8_t USBD_WINUSB_OSFeatureDesc[USB_LEN_OS_FEATURE_DESC] __ALIGN_END =
{
		0x28, 0, 0, 0, // length
		0, 1,          // bcd version 1.0
		4, 0,          // windex: extended compat ID descritor
		1,             // no of function
		0, 0, 0, 0, 0, 0, 0, // reserve 7 bytes
		// function
		0,             // interface no
		0,             // reserved
		'W', 'I', 'N', 'U', 'S', 'B', 0, 0, //  first ID
		0,   0,   0,   0,   0,   0, 0, 0,  // second ID
		0,   0,   0,   0,   0,   0 // reserved 6 bytes
};

uint8_t *USBD_WinUSBOSFeatureDescriptor(uint16_t *length)
{
	*length = USB_LEN_OS_FEATURE_DESC;
	return USBD_WINUSB_OSFeatureDesc;
}

#define USB_LEN_OS_PROPERTY_DESC 0x8E
__ALIGN_BEGIN uint8_t USBD_WINUSB_OSPropertyDesc[USB_LEN_OS_PROPERTY_DESC] __ALIGN_END =
{
		0x8E, 0, 0, 0,  // length 246 byte
		0x00, 0x01,   // BCD version 1.0
		0x05, 0x00,   // Extended Property Descriptor Index(5)
		0x01, 0x00,   // number of section (1)
		//; property section
		0x84, 0x00, 0x00, 0x00,   // size of property section
		0x1, 0, 0, 0,   //; property data type (1)
		0x28, 0,        //; property name length (42)
		'D', 0,
		'e', 0,
		'v', 0,
		'i', 0,
		'c', 0,
		'e', 0,
		'I', 0,
		'n', 0,
		't', 0,
		'e', 0,
		'r', 0,
		'f', 0,
		'a', 0,
		'c', 0,
		'e', 0,
		'G', 0,
		'U', 0,
		'I', 0,
		'D', 0,
		0, 0,
		// 13eb360b-bc1e-46cb-ac8b-ef3da47
		0x4E, 0, 0, 0,  // ; property data length
		'{', 0,
		'1', 0,
		'3', 0,
		'E', 0,
		'B', 0,
		'3', 0,
		'6', 0,
		'0', 0,
		'B', 0,
		'-', 0,
		'B', 0,
		'C', 0,
		'1', 0,
		'E', 0,
		'-', 0,
		'4', 0,
		'6', 0,
		'C', 0,
		'B', 0,
		'-', 0,
		'A', 0,
		'C', 0,
		'8', 0,
		'B', 0,
		'-', 0,
		'E', 0,
		'F', 0,
		'3', 0,
		'D', 0,
		'A', 0,
		'4', 0,
		'7', 0,
		'B', 0,
		'4', 0,
		'0', 0,
		'6', 0,
		'2', 0,
		'}', 0,
		0, 0,

};
uint8_t *USBD_WinUSBOSPropertyDescriptor(uint16_t *length)
{
	*length = USB_LEN_OS_PROPERTY_DESC;
	return USBD_WINUSB_OSPropertyDesc;
}
#endif // (USBD_SUPPORT_WINUSB==1)

在usbd_ctlreq.c中static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)增加case 0xEE。

c 复制代码
#if (USBD_SUPPORT_WINUSB==1)
	case 0xEE: // OS String 
	if (pdev->pClass->GetWinUSBOSDescriptor != NULL)
	{
		pbuf = pdev->pClass->GetWinUSBOSDescriptor(&len);
	}
	else
	{
		USBD_CtlError(pdev, req);
		err++;
	}  
	break;
#endif // (USBD_SUPPORT_WINUSB==1)

USBD_DescriptorsTypeDef CDC_Desc =
{
  USBD_CDC_DeviceDescriptor,
  USBD_CDC_LangIDStrDescriptor,
  USBD_CDC_ManufacturerStrDescriptor,
  USBD_CDC_ProductStrDescriptor,
  USBD_CDC_SerialStrDescriptor,
  USBD_CDC_ConfigStrDescriptor,
  USBD_CDC_InterfaceStrDescriptor,
 USBD_WinUSBOSFeatureDescriptor,
USBD_WinUSBOSPropertyDescriptor,
};

在usbd_def.h中USBD_ClassTypeDef和USBD_DescriptorsTypeDef增加winusb描述

c 复制代码
typedef struct _Device_cb
{
  uint8_t (*Init)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx);
  uint8_t (*DeInit)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx);
  /* Control Endpoints*/
  uint8_t (*Setup)(struct _USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef  *req);
  uint8_t (*EP0_TxSent)(struct _USBD_HandleTypeDef *pdev);
  uint8_t (*EP0_RxReady)(struct _USBD_HandleTypeDef *pdev);
  /* Class Specific Endpoints*/
  uint8_t (*DataIn)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
  uint8_t (*DataOut)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
  uint8_t (*SOF)(struct _USBD_HandleTypeDef *pdev);
  uint8_t (*IsoINIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
  uint8_t (*IsoOUTIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);

  uint8_t  *(*GetHSConfigDescriptor)(uint16_t *length);
  uint8_t  *(*GetFSConfigDescriptor)(uint16_t *length);
  uint8_t  *(*GetOtherSpeedConfigDescriptor)(uint16_t *length);
  uint8_t  *(*GetDeviceQualifierDescriptor)(uint16_t *length);
#if (USBD_SUPPORT_USER_STRING_DESC == 1U)
  uint8_t  *(*GetUsrStrDescriptor)(struct _USBD_HandleTypeDef *pdev, uint8_t index,  uint16_t *length);
#endif
#if (USBD_SUPPORT_WINUSB == 1) 
  uint8_t  *(*GetWinUSBOSDescriptor)(uint16_t *length); 
#endif  

} USBD_ClassTypeDef;

/* USB Device descriptors structure */
typedef struct
{
  uint8_t *(*GetDeviceDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
  uint8_t *(*GetLangIDStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
  uint8_t *(*GetManufacturerStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
  uint8_t *(*GetProductStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
  uint8_t *(*GetSerialStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
  uint8_t *(*GetConfigurationStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
  uint8_t *(*GetInterfaceStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
#if (USBD_CLASS_USER_STRING_DESC == 1)
  uint8_t *(*GetUserStrDescriptor)(USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length);
#endif
#if ((USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1))
  uint8_t *(*GetBOSDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
#endif
#if (USBD_SUPPORT_WINUSB==1)
   uint8_t *(*GetWinUSBOSFeatureDescriptor)(uint16_t *length);
   uint8_t *(*GetWinUSBOSPropertyDescriptor)(uint16_t *length);
#endif
} USBD_DescriptorsTypeDef;

在usbd_cdc.c中的static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev,

USBD_SetupReqTypedef *req)更改为下面

c 复制代码
#define WINUSB_CONFIG_DESC_SIZE 32
__ALIGN_BEGIN uint8_t USBD_CDC_CfgHSDesc[WINUSB_CONFIG_DESC_SIZE] __ALIGN_END =
{
  /*Configuration Descriptor*/
  0x09,   /* bLength: Configuration Descriptor size */
  USB_DESC_TYPE_CONFIGURATION,      /* bDescriptorType: Configuration */
  WINUSB_CONFIG_DESC_SIZE,                /* wTotalLength:no of returned bytes */
  0x00,
  0x01,   /* bNumInterfaces: 1 interface for WINUSB */
  0x01,   /* bConfigurationValue: Configuration value */
  USBD_IDX_CONFIG_STR,   /* iConfiguration: Index of string descriptor describing the configuration */
  0xC0,   /* bmAttributes: self powered */
  0x32,   /* MaxPower 50*2 mA */
  
  /*---------------------------------------------------------------------------*/
  /*Data class interface descriptor*/
  0x09,   /* bLength: Endpoint Descriptor size */
  USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */
  0x00,   /* bInterfaceNumber: Number of Interface, zero based index of this interface */
  0x00,   /* bAlternateSetting: Alternate setting */
  0x02,   /* bNumEndpoints: Two endpoints used */
  0xff,   /* bInterfaceClass: vendor */
//  0x00,   /* bInterfaceClass: vendor */
  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_HS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
  HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),
  0x00,                              /* bInterval: ignore for Bulk transfer */
  
  /*Endpoint IN Descriptor*/
  0x07,   /* bLength: Endpoint Descriptor size */
  USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
  CDC_IN_EP,                         /* bEndpointAddress */
  0x02,                              /* bmAttributes: Bulk */
  LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
  HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),
  0x00                               /* bInterval: ignore for Bulk transfer */
} ;

__ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[WINUSB_CONFIG_DESC_SIZE] __ALIGN_END =
{
  /*Configuration Descriptor*/
  0x09,   /* bLength: Configuration Descriptor size */
  USB_DESC_TYPE_CONFIGURATION,      /* bDescriptorType: Configuration */
  WINUSB_CONFIG_DESC_SIZE,                /* wTotalLength:no of returned bytes */
  0x00,
  0x01,   /* bNumInterfaces: 1 interface for Game IO */
  0x01,   /* bConfigurationValue: Configuration value */
  USBD_IDX_CONFIG_STR,   /* iConfiguration: Index of string descriptor describing the configuration */
  0xC0,   /* bmAttributes: self powered */
  0x32,   /* MaxPower 0 mA */
  
  /*---------------------------------------------------------------------------*/
  /*Data class interface descriptor*/
  0x09,   /* bLength: Endpoint Descriptor size */
  USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */
  0x00,   /* bInterfaceNumber: Number of Interface, zero based index of this interface */
  0x00,   /* bAlternateSetting: Alternate setting */
  0x02,   /* bNumEndpoints: Two endpoints used */
  0xff,   /* bInterfaceClass: vendor */
//  0x00,   /* bInterfaceClass: vendor */
  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: ignore for Bulk transfer */
  
  /*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: ignore for Bulk transfer */
} ;    

void USBD_WinUSBGetDescriptor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
  uint16_t len;
  uint8_t *pbuf;
  
    
  switch (req->wIndex)
  { 
  case 0x04: // compat ID
    pbuf = pdev->pDesc->GetWinUSBOSFeatureDescriptor(&len);
    break;
  case 0x05:
    pbuf = pdev->pDesc->GetWinUSBOSPropertyDescriptor(&len);
    break;
     
  default: 
     USBD_CtlError(pdev , req);
    return;
  }
  if((len != 0)&& (req->wLength != 0))
  {
    
    len = MIN(len , req->wLength);
    
    USBD_CtlSendData (pdev, 
                      pbuf,
                      len);
  }
} 

static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev,
                              USBD_SetupReqTypedef *req)
{
  USBD_StatusTypeDef ret = USBD_OK;

  if(req->bRequest == 0xA0)
  {
    USBD_WinUSBGetDescriptor( pdev, req ); 
    return USBD_OK;
  }

  if(req->bmRequest == 0xC1) 
  {
  	USBD_WinUSBGetDescriptor( pdev, req ); 
  	return USBD_OK;
  }
  
  return (uint8_t)ret;
}

编译驱动成功!

网盘:https://pan.baidu.com/s/1nIK4ig2TW4pdCfUxiYL6VA?pwd=1234

相关推荐
anghost1502 小时前
基于 STM32 的多传感器健康监测系统设计
stm32·单片机·嵌入式硬件
玉~你还好吗2 小时前
【嵌入式电机控制#34】FOC:意法电控驱动层源码解析——HALL传感器中断(不在两大中断内,但重要)
单片机·嵌入式系统·电机控制
STC_USB_CAN_80513 小时前
所有普通I/O口都支持中断的51单片机@Ai8051U, AiCube 图形化配置
单片机·嵌入式硬件·51单片机
正点原子4 小时前
《ESP32-S3使用指南—IDF版 V1.6》第三十四章 RGB触摸实验
单片机·物联网·嵌入式
码小文5 小时前
Altium Designer 22使用笔记(8)---PCB电气约束设置
笔记·嵌入式硬件·硬件工程·ad22
dumpling01205 小时前
新手向:使用STM32通过RS485通信接口控制步进电机
stm32·单片机·嵌入式硬件
hazy1k5 小时前
STM32-FreeRTOS快速入门指南(中)
stm32·单片机·嵌入式硬件
清风6666666 小时前
基于51单片机自动浇花1602液晶显示设计
单片机·嵌入式硬件·mongodb·毕业设计·51单片机·课程设计
古译汉书6 小时前
嵌入式-SPI番外之按钮驱动程序的编写-Day15
c语言·stm32·单片机·嵌入式硬件·mcu·算法
小莞尔11 小时前
【Proteus仿真】【51单片机】基于51单片机密码锁
stm32·单片机·嵌入式硬件·51单片机·proteus