62 stm32 usb自定义hid复合设备修改实验
Posted Chasing_Chasing
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了62 stm32 usb自定义hid复合设备修改实验相关的知识,希望对你有一定的参考价值。
1.引言
最近因为项目需要,我们希望单片机既能有hid键盘功能,又能有hid设备的功能。即单片机的一个usb接口插入电脑后,电脑能识别出键盘设备和hid设备,两者同时存在的。
基于项目只是要求实现功能,故本次只是对stm32usb应用方面进行了研究,并未对usb进行更深层次的了解,所以本blog只是记录了,如何基于单片机hid键盘例程,修改成hid键盘+hid设备过程及遇到的问题。
2.目标
图1单hid设备,在电脑中的显示:
图2单键盘设备在电脑中的显示:
图3 hid键盘+hid设备在电脑中的显示:
本次的目标就是,将stm32 usb插入电脑后,电脑能生成设备键盘+hid设备的节点,即图3示。
3.工具介绍
在修改移植代码中遇到一些问题,或测试数据需要一些工具(下载请自行百度)。
(1)其中使用bus hound来抓取usb收发的数据内容,通过该工具可以抓到usb设备收发的内容。
(2)使用hid收发工具,就像串口工具一样,可以测试hid设备的收发
上述两个工具,网上都可下载到。
4.usb代码修改过程
在这部分,我们进入具体的移植详情讲解,以及将所遇到的问题进行说明。
步骤1:修改usb_desc.c文件
因为底层的usb相关协议,原厂以及做好,作为开发应用的我们,暂时只需要关注应用方面。而对于应用方面,我们要第一个要关注的就是usb_desc.c文件。
当usb插入电脑的时候,usb的host与设备之间就会立即通信,host就会询问usb设备相关信息,入设备类型,支持的协议版本,usb的厂商标识等等。这些内容就在usb_desc.c文件下的设备描述结构体中,用户可根据需要修改这部分的内容。
#define USB_VID 0x5548
#define USB_PID 0x6666
#define DEV_VER 0x0100
/* USB Standard Device Descriptor */
const uint8_t CustomHID_DeviceDescriptor[CUSTOMHID_SIZ_DEVICE_DESC] =
0x12, /*bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType*/
0x00, /*bcdUSB */
0x02,
0x00, /*bDeviceClass*/
0x00, /*bDeviceSubClass*/
0x00, /*bDeviceProtocol*/
0x40, /*bMaxPacketSize40*/
USB_VID&0xff, /*idVendor*/
USB_VID>>8,
USB_PID&0xff, /*idProduct*/
USB_PID>>8,
DEV_VER&0xff, /*bcdDevice rel. 1.00*/
DEV_VER>>8,
1, /*Index of string descriptor describing
manufacturer */
2, /*Index of string descriptor describing
product*/
3, /*Index of string descriptor describing the
device serial number */
0x01 /*bNumConfigurations*/
; /* CustomHID_DeviceDescriptor */
上述字段中bMaxPacketSize40字段,是告知usb host本设备能支持传输的最大字节,一般一个标准的hid设备,每次传输的包就是64字节,所以64的十六进制就是0x40。上述结构中,除了关注这个字节数外,还可能常改的就是usb 的VID和PID。
usb设备描述信息之后便是,usb的设备配置描述结构。该设备配置信息结构向host上报本身详细的配置信息以及设备所支持的能力,原本例程只是hid键盘相关的配置,所以我们需要在此结构添加相关信息。
/* USB Configuration Descriptor */
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
const uint8_t CustomHID_ConfigDescriptor[CUSTOMHID_SIZ_CONFIG_DESC] =
0x09, /* bLength: Configuration Descriptor size */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
CUSTOMHID_SIZ_CONFIG_DESC,
/* wTotalLength: Bytes returned */
0x00,
0x02, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing
the configuration*/
0xC0, /* bmAttributes: Self powered */
0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */
/************** Descriptor of Custom HID interface ****************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType: Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints */
0x03, /* bInterfaceClass: HID */
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x01, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0, /* iInterface: Index of string descriptor */
/******************** Descriptor of Custom HID HID ********************/
/* 18 */
0x09, /* bLength: HID Descriptor size */
HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */
0x10, /* bcdHID: HID Class Spec release number */
0x01,
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
0x22, /* bDescriptorType */
sizeof(CustomHID_ReportDescriptor)&0xFF, /* wItemLength: Total length of Report descriptor :36 bytes*/
(sizeof(CustomHID_ReportDescriptor)>>8)&0xFF,
/******************** Descriptor of Custom HID endpoints ******************/
/* 27 */
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
0x81, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
0x08, /* wMaxPacketSize: 64 Bytes max */
0x00,
0x0A, /* bInterval: Polling Interval (32 ms) */
/* 34 */
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
/* Endpoint descriptor type */
0x01, /* bEndpointAddress: */
/* Endpoint Address (OUT) */
0x03, /* bmAttributes: Interrupt endpoint */
0x08, /* wMaxPacketSize: 64 Bytes max */
0x00,
0x0A, /* bInterval: Polling Interval (10 ms) */
//下面是自己添加的hid设备相关描述//
/************** Descriptor of 2/0 HID interface ****************/
/* 41 */
0x09, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType: Interface descriptor type */
0x01, /* bInterfaceNumber: Number of Interface这里改成1 */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints这里改成2 */
0x03, /* bInterfaceClass: HID */
0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0x00, /* iInterface: Index of string descriptor */
/******************** Descriptor of 2/0 HID ********************/
/* 50 */
0x09, /* bLength: HID Descriptor size */
HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */
0x10, /*bcdHID: HID Class Spec release number*/
0x01,
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
0x22, /* bDescriptorType */
sizeof(HID_driver_ReportDescriptor)&0xFF, /* wItemLength: Total length of Report descriptor :36 bytes*/
(sizeof(HID_driver_ReportDescriptor)>>8)&0xFF,
/******************** Descriptor of 2/0 HID endpoints :3 In, Interrupt, 3 ms******************/
/* 59 */
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
0x82, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
0x40, /* wMaxPacketSize: 10 Bytes max */
0x00,
0x22, /* bInterval: Polling Interval (10 ms) */
/******************** Descriptor of 2/0 HID endpoints :3 Out, Interrupt, 3 ms******************/
/* 66 */
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
0x02, /* bEndpointAddress: Endpoint Address (out) */
0x03, /* bmAttributes: Interrupt endpoint */
0x40, /* wMaxPacketSize: 10 Bytes max */
0x00,
0x0A, /* bInterval: Polling Interval (10 ms) */
/* 73 */
///添加结束//
; /* CustomHID_ConfigDescriptor */
(1)因为设备usb插入电脑需要被识别成两个设备,所以上述的字段bNumInterfaces,需要改成2。
(2)根据hid设备相关标准,往结构中添加设备配置描述字段,添加完之后记得修改CUSTOMHID_SIZ_CONFIG_DESC数组大小的宏定义。
(3)我们添加了新的一个设备接口,而前面的hid键盘是第一个设备,所以我们添加的是第二个设备,因此我们需要将bInterfaceNumber字段,依次累加,第一个设备是0,所以我们这里就是1.
(4)usb通信的数据收发都是通过端点的,而我们第二个设备使用了两个端点,即一收一发,所以bNumEndpoints 要改成2
(5)然后我这次增加的设备是无类型的,所以nInterfaceProtocol就是0
(6)在hid接口配置的信息结构中,需要填上,该设备的描述信息结构大小,即wItemLength应该要调描述信息结构的
(7)我们增加的hid设备接口,使用的是端口2。端口0是默认的控制交互的端点,端口1是前面hid键盘的通信端点,我们使用的是端点2。
端点2的输入端点bEndpointAddress字段需要配置成0x82,输出端点需要配置为0x02。原因请看下图详解。
(8)对于数据的收发,usb中提供了四种方式:中断传输、批量传输、控制传输、 同步传输。对于数据量不大的业务一般使用中断传输就好,所以上述端点bmAttributes字段配置为0x03。更多详解,请看下图。
(9)我使用的是中断传输数据,但这中断只是usb内部的收发机制吧(具体的没去了解),然后我们收发数据,间隔是通过bInterval字段设置的时间去端点收发数据函数执行代码。故,如果bInterval字段设置间隔太长会影响数据的吞吐量,这个需要看具体需求而定。
修改完上述的hid接口配置信息后,需要给我们新增的hid设备增加接口的设备描述信息,该描述信息具体的字段文档说明,没找到,我是直接复制现成的。
const uint8_t HID_driver_ReportDescriptor[HID_driver_SIZ_REPORT_DESC] =
//vendor
0x06, 0x00, 0xFF, //Usage Page (Vendor-Defined 29)
0x09, 0x92, //Usage (Vendor-Defined 146)
0xA1, 0x01, //Collection (Application)
0x19, 0x00, //Usage Minimum (Undefined)
0x2A, 0xFF, 0x00, //Usage Maximum (Vendor-Defined 255)
0x15, 0x00, //Logical Minimum (0)
0x26, 0xFF, 0x00, //Logical Maximum (255)
0x75, 0x08, //Report Size (8)
0x95, 0x40, //Report Count (63)
0x91, 0x00, //Output (Data,Ary,Abs,NWrp,Lin,Pref,NNul,NVol,Bit)
0x19, 0x00, //Usage Minimum (Undefined)
0x2a, 0xFF, 0x00, //Usage Maximum (Vendor-Defined 255)
0x81, 0x00, //Input (Data,Ary,Abs)
0xC0, //End Collection
;
记得按照实际定义HID_driver_SIZ_REPORT_DESC宏的大小。
步骤2:修改usb_desc.h文件
该步骤实为对步骤1所修改的,在头文件修改宏,或增加定义。
//在头文件修改CUSTOMHID_SIZ_CONFIG_DESC宏定义大小
//自己去算算CustomHID_ConfigDescriptor结构大小就知道是73
#define CUSTOMHID_SIZ_CONFIG_DESC 73
//在头文件新增
#define HID_driver_SIZ_REPORT_DESC 31
#define HID_driver_OFF_HID_DESC 50
extern const uint8_t HID_driver_ReportDescriptor[HID_driver_SIZ_REPORT_DESC];
步骤3:修改usb_endp.c文件
因为我们新增了一个设备接口,使用端点2进行数据传输,所以我们要在usb_endp.c仿制端点1的数据收发,实现端点2函数。
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief EP1 OUT Callback Routine.
*/
void EP1_OUT_Callback(void)
/* Enable the receive of data on EP1 */
SetEPRxStatus(ENDP1, EP_RX_VALID);
/**
* @brief EP1 IN Callback Routine.
*/
void EP1_IN_Callback(void)
void EP2_OUT_Callback(void)
USER_USB_HIDEP2_RX_LEN = USB_GetEpRxCnt(ENDP2);
USB_CopyPMAToUserBuf((unsigned char*)USER_USB_HIDEP2_RX_Buf, ENDP2_RXADDR, USER_USB_HIDEP2_RX_LEN);
HtClient_RcvBufDataIn(MODE_HID2, USER_USB_HIDEP2_RX_Buf, USER_USB_HIDEP2_RX_LEN);
/* Enable the receive of data on EP2 */
SetEPRxStatus(ENDP2, EP_RX_VALID);
void EP2_IN_Callback(void)
步骤4:修改usb_conf.h文件
修改完usb_endp.c文件,我们需要屏蔽usb_conf.h文件中对EP2_IN_Callback和EP2_OUT_Callback函数的定义。
另外,我们需要定义usb收发数据的buf地址。因为usb的工作机制是,数据来了先缓存到usb接收缓存buf,然后按照到了usb数据轮询查看时间,发现有数据后,通过回调EPx_OUT_Callback函数,将数据从该buf拷贝出来,也就是说EPx_OUT_Callback就是usb接收数据的地方。
然后usb有对应的buf用以存放接收的数据,但是需要我们手动设置端点存放数据的起始地址,又因为hid固定是发64Byte一帧数据,所以收发地址依次递增64Byte就行。
以下就是我修改后的usb_conf.h文件。
#ifndef __USB_CONF_H__
#define __USB_CONF_H__
/*-------------------------------------------------------------*/
/* EP_NUM */
/* defines how many endpoints are used by the device */
/*-------------------------------------------------------------*/
#define EP_NUM (3) //这里要修改为3 端点0+端点1+端点2 =3个端点
/*-------------------------------------------------------------*/
/* -------------- Buffer Description Table -----------------*/
/*-------------------------------------------------------------*/
/* buffer table base address */
/* buffer table base address */
#define BTABLE_ADDRESS (0x00)
/* EP0 */
/* rx/tx buffer base address */
#define ENDP0_RXADDR (0x18)//这个起始地址好像可以随意?具体没深入研究
#define ENDP0_TXADDR (0x58)//依次递增64Byte就系,也就是0x40
/* EP1 */
/* tx buffer base address */
#define ENDP1_TXADDR (0x98)
#define ENDP1_RXADDR (0xD8)
/* EP2 */
/* tx buffer base address */
#define ENDP2_TXADDR (0x118) //ENDP2_TXADDR+0x40开始
#define ENDP2_RXADDR (0x158)
/*-------------------------------------------------------------*/
/* ------------------- STS events -------------------------*/
/*-------------------------------------------------------------*/
/* IMR_MSK */
/* mask defining which events has to be handled */
/* by the device application software */
//#define IMR_MSK (CTRL_CTRSM | CTRL_WKUPM | CTRL_SUSPDM | CTRL_ERRORM | CTRL_SOFM \\
// | CTRL_ESOFM | CTRL_RSTM )
#define IMR_MSK (CTRL_CTRSM | CTRL_RSTM)
/* CTR service routines */
/* associated to defined endpoints */
//#define EP1_IN_Callback USB_ProcessNop
//#define EP2_IN_Callback USB_ProcessNop //我注释的
#define EP3_IN_Callback USB_ProcessNop
#define EP4_IN_Callback USB_ProcessNop
#define EP5_IN_Callback USB_ProcessNop
#define EP6_IN_Callback USB_ProcessNop
#define EP7_IN_Callback USB_ProcessNop
//#define EP1_OUT_Callback USB_ProcessNop
//#define EP2_OUT_Callback USB_ProcessNop //我注释的
#define EP3_OUT_Callback USB_ProcessNop
#define EP4_OUT_Callback USB_ProcessNop
#define EP5_OUT_Callback USB_ProcessNop
#define EP6_OUT_Callback USB_ProcessNop
#define EP7_OUT_Callback USB_ProcessNop
#endif /*__USB_CONF_H__*/
步骤5:修改usb_prop.c文件
(1)我们在usb_des.c增加了新的hid接口以及相关的接口配置信息和设备描述信息,这些信息都将会在usb_prop.c调用到。仿制原有的hid键盘设备的代码,在usb_prop.c文件中,我们新增了两个变量。
//hid设备描述信息
USB_OneDescriptor HID_driver_Report_Descriptor = (uint8_t*)HID_driver_ReportDescriptor, HID_driver_SIZ_REPORT_DESC;
//hid设备接口描述信息
USB_OneDescriptor HID_driver_Hid_Descriptor = (uint8_t*)CustomHID_ConfigDescriptor + HID_driver_OFF_HID_DESC, CUSTOMHID_SIZ_HID_DESC;
然后增加获取hid设备接口信息和设备描述信息的函数。
uint8_t *HID_driver_GetReportDescriptor(uint16_t Length)
return Standard_GetDescriptorData(Length, &HID_driver_Report_Descriptor);
uint8_t *HID_driver_GetHIDDescriptor(uint16_t Length)
return Standard_GetDescriptorData(Length, &HID_driver_Hid_Descriptor);
(2)修改获取设备信息函数。下面通过pInformation->USBwIndex0来区分获取不同的设备信息,而pInformation->USBwIndex0跟我们在usb_desc.c下的CustomHID_ConfigDescriptor结构中的bInterfaceNumber有关。一般bInterfaceNumber从0开始,所以下面的pInformation->USBwIndex0是从0-1遍历。
/**
* @brief Handle the data class specific requests.
* @param Request Nb.
*/
USB_Result CustomHID_Data_Setup(uint8_t RequestNo)
uint8_t* (*CopyRoutine)(uint16_t);
// if (pInformation->USBwIndex != 0)
//return UnSupport;
CopyRoutine = NULL;
if ((RequestNo == GET_DESCRIPTOR) && (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))
&& (pInformation->USBwIndex0 < 3))
if (pInformation->USBwValue1 == REPORT_DESCRIPTOR)
//原来的hid键盘设备
if (pInformation->USBwIndex0 == 0)
CopyRoutine = CustomHID_GetReportDescriptor;
//我们新增的hid设备,为什么是1.是我们在hid接口描述bInterfaceNumber中写的是1
else if (pInformation->USBwIndex0 == 1)
CopyRoutine = HID_driver_GetReportDescriptor;
else if (pInformation->USBwValue1 == HID_DESCRIPTOR_TYPE)
//原来的hid键盘设备
if (pInformation->USBwIndex0 == 0)
CopyRoutine = CustomHID_GetHIDDescriptor;
//我们新增的hid设备,为什么是1.是我们在hid接口描述bInterfaceNumber中写的是1
else if (pInformation->USBwIndex0 == 1)
CopyRoutine = HID_driver_GetHIDDescriptor;
/* End of GET_DESCRIPTOR */
/*** GET_PROTOCOL, GET_REPORT, SET_REPORT ***/
else if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)))
switch (RequestNo)
case GET_PROTOCOL:
CopyRoutine = CustomHID_GetProtocolValue;
break;
case SET_REPORT:
CopyRoutine = CustomHID_SetReport_Feature;
Request = SET_REPORT;
break;
default:
break;
if (CopyRoutine == NULL)
return UnSupport;
pInformation->Ctrl_Info.CopyData = CopyRoutine;
pInformation->Ctrl_Info.Usb_wOffset = 0;
(*CopyRoutine)(0);
return Success;
(3)修改usb的CustomHID_Reset函数。注意USB_SetEpTxCnt函数,一定要设为0,否则usb会定时上报上次发送的数据,这是一个小坑。
/**
* @brief Custom HID reset routine.
*/
void CustomHID_Reset(void)
/* Set CustomHID_DEVICE as not configured */
pInformation->CurrentConfiguration = 0;
pInformation->CurrentInterface = 0; /*the default Interface*/
/* Current Feature initialization */
pInformation->CurrentFeature = CustomHID_ConfigDescriptor[7];
USB_SetBuftab(BTABLE_ADDRESS);
/* Initialize Endpoint 0 */
USB_SetEpType(ENDP0, EP_CONTROL);
SetEPTxStatus(ENDP0, EP_TX_STALL);
USB_SetEpRxAddr(ENDP0, ENDP0_RXADDR);
USB_SetEpTxAddr(ENDP0, ENDP0_TXADDR);
USB_ClrStsOut(ENDP0);
USB_SetEpRxCnt(ENDP0, Device_Property.MaxPacketSize);
USB_SetEpRxValid(ENDP0);
/* Initialize Endpoint 1 */
USB_SetEpType(ENDP1, EP_INTERRUPT);
USB_SetEpTxAddr(ENDP1, ENDP1_TXADDR);
USB_SetEpRxAddr(ENDP1, ENDP1_RXADDR);
USB_SetEpTxCnt(ENDP1, 0);//这里设置需要设置为0,不然usb会自己一直发上次发送的数据
USB_SetEpRxCnt(ENDP1, HIDEP1_REPORT_COUNT);
SetEPRxStatus(ENDP1, EP_RX_VALID);
SetEPRxStatus(ENDP1, EP_TX_VALID);
/* Initialize Endpoint 2 */
USB_SetEpType(ENDP2, EP_INTERRUPT);
USB_SetEpTxAddr(ENDP2, ENDP2_TXADDR);
USB_SetEpRxAddr(ENDP2, ENDP2_RXADDR);
USB_SetEpTxCnt(ENDP2, 0);//这里设置需要设置为0,不然usb会自己一直发上次发送的数据
USB_SetEpRxCnt(ENDP2, HIDEP2_REPORT_COUNT);
SetEPTxStatus(ENDP2, EP_TX_VALID);
SetEPRxStatus(ENDP2, EP_RX_VALID);
/* Set this device to response on default address */
USB_SetDeviceAddress(0);
bDeviceState = ATTACHED;
步骤6:修改usb_prop.h文件
在头文件添加一下函数的声明就好了。
//添加上函数的声明
uint8_t *HID_driver_GetReportDescriptor(uint16_t Length);
uint8_t *HID_driver_GetHIDDescriptor(uint16_t Length);
步骤7:修改hid数据发送函数(可选)
hid的数据发送,可以通过端点的发送函数,发送,也可以自己调用相关接口发送,以下是分享我的发送函数格式。
#define HIDEP1_REPORT_COUNT (8)
#define HIDEP2_REPORT_COUNT (64)
uint8_t USER_USB_HIDEP1_TX_LEN = 0;
uint8_t USER_USB_HIDEP1_RX_LEN = 0;
uint8_t USER_USB_HIDEP1_TX_Buf[HIDEP1_REPORT_COUNT] =0;
uint8_t USER_USB_HIDEP1_RX_Buf[HIDEP1_REPORT_COUNT] =0;
uint8_t USER_USB_HIDEP2_TX_LEN = 0;
uint8_t USER_USB_HIDEP2_RX_LEN = 0;
uint8_t USER_USB_HIDEP2_TX_Buf[HIDEP2_REPORT_COUNT] =0;
uint8_t USER_USB_HIDEP2_RX_Buf[HIDEP2_REPORT_COUNT] =0;
int USBHID1_SendData(uint8_t *data, int dataSize)
uint16_t delayMsCnt = 0;
uint16_t tempSize = 0;
uint16_t sendSize = 0;
if(bDeviceState != CONFIGURED)
return -1;
if(dataSize == 0)
return -2;
do
memset(USER_USB_HIDEP1_TX_Buf, 0, HIDEP1_REPORT_COUNT);
if(dataSize>HIDEP1_REPORT_COUNT)
tempSize = HIDEP1_REPORT_COUNT;
else
tempSize = dataSize;
memcpy(USER_USB_HIDEP1_TX_Buf, (uint8_t*)(data + sendSize), tempSize);
USER_USB_HIDEP1_TX_LEN = tempSize;
dataSize -= tempSize;
sendSize += tempSize;
USB_SilWrite(ENDP1, USER_USB_HIDEP1_TX_Buf, HIDEP1_REPORT_COUNT);
USB_SetEpTxValid(ENDP1);
while(dataSize>0);
//数据发完之后清零
delay_ms(20);
memset(USER_USB_HIDEP1_TX_Buf, 0, HIDEP1_REPORT_COUNT);
USB_SilWrite(ENDP1, USER_USB_HIDEP1_TX_Buf, HIDEP1_REPORT_COUNT);
USB_SetEpTxValid(ENDP1);
return sendSize;
int USBHID2_SendData(uint8_t *data, int dataSize)
uint16_t delayMsCnt = 0;
uint16_t tempSize = 0;
uint16_t sendSize = 0;
if(bDeviceState != CONFIGURED)
return -1;
if(dataSize == 0)
return -2;
do
memset(USER_USB_HIDEP2_TX_Buf, 0, HIDEP2_REPORT_COUNT);
if(dataSize>HIDEP2_REPORT_COUNT)
tempSize = HIDEP2_REPORT_COUNT;
else
tempSize = dataSize;
memcpy(USER_USB_HIDEP2_TX_Buf, (uint8_t*)(data + sendSize), tempSize);
USER_USB_HIDEP2_TX_LEN = tempSize;
dataSize -= tempSize;
sendSize += tempSize;
USB_SilWrite(ENDP2, USER_USB_HIDEP2_TX_Buf, HIDEP2_REPORT_COUNT);
USB_SetEpTxValid(ENDP2);
while(dataSize>0);
return sendSize;
修改到此结束。
5 结束
好了,经过上述的修改,基本上就可以完成实验的目标,一个usb接口模拟出多个usb设备。如下图示:
以上是关于62 stm32 usb自定义hid复合设备修改实验的主要内容,如果未能解决你的问题,请参考以下文章
STM32CubeMX学习笔记(46)——USB接口使用(HID自定义设备)