STM32 USB HID开发实例,实现USB双向通信。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
在STM32 ARM平台上实现USB与PC端得通信(IC为STM32F10XX系列)。本文提供一个例程(已测试通过),不用了解任何USB协议(当然了解USB相关协议或描述表的意义是很必要的),在此例程上,稍作修改,即可开展你的项目或学习或进行产品开发。
在ST中我们可以获得了USB相关的一个HID例程,但是官方例子中只是用到2个端点。数据只收不发。
本例程中,用到了3个USB端点,实现PC上位机与下位机见双向通信。EP0为控制端点(必须的,这是因为系统默认端点0作为控制传输端点),EP1为INTERRUPT OUT端点(数据输出端,即PC向MCU发送数据段),EP2为INTERRUPT OUT端点(数据输入端,即MCU向PC发送数据)。
实现过程,我们需要修改一下HID的描述表,修改如下(有详细注释)
/* USB Configuration Descriptor */
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
const u8 CustomHID_ConfigDescriptor[CUSTOMHID_SIZ_CONFIG_DESC] =
{
0x09, /* bLength: Configuation Descriptor size */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
CUSTOMHID_SIZ_CONFIG_DESC,
/* wTotalLength: Bytes returned */
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing
the configuration*/
0xC0, /* bmAttributes: Bus powered */
/*Bus powered: 7th bit, Self Powered: 6th bit, Remote wakeup: 5th bit, reserved: 4..0 bits */
0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */
// 0x96, /* MaxPower 300 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 */
0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x00, /* 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 */
CUSTOMHID_SIZ_REPORT_DESC,/* wItemLength: Total length of Report descriptor */
0x00,
/******************** Descriptor of Custom HID endpoints ******************/
/* 27 */
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
0x82, /* bEndpointAddress: Endpoint Address (IN) */
// bit 3...0 : the endpoint number
// bit 6...4 : reserved
// bit 7 : 0(OUT), 1(IN)
0x03, /* bmAttributes: Interrupt endpoint */
0x40,//0x02, /* wMaxPacketSize: 20 Bytes max */
0x00,
0x20, /* 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 */
0x40,//0x02, /* wMaxPacketSize: 20 Bytes max */
0x00,
0x10, /* bInterval: Polling Interval (16 ms) */
/* 41 */
}; /* CustomHID_ConfigDescriptor */
关于如何理解HID 描述表,请参考USB HID协议1.1版本,相关资料可以在网络上搜索得到。
在此,现提供KEIL MDK 和 IAR EWARM 5.4版本的例子,欢迎下载。萝卜青菜,喜欢用MDK,就MDK,喜欢EWARM,就EWARM。同样这里有见有意思的事,在全编译的情况下,EWARM要比MDK编译速度要快一些。
相关测试结果如下:
通过呀呀USB_hid 或Bus Hound相关工具,先发一包数据给下位机,这样下位机每隔1s会发送一包数据。结果如图:
呀USB_hid可以在本博客上下载^_^: http://blog.ednchina.com/itspy
源码下载:
KEIL MDK 版本(4.0):
https://static.assets-stash.eet-china.com/album/old-resources/2010/6/22/97c50783-e683-4e89-9e7d-d9e41a7e9cd2.rar
IAR EWARM 版本(v5.4):
https://static.assets-stash.eet-china.com/album/old-resources/2010/6/22/97c50783-e683-4e89-9e7d-d9e41a7e9cd2.rar" target=_blank>
用户377235 2016-3-2 21:05
为什么 只能发比22个字节少的数呢
用户967597 2015-6-12 11:44
用户403160 2013-10-20 22:00
由衷地谢谢您的分享
用户377235 2013-3-14 20:27
首先感谢您给我们这些初学者提供这么好的资源。在学习的过程中,我尝试在板子上跑您的程序,但是我一直没弄明白USB_Receive*** 这个变量是怎么控制的?他是软件控制,还是当USB接收到上位机的数据后硬件控制的??比如这段程序 USB_Interrupts_Config(); Set_USBClock(); USB_Init(); USB_ReceiveF.lg = FALSE; while(1) // { if (TimeCount && USB_ReceiveF-lg == TRUE) //收到后上位机的数据后,将1S发送一次数据给PC { USB_SendString("Hi,PC! I'm STM32-ARM"); TimeCount = 0x00; } } USB_Receive***怎么变成的TRUE呢??
用户421709 2012-8-10 14:46
用户377235 2012-6-9 18:08
学习中 非常感谢版主!
用户1313238 2012-4-25 11:26
用户377235 2012-4-12 13:57
问一下,这个双向通信的例程要不要自己制作驱动程序,我用usb调试助手能识别这个设备部
用户191241 2012-3-30 17:27
hjf2002_hk_735514074 2012-2-29 09:43