请选择 进入手机版 | 继续访问电脑版
搜索
查看: 39230|回复: 60

[分享] STM32 USB-HID通信移植步骤STM32 USB HID键盘例程

  [复制链接]

该用户从未签到

7

主题

23

帖子

0

蝴蝶豆

初级会员

最后登录
2020-1-6
发表于 2016-7-24 16:52:09 | 显示全部楼层 |阅读模式
STM32 USB HID键盘例程

最全USB HID开发资料,悉心整理一个月,亲自测试

通过STM32CUbeMX建立USB HID的双向通讯实验成功


发现很多人对STM32的USB通信很感兴趣。要将USB的通信协议搞懂确实是一个比较漫长的过程。但是USB的HID通信无论是上位机的设计还是STM32程序的编程都非常的简单。只是我想很多人都不知道而已。这篇文章的目的是让大家以最短的时间将USB加到你的设备中。如果想学得更深就靠大家。


HID只是适合低速传输,其理论上可以达到64KB/S,但多由于windows系统和硬件的关系一般达不到这个传输数度。但这个速度对于一般系统的控制和数据传输都已经足够了,而且是免驱,省去了很多麻烦。如果您需要高速传输可参考我的另外一篇文章《STM32的USB例程修改步骤》文章在

一、安装完MDK后请打开C:/Keil/ARM/Examples/ST/STM32F10xUSBLib/Demos路径,将Custom_HID在同一个目录下复制一份,如果你要放到其他路径你需要在MDK Options for target的C/C++中添加USB的头文件路径(MDK下的/INC/ST/STM32F10x/USB)。

二、打开usb_desc.c文件,该文件主要包含的端点描述符、设备描述符、配置描述符和字符描述符等。具体请大家参考其他资料了,这里主要说几个常用。

u8 DeviceDescriptor[SIZ_DEVICE_DESC]为USB设备描述符。当中的
0x83, /*idVendor (0x0483)*/
0x04,
0x50, /*idProduct = 0x5750*/
0x57,
//idVender字段。厂商ID号,我们这里取0x0483,仅供实验用。
//实际产品不能随便使用厂商ID号,必须跟USB协会申请厂商ID号。
//注意小端模式,低字节在先。
//idProduct字段。产品ID号,我们这里取0x5750。
//注意小端模式,低字节应该在前。


const u8 ConfigDescriptor[SIZ_CONFIG_DESC]是配置描述符,注意如下
  1. USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
  2. 0x81, /* bEndpointAddress: Endpoint Address (IN) */
  3. 0x03, /* bmAttributes: Interrupt endpoint */
  4. 0x02, /* wMaxPacketSize: 2 Bytes max */
  5. 0x00,
  6. 0x20, /* bInterval: Polling Interval (32 ms) */
  7. /* 34 */
  8. 0x07, /* bLength: Endpoint Descriptor size */
  9. USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
  10. /* Endpoint descriptor type */
  11. 0x01, /* bEndpointAddress: */
  12. /* Endpoint Address (OUT) */
  13. 0x03, /* bmAttributes: Interrupt endpoint */
  14. 0x02, /* wMaxPacketSize: 2 Bytes max */
  15. 0x00,
  16. 0x20, /* bInterval: Polling Interval (20 ms) */
复制代码

上面包含了“输入端点描述符”和“输出端点描述符”。
//wMaxPacketSize字段。该端点的最大包长。
//bInterval字段。端点查询的时间,

为了实现更高速的通信我们修改如下:
  1. /******************** Descriptor of endpoint ********************/
  2. /* 27 */
  3. 0x07, /*bLength: Endpoint Descriptor size*/
  4. USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/
  5. 0x81, /*bEndpointAddress: Endpoint Address (IN)*/
  6. 0x03, /*bmAttributes: Interrupt endpoint*/
  7. 0x40, /*wMaxPacketSize: 64 Byte max */
  8. 0x00,
  9. 0x0A, /*bInterval: Polling Interval (10 ms)*/
  10. /* 34 */
  11. /******************** Descriptor of endpoint ********************/
  12. /* 27 */
  13. 0x07, /*bLength: Endpoint Descriptor size*/
  14. USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/
  15. 0x01, /*bEndpointAddress: Endpoint Address (OUT)*/
  16. 0x03, /*bmAttributes: Interrupt endpoint*/
  17. 0x40, /*wMaxPacketSize: 64 Byte max */
  18. 0x00,
  19. 0x0A, /*bInterval: Polling Interval (10 ms)*/

  20. const u8 ReportDescriptor[SIZ_REPORT_DESC]为HID专用的报告描述符,具体的大家就参考资料了,这里可以直接复制了。
  21. const u8 CustomHID_ReportDescriptor[CUSTOMHID_SIZ_REPORT_DESC] =
  22. {
  23. 0x05, 0xFF, // USAGE_PAGE(User define)
  24. 0x09, 0xFF, // USAGE(User define)
  25. 0xa1, 0x01, // COLLECTION (Application)
  26. 0x05, 0x01, // USAGE_PAGE(1)
  27. 0x19, 0x00, // USAGE_MINIMUM(0)
  28. 0x29, 0xFF, // USAGE_MAXIMUM(255)
  29. 0x15, 0x00, // LOGICAL_MINIMUM (0)
  30. 0x25, 0xFF, // LOGICAL_MAXIMUM (255)
  31. 0x75, 0x08, // REPORT_SIZE (8)
  32. 0x95, 0x40, // REPORT_COUNT (64)
  33. 0x81, 0x02, // INPUT (Data,Var,Abs)
  34. 0x05, 0x02, // USAGE_PAGE(2)
  35. 0x19, 0x00, // USAGE_MINIMUM (0)
  36. 0x29, 0xFF, // USAGE_MAXIMUM (255)
  37. 0x15, 0x00, // LOGICAL_MINIMUM (0)
  38. 0x25, 0xFF, // LOGICAL_MAXIMUM (255)
  39. 0x95, 0x08, // REPORT_COUNT (8)
  40. 0x75, 0x40, // REPORT_SIZE (64)
  41. 0x91, 0x02, // OUTPUT (Data,Var,Abs)
  42. 0xc0 // END_COLLECTION
  43. }; /* ReportDescriptor */

  44. const u8 CustomHID_StringVendor[CUSTOMHID_SIZ_STRING_VENDOR]
  45. const u8 StringProduct[SIZ_STRING_PRODUCT]
  46. const u8 StringSerial[SIZ_STRING_SERIAL]
复制代码

分别是“厂商字符”、“产品字符”、“产品序列号”,这些将在USB HID设备加载的时候显示。但是这需要这些字符要求为Unicode编码,你需要将你要显示的字符先转为Unicode编码。最好大家还要根据各个数组的长度修改如下定义。

  1. #define CUSTOMHID_SIZ_REPORT_DESC 39
  2. #define CUSTOMHID_SIZ_STRING_VENDOR 64
  3. #define CUSTOMHID_SIZ_STRING_PRODUCT 28
  4. #define CUSTOMHID_SIZ_STRING_SERIAL 26
复制代码

三、打开hw_config.c文件,将那些没有的函数删除,只保留如下函数
a) Set_System(void)
b) void Set_USBClock(void)
c) void USB_Interrupts_Config(void)
d) void USB_Cable_Config (FunctionalState NewState)
特别要注意最后一个函数,其主要作用是控制USB的上拉电阻,让电脑检测USB设备是否连接的。


四、打开stm32f10x_it.c文件,把EXTI15_10_IRQHandler等中断内的代码删除。
打开usb_prop.c文件,修改如下:
  1. void CustomHID_Reset(void)
  2. {
  3. /* Set Joystick_DEVICE as not configured */
  4. pInformation->Current_Configuration = 0;
  5. pInformation->Current_Interface = 0;/*the default Interface*/
  6. SetBTABLE(BTABLE_ADDRESS);

  7. /* Initialize Endpoint 0 */
  8. SetEPType(ENDP0, EP_CONTROL);
  9. SetEPTxStatus(ENDP0, EP_TX_STALL);
  10. SetEPRxAddr(ENDP0, ENDP0_RXADDR);
  11. SetEPTxAddr(ENDP0, ENDP0_TXADDR);
  12. Clear_Status_Out(ENDP0);
  13. SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
  14. SetEPRxValid(ENDP0);

  15. /* Initialize Endpoint 1 */
  16. SetEPType(ENDP1, EP_INTERRUPT);
  17. SetEPTxAddr(ENDP1, ENDP1_TXADDR);
  18. SetEPTxCount(ENDP1, 64);
  19. SetEPRxStatus(ENDP1, EP_RX_DIS);
  20. SetEPTxStatus(ENDP1, EP_TX_NAK);

  21. /* Initialize Endpoint 1 */
  22. // SetEPType(ENDP1, EP_INTERRUPT);
  23. SetEPRxAddr(ENDP1, ENDP1_RXADDR);
  24. SetEPRxCount(ENDP1, 64);
  25. // SetEPTxStatus(ENDP1, EP_TX_DIS);
  26. SetEPRxStatus(ENDP1, EP_RX_VALID);
  27. /* Set this device to response on default address */
  28. SetDeviceAddress(0);
  29. }
复制代码

五、usb_endp.c文件
  1. void EP1_OUT_Callback(void)
  2. {
  3. 这些写接收代码
  4. }
复制代码

六、数据发送和接收,举例说明
1、数据接收
  1. u8 DataLen;
  2. DataLen = GetEPRxCount(ENDP1);
  3. PMAToUserBufferCopy(TX1_buffer, ENDP1_RXADDR, DataLen);
  4. SetEPRxValid(ENDP1);
  5. USART1_Send(DataLen);
  6. count_out = 1;
复制代码

2、数据发送
  1. UserToPMABufferCopy(InBuffer, GetEPTxAddr(ENDP1), 64);
  2. SetEPTxCount(ENDP1, 64);
  3. SetEPTxValid(ENDP1);
复制代码

如果你发送数据较为频繁,每次发送前应使用GetEPTxStatus(ENDP1)检测上次发送是否完成。如果端点状态处于EP_TX_VALID,说明发送未结束,如果端点状态处于EP_TX_NAK,说明发送结束。


(by xidongs)
回复

使用道具 举报

该用户从未签到

22

主题

1027

帖子

12

蝴蝶豆

金牌会员

最后登录
2021-7-23
发表于 2016-7-25 08:02:01 | 显示全部楼层
谢谢分享,标记一下
回复 支持 反对

使用道具 举报

该用户从未签到

100

主题

3786

帖子

1

蝴蝶豆

论坛元老

最后登录
2024-1-14
发表于 2016-7-25 10:18:29 | 显示全部楼层
回复

使用道具 举报

该用户从未签到

0

主题

56

帖子

0

蝴蝶豆

初级会员

最后登录
2019-12-8
发表于 2016-7-25 15:20:24 | 显示全部楼层
谢谢分享,标记一下
回复 支持 反对

使用道具 举报

该用户从未签到

2

主题

796

帖子

2

蝴蝶豆

金牌会员

最后登录
2019-3-6
发表于 2016-7-25 23:16:14 | 显示全部楼层
谢谢分享. 学习了
回复 支持 反对

使用道具 举报

该用户从未签到

23

主题

722

帖子

0

蝴蝶豆

金牌会员

最后登录
2020-12-20
发表于 2016-7-26 08:37:29 | 显示全部楼层
谢谢,分享
回复

使用道具 举报

该用户从未签到

2

主题

49

帖子

0

蝴蝶豆

中级会员

最后登录
2020-3-13
发表于 2016-7-26 14:45:23 | 显示全部楼层
支持下,标记下!
回复 支持 反对

使用道具 举报

该用户从未签到

1

主题

6

帖子

0

蝴蝶豆

新手上路

最后登录
1970-1-1
发表于 2016-8-7 12:24:50 | 显示全部楼层
感谢分享
回复

使用道具 举报

该用户从未签到

0

主题

31

帖子

0

蝴蝶豆

中级会员

最后登录
2018-2-8
发表于 2016-8-9 16:32:26 | 显示全部楼层
谢谢分享,标记一下
回复 支持 反对

使用道具 举报

该用户从未签到

1

主题

8

帖子

0

蝴蝶豆

新手上路

最后登录
2019-11-5
发表于 2016-8-10 22:48:08 | 显示全部楼层
谢谢,已经移植可以识别,但是上位机软件怎么写啊
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|论坛-意法半导体STM32/STM8技术社区

GMT+8, 2024-3-29 18:30 , Processed in 1.182017 second(s), 40 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表