完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
发现很多人对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)。 评分
|
||
相关推荐
|
||
二、打开u***_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]是配置描述符,注意如下 USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */ 0x81, /* bEndpointAddress: Endpoint Address (IN) */ 0x03, /* bmAttributes: Interrupt endpoint */ 0x02, /* wMaxPacketSize: 2 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 */ 0x02, /* wMaxPacketSize: 2 Bytes max */ 0x00, 0x20, /* bInterval: Polling Interval (20 ms) */ 上面包含了“输入端点描述符”和“输出端点描述符”。 //wMaxPacketSize字段。该端点的最大包长。 //bInterval字段。端点查询的时间, |
|
|
|
|
|
为了实现更高速的通信我们修改如下:
/******************** Descriptor of endpoint ********************/ /* 27 */ 0x07, /*bLength: Endpoint Descriptor size*/ USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/ 0x81, /*bEndpointAddress: Endpoint Address (IN)*/ 0x03, /*bmAttributes: Interrupt endpoint*/ 0x40, /*wMaxPacketSize: 64 Byte max */ 0x00, 0x0A, /*bInterval: Polling Interval (10 ms)*/ /* 34 */ /******************** Descriptor of endpoint ********************/ /* 27 */ 0x07, /*bLength: Endpoint Descriptor size*/ USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/ 0x01, /*bEndpointAddress: Endpoint Address (OUT)*/ 0x03, /*bmAttributes: Interrupt endpoint*/ 0x40, /*wMaxPacketSize: 64 Byte max */ 0x00, 0x0A, /*bInterval: Polling Interval (10 ms)*/ const u8 ReportDescriptor[SIZ_REPORT_DESC]为HID专用的报告描述符,具体的大家就参考资料了,这里可以直接复制了。 const u8 CustomHID_ReportDescriptor[CUSTOMHID_SIZ_REPORT_DESC] = { 0x05, 0xFF, // USAGE_PAGE(User define) 0x09, 0xFF, // USAGE(User define) 0xa1, 0x01, // COLLECTION (Application) 0x05, 0x01, // USAGE_PAGE(1) 0x19, 0x00, // USAGE_MINIMUM(0) 0x29, 0xFF, // USAGE_MAXIMUM(255) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0xFF, // LOGICAL_MAXIMUM (255) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x40, // REPORT_COUNT (64) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x05, 0x02, // USAGE_PAGE(2) 0x19, 0x00, // USAGE_MINIMUM (0) 0x29, 0xFF, // USAGE_MAXIMUM (255) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0xFF, // LOGICAL_MAXIMUM (255) 0x95, 0x08, // REPORT_COUNT (8) 0x75, 0x40, // REPORT_SIZE (64) 0x91, 0x02, // OUTPUT (Data,Var,Abs) 0xc0 // END_COLLECTION }; /* ReportDescriptor */ const u8 CustomHID_StringVendor[CUSTOMHID_SIZ_STRING_VENDOR] const u8 StringProduct[SIZ_STRING_PRODUCT] const u8 StringSerial[SIZ_STRING_SERIAL] |
|
|
|
|
|
分别是“厂商字符”、“产品字符”、“产品序列号”,这些将在USB HID设备加载的时候显示。但是这需要这些字符要求为Unicode编码,你需要将你要显示的字符先转为Unicode编码。你可以到http://computer00.21ic.org/user1/2198/archives/2007/42769.html转换。最好大家还要根据各个数组的长度修改如下定义。
#define CUSTOMHID_SIZ_REPORT_DESC 39 #define CUSTOMHID_SIZ_STRING_VENDOR 64 #define CUSTOMHID_SIZ_STRING_PRODUCT 28 #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等中断内的代码删除。
打开u***_prop.c文件,修改如下: void CustomHID_Reset(void) { /* Set Joystick_DEVICE as not configured */ pInformation->Current_Configuration = 0; pInformation->Current_Interface = 0;/*the default Interface*/ SetBTABLE(BTABLE_ADDRESS); /* Initialize Endpoint 0 */ SetEPType(ENDP0, EP_CONTROL); SetEPTxStatus(ENDP0, EP_TX_STALL); SetEPRxAddr(ENDP0, ENDP0_RXADDR); SetEPTxAddr(ENDP0, ENDP0_TXADDR); Clear_Status_Out(ENDP0); SetEPRxCount(ENDP0, Device_Property.MaxPacketSize); SetEPRxValid(ENDP0); /* Initialize Endpoint 1 */ SetEPType(ENDP1, EP_INTERRUPT); SetEPTxAddr(ENDP1, ENDP1_TXADDR); SetEPTxCount(ENDP1, 64); SetEPRxStatus(ENDP1, EP_RX_DIS); SetEPTxStatus(ENDP1, EP_TX_NAK); /* Initialize Endpoint 1 */ // SetEPType(ENDP1, EP_INTERRUPT); SetEPRxAddr(ENDP1, ENDP1_RXADDR); SetEPRxCount(ENDP1, 64); // SetEPTxStatus(ENDP1, EP_TX_DIS); SetEPRxStatus(ENDP1, EP_RX_VALID); /* Set this device to response on default address */ SetDeviceAddress(0); } |
|
|
|
|
|
五、u***_endp.c文件
void EP1_OUT_Callback(void) { 这些写接收代码 } 六、数据发送和接收,举例说明 1、数据接收 u8 DataLen; DataLen = GetEPRxCount(ENDP1); PMAToUserBufferCopy(TX1_buffer, ENDP1_RXADDR, DataLen); SetEPRxValid(ENDP1); USART1_Send(DataLen); count_out = 1; 2、数据发送 UserToPMABufferCopy(InBuffer, GetEPTxAddr(ENDP1), 64); SetEPTxCount(ENDP1, 64); SetEPTxValid(ENDP1); 如果你发送数据较为频繁,每次发送前应使用GetEPTxStatus(ENDP1)检测上次发送是否完成。如果端点状态处于EP_TX_VALID,说明发送未结束,如果端点状态处于EP_TX_NAK,说明发送结束。 |
|
|
|
|
|
谢谢分享。。。。。。。。
|
|
|
|
|
|
嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-TF卡烧录流程之烧写过程
706 浏览 0 评论
1042 浏览 0 评论
嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-mfgtools烧录流程之烧写原理
1087 浏览 0 评论
请问SPH0641LU4H这款麦克风如何在不使用I2S的情况下,单纯通过GPIO来进行驱动且正常读取数据呢
795 浏览 1 评论
497 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
12094 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-2 01:23 , Processed in 0.516455 second(s), Total 52, Slave 45 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号