STM32 USB-HID通信移植步驟
HID只是適合低速傳輸,其理論上可以達(dá)到64KB/S,但多由于windows系統(tǒng)和硬件的關(guān)系一般達(dá)不到這個(gè)傳輸數(shù)度。但這個(gè)速度對(duì)于一般系統(tǒng)的控制和數(shù)據(jù)傳輸都已經(jīng)足夠了,而且是免驅(qū),省去了很多麻煩。如果您需要高速傳輸可參考我的另外一篇文章《STM32的USB例程修改步驟》文章在http://blog.csdn.net/cy757/archive/2010/01/01/5117610.aspx
一、安裝完MDK后請(qǐng)打開C:/Keil/ARM/Examples/ST/STM32F10xUSBLib/Demos路徑,將Custom_HID在同一個(gè)目錄下復(fù)制一份,如果你要放到其他路徑你需要在MDK Options for target的C/C++中添加USB的頭文件路徑(MDK下的/INC/ST/STM32F10x/USB)。
二、打開usb_desc.c文件,該文件主要包含的端點(diǎn)描述符、設(shè)備描述符、配置描述符和字符描述符等。具體請(qǐng)大家參考其他資料了,這里主要說幾個(gè)常用。
u8 DeviceDescriptor[SIZ_DEVICE_DESC]為USB設(shè)備描述符。當(dāng)中的
0x83, /*idVendor (0x0483)*/
0x04,
0x50, /*idProduct = 0x5750*/
0x57,
//idVender字段。廠商ID號(hào),我們這里取0x0483,僅供實(shí)驗(yàn)用。
//實(shí)際產(chǎn)品不能隨便使用廠商ID號(hào),必須跟USB協(xié)會(huì)申請(qǐng)廠商ID號(hào)。
//注意小端模式,低字節(jié)在先。
//idProduct字段。產(chǎn)品ID號(hào),我們這里取0x5750。
//注意小端模式,低字節(jié)應(yīng)該在前。
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) */
上面包含了“輸入端點(diǎn)描述符”和“輸出端點(diǎn)描述符”。
//wMaxPacketSize字段。該端點(diǎn)的最大包長。
//bInterval字段。端點(diǎn)查詢的時(shí)間,
為了實(shí)現(xiàn)更高速的通信我們修改如下:
/******************** 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專用的報(bào)告描述符,具體的大家就參考資料了,這里可以直接復(fù)制了。
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]
分別是“廠商字符”、“產(chǎn)品字符”、“產(chǎn)品序列號(hào)”,這些將在USB HID設(shè)備加載的時(shí)候顯示。但是這需要這些字符要求為Unicode編碼,你需要將你要顯示的字符先轉(zhuǎn)為Unicode編碼。你可以到http://computer00.21ic.org/user1/2198/archives/2007/42769.html轉(zhuǎn)換。最好大家還要根據(jù)各個(gè)數(shù)組的長度修改如下定義。
#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文件,將那些沒有的函數(shù)刪除,只保留如下函數(shù)
a) Set_System(void)
b) void Set_USBClock(void)
c) void USB_Interrupts_Config(void)
d) void USB_Cable_Config (FunctionalState NewState)
特別要注意最后一個(gè)函數(shù),其主要作用是控制USB的上拉電阻,讓電腦檢測USB設(shè)備是否連接的。
四、打開stm32f10x_it.c文件,把EXTI15_10_IRQHandler等中斷內(nèi)的代碼刪除。
打開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)
{
這些寫接收代碼
}
六、數(shù)據(jù)發(fā)送和接收,舉例說明
1、數(shù)據(jù)接收
u8 DataLen;
DataLen = GetEPRxCount(ENDP1);
PMAToUserBufferCopy(TX1_buffer, ENDP1_RXADDR, DataLen);
SetEPRxValid(ENDP1);
USART1_Send(DataLen);
count_out = 1;
2、數(shù)據(jù)發(fā)送
UserToPMABufferCopy(InBuffer, GetEPTxAddr(ENDP1), 64);
SetEPTxCount(ENDP1, 64);
SetEPTxValid(ENDP1);
如果你發(fā)送數(shù)據(jù)較為頻繁,每次發(fā)送前應(yīng)使用GetEPTxStatus(ENDP1)檢測上次發(fā)送是否完成。如果端點(diǎn)狀態(tài)處于EP_TX_VALID,說明發(fā)送未結(jié)束,如果端點(diǎn)狀態(tài)處于EP_TX_NAK,說明發(fā)送結(jié)束。
評(píng)論