1,將STM32的USB枚舉爲HID設備。
2,STM32使用3個端點,端點0用於枚舉用,端點1和2用於數據的發送和接收。
3,端點長度爲64,也就是單次最多可以傳輸64個字節數據。
4,STM32獲取上位機下發的數據並將該數據通過USB原樣返回,同時將數據打印輸出。5,上位機程序通過調用windows的API實現對HID設備的讀寫控制。
原理圖:
說明:實際測試的時候不用這麼複雜的電路,接好PA11和PA12即可,當然在PA12引腳上需要一個上拉電阻,其他電路都可以省略。
HID枚舉成功:
說明:枚舉成功後會自動安裝HID驅動,無需單獨安裝。
上位機程序運行效果圖:
說明:上位機程序是在VS2010環境下寫的,不過可以根據自己需求移植到其他環境中。
單片機運行輸出:
說明:單片機端採用超級終端輸出相關信息,使用的USART1串口,也就是PA9和PA10兩個引腳。
Bus Hound抓取數據截圖:
說明:Bus Hound是一個很不錯的數據抓包工具,調試USB程序相當有用。
部分程序源碼:
STM32的報告描述符:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
const
uint8_t CustomHID_ReportDescriptor[CUSTOMHID_SIZ_REPORT_DESC] = {
0x05,
0x8c, /*
USAGE_PAGE (ST Page) */ 0x09,
0x01, /*
USAGE (Demo Kit) */ 0xa1,
0x01, /*
COLLECTION (Application) */ //
The Input report 0x09,0x03,
//
USAGE ID - Vendor defined 0x15,0x00,
//
LOGICAL_MINIMUM (0) 0x26,0x00,
0xFF, //
LOGICAL_MAXIMUM (255) 0x75,0x08,
//
REPORT_SIZE (8bit) 0x95,0x40,
//
REPORT_COUNT (64Byte) 0x81,0x02,
//
INPUT (Data,Var,Abs) //
The Output report 0x09,0x04,
//
USAGE ID - Vendor defined 0x15,0x00,
//
LOGICAL_MINIMUM (0) 0x26,0x00,0xFF,
//
LOGICAL_MAXIMUM (255) 0x75,0x08,
//
REPORT_SIZE (8bit) 0x95,0x40,
//
REPORT_COUNT (64Byte) 0x91,0x02,
//
OUTPUT (Data,Var,Abs) 0xc0
/*
END_COLLECTION */ };
/*
CustomHID_ReportDescriptor */ |
上位機測試程序:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
/** *
@brief 發送數據後讀取數據 *
@param None *
@retval None */ void
HIDSampleFunc( void )
{
HANDLE
hDev; BYTE
recvDataBuf[1024],reportBuf[1024];; DWORD
bytes; hDev
= OpenMyHIDDevice(0); //
打開設備,不使用重疊(異步)方式 ; if
(hDev == INVALID_HANDLE_VALUE){ printf ( "INVALID_HANDLE_VALUE\n" ); return ;
} reportBuf[0]
= 0; //
輸出報告的報告 ID 是 0 for ( int
i=0;i<REPORT_COUNT;i++){ reportBuf[i+1]=i+1; //將數據存放在數據緩衝區 } printf ( "開始寫數據到設備...\n" ); //
寫入數據到設備,注意,第三個參數值必須爲REPORT_COUNT+1,否則會返回1784錯誤 if
(!WriteFile(hDev, reportBuf, REPORT_COUNT+1, &bytes, NULL)){ printf ( "write
data error! %d\n" ,GetLastError()); return ;
} else { printf ( "成功向設備寫出%d個數據...
\n" ,bytes); } printf ( "開始從設備讀取數據...\n" ); //
從設備讀取數據,注意,第三個參數值必須大於等於REPORT_COUNT+1,否則會返回1784錯誤 if (!ReadFile(hDev,
recvDataBuf, REPORT_COUNT+1, &bytes, NULL)){ //
讀取設備發給主機的數據 printf ( "read
data error! %d\n" ,GetLastError()); return ;
} else { printf ( "成功向設備讀出%d個數據...
\n" ,bytes); } printf ( "設備返回的數據爲:\n" ); //顯示讀取回來的數據 for ( int
i=0;i<REPORT_COUNT;i++){ printf ( "0x%02X
" ,recvDataBuf[i+1]); } printf ( "\n\r" ); } |