最近在做一个简单的joystick,用来项目调试,既是简单的,那上位机必定不要自己写驱动,利用win7自带的即可。奔着这个目标,花了两天时间整好,中间遇到了不少问题,最大的问题在于USB上。
这是WIN7(设备和打印机)上看到的设置界面
具体事项,下面一一道来。
1、采用STM32F103C8T6+普通摇杆。
2、USB的D+,一定要注意,注意,注意,要接上拉电阻1.5K。否则,USB根本无法被电脑识别。
3、用stm32cube生成项目,包括ADC,USB等。此时生成的代码,是键盘或者鼠标的程序,插上电脑后,即可看到识别出来的设备,我这边选的是鼠标。
4、USB中,用于识别设备的东西,叫描述符,包括设备描述符、配置描述符、端点描述符等,其中最重要的便是,报告描述符,具体可见《USB HID Usage Tables》,其中包括很多实例的报告描述符。此处,便是花了一天多时间才搞明白的,主要还是因为对USB协议不熟悉才造成的。
5、对于stm32cube自动生成的代码中,需要修改的地方主要是
1)、usbd_hid.c下,USBD_HID_CfgDesc[]的wItemLength参数,是报告描述符数组的数目。
2)、usbd_hid.c下,USBD_HID_Desc[]的wItemLength参数,是报告描述符数组的数目。
3)、usbd_hid.c下HID_MOUSE_ReportDesc[],报告描述符数组。
6、以下是usbd_hid.c修改后的相关参考代码:
/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_HID_CONFIG_DESC_SIZ,
/* wTotalLength: Bytes returned */
0x00,
0x01, /*bNumInterfaces: 1 interface*/
0x01, /*bConfigurationValue: Configuration value*/
0x00, /*iConfiguration: Index of string descriptor describing
the configuration*/
0xE0, /*bmAttributes: bus powered and Support Remote Wake-up */
0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/
/************** Descriptor of Joystick Mouse interface ****************/
/* 09 */
0x09, /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
0x00, /*bInterfaceNumber: Number of Interface*/
0x00, /*bAlternateSetting: Alternate setting*/
0x01, /*bNumEndpoints*/
0x03, /*bInterfaceClass: HID*/
0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
0x00,//0x02, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
0, /*iInterface: Index of string descriptor*/
/******************** Descriptor of Joystick Mouse HID ********************/
/* 18 */
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11, /*bcdHID: HID Class Spec release number*/
0x01,
0x00, /*bCountryCode: Hardware target country*/
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
0x22, /*bDescriptorType*/
30,//0xe3,//HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
0,//0x01,//0x00,
/******************** Descriptor of Mouse endpoint ********************/
/* 27 */
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/
HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */
0x00,
HID_FS_BINTERVAL, /*bInterval: Polling Interval (10 ms)*/
/* 34 */
} ;
/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_Desc[USB_HID_DESC_SIZ] __ALIGN_END =
{
/* 18 */
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11, /*bcdHID: HID Class Spec release number*/
0x01,
0x00, /*bCountryCode: Hardware target country*/
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
0x22, /*bDescriptorType*/
30,//0xe3,//HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
0,//0x01,//0x00,
};
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_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,
};
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
0x05,0x01, /*Usage Page(Generic Desktop)*/
0x09,0x04, /*Usage(joystick)*/
0xA1,0x01, /*Collection(Application)*/
0x05,0x01, /**/
0x09,0x01, /**/
0xa1,0x00, /**/
0x09,0x30, /*Usage(X axis)*/
0x09,0x31, /*Usage(Y axis)*/
0x09,0x32, /*Usage(Z axis)*/
0x15,0x81, /*Logical Minimum(-127)*/
0x25,0x7f, /*Logical Maximum(127)*/
// 0x19,0x00, /**/
// 0x29,0xff, /**/
0x95,0x03, /*Report Count(3)*/
0x75,0x08, /*Report Size(8)*/
0x81,0x02, /*Input(Variable)*/
0xc0, /**/
0xC0, /*End Collection*/
};
7、总结:对于USB设备,除了通用描述符外,需要配置详细的描述符,否则,就算电脑识别到了设备,设备也往上发了数据,电脑依然识别不了收到的数据是要怎么处理,做何用途。