您的位置 首页 资料

STM32 USB-HID通讯移植过程

最近发现很多人对STM32的USB通信很感兴趣。要将USB的通信协议搞懂确实是一个比较漫长的过程。但是USB的HID通信无论是上位机的设计还是STM32…

最近发现许多人对STM32的USB通讯很感兴趣。要将USB的通讯协议搞懂确实是一个比较绵长的进程。可是USB的HID通讯无论是上位机的规划仍是STM32程序的编程都十分的简略。仅仅我想许多人都不知道罢了。这篇文章的意图是让咱们以最短的时刻将USB加到你的设备中。假如想学得更深就靠咱们。

HID仅仅合适低速传输,其理论上能够到达64KB/S,但多因为windows体系和硬件的联系一般达不到这个传输数度。但这个速度关于一般体系的操控和数据传输都现已足够了,并且是免驱,省去了许多费事。假如您需求高速传输可参阅我的别的一篇文章《STM32的USB例程修正过程》文章在http://blog.csdn.net/cy757/archive/2010/01/01/5117610.aspx

一、安装完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]是装备描述符,留意如下

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等中止内的代码删去。

翻开usb_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);

}

五、usb_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,阐明发送完毕。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ziliao/268236.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部