STM32F103C8T6 usb gamepad joystick 鼠標手柄鍵盤hid評估學習指南


第一部分、硬件概述

1.1 實物概圖

image
圖1.1Gamepad實物概圖

如圖1.1所示Gamepad評估板配置了8個6*6輕觸按鍵,一個搖桿(Joystick),搭載一顆WS2812B燈珠,並將UART1串口,編程接口(SWD),外接Joystick接口,microUSB接口引出;

1.2 Gamepad原理圖

Gamepad原理圖如圖1.2所示,如看不清可打開Doc目錄下的PDF文檔查閱

image
圖1.2 Gamepad原理圖

第二部分、軟件工具

2.1 軟件概述

在 /Software 目錄下是常用的工具軟件:

  1. Dt2_4:配置USB設備Report描述符的工具;
  2. USBHID調試助手/呀呀USB: USB調試工具,相當於串口調試助手功能;
  3. BUSHound:總線調試工具;
  4. USBlyzer:一款專業的USB協議分析軟件
  5. MDK:常用編譯器;
  6. STM32CubeMX:代碼生成工具;

第三部分、實戰訓練

3.1 實例Eg1_GamePad

目標是實現GamePad:枚舉成XY軸的平面坐標和8個按鍵的USB設備。

3.1.1硬件設計

image
圖1.3 Joystick原理圖
如圖1.3是Joystick原理圖,其中VRX1與VRY1是搖桿的電位器輸出的電壓信號(ADC檢測);SW1則是按鍵,右側H1是外接的Joystick口;

image
圖1.4 KEY原理圖

如圖1.4是KEY原理圖,我們只要配置8個GPIO作為輸入去檢測按鍵信號;

3.1.2 軟件設計

首先是初始化代碼,我們通過STM32cubeMX軟件去生成代碼,具體配置請打開GamePad.ioc查閱,這里不再贅述;
我們的工程使用的是Keil-MDK編譯器,生成的工程目錄如圖1.5

image
圖1.5 工程目錄
其中

  • Application/MDK-ARM 存放的是啟動代碼;
  • Application/User/Core: main函數,中斷Handler,MSP相關代碼;
  • Application/User/USB_DEVICE/App:* USB設備應用代碼;
  • Application/User/USB_DEVICE/Target: USB設備配置代碼;
  • Drivers/STM32F1xx_HAL_Driver: HAL庫驅動代碼
  • Drivers/CMSIS: CMSIS相關代碼
  • Middlewares/USB_Device_Library/ USB設備庫代碼,對應cubemx Middleware;
  • Customer: 這是我們自定義的代碼;
  • Doc: 存放說明文本文檔;

工程目錄這里只做一次介紹,后面的樣例目錄大同小異。接下來我們配置一下USB的報告描述符,我們定位到
"Application/User/USB_DEVICE/App/ usbd_custom_hid_if.c"文件,
打開usbd_custom_hid_if.c文件,並找到數組變量CUSTOM_HID_ReportDesc_FS;
另外需要注意USBD_CUSTOM_HID_REPORT_DESC_SIZE,
這個宏是報告描述符實際數組大小,大小不對會導致枚舉失敗;
"#define USBD_CUSTOM_HID_REPORT_DESC_SIZE 46"

通過報告描述符生成工具Dt2_4配置生成報告描述符,如下

__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
  /* USER CODE BEGIN 0 */
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x04,                    // USAGE (Joystick)
    0xa1, 0x01,                    // COLLECTION (Application)
    0xa1, 0x02,                    //     COLLECTION (Logical)
    0x09, 0x30,                    //     USAGE (X)
    0x09, 0x31,                    //     USAGE (Y)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //     LOGICAL_MAXIMUM (255)
    0x35, 0x00,                    //     PHYSICAL_MINIMUM (0)
    0x46, 0xff, 0x00,              //     PHYSICAL_MAXIMUM (255)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x02,                    //     REPORT_COUNT (2)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
    0x29, 0x08,                    //     USAGE_MAXIMUM (Button 8)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x08,                    //     REPORT_COUNT (8)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0xc0,                          //               END_COLLECTION

  /* USER CODE END 0 */
  0xC0    /*     END_COLLECTION	             */
};

由上述描述符可以看出X,Y軸定義成無符號8位數,XY的描述占用2個字;按鍵一共有8個,每個大小描述是bit,8個bit即1個byte;因此XY坐標+8個按鍵=3個byte;我們需要上報3個byte的數據給主機(HOST)。
最后是應用程序的編寫,在main函數中,我們通過HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&AD_DATA, N)啟動ADC DMA采集兩個坐標數據;
bubble_sort是冒泡排序算法,對XY采樣到的數據進行排序后取中間值幾個進行求平均以減少誤差;

  • 公式:

X=((Xtemp-Xmin)255)/(Xmax-Xmin);
Y=((Ytemp-Ymin)
255)/(Ymax-Ymin);

這兩個公式是坐標解析算法,即兩點一線方程;
按鍵的解析就是操作對應的key變量對應的位:如按鍵1按下,把最低位置1;按鍵1彈起,把最低位清零即可;
這樣組成報告描述符,通過USBD_CUSTOM_HID_SendReport上報給主機,如下


Joystick_Report[0] =Y;
Joystick_Report[1]=X;
Joystick_Report[2]=key;
USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS,(u8*)&Joystick_Report, 3);

至此,軟件設計完成。(對於沒有基礎的同學,還是建議多看代碼,精力有限,恕難面面俱到)

3.1.3 下載驗證

我們把固件程序下載進去可以,打開“設備與打印機”可以看到USB設備枚舉成了一個Gamepad,如下圖。
image

圖1.5 Gamepad設備
右鍵打開游戲控制器后,點擊屬性得到下圖所示界面
image
圖1.6 游戲控制器
我們可以搖Joystick和按按鍵可以發現上圖游戲控制器界面也跟着響應。

3.2 實例Eg2_WS2812B

目標是實現點亮WS2812B燈珠。

3.2.1硬件設計

如圖1.7和1.8所示MCU通過1根數據線控制WS2812B
image
圖1.7 WS2812B單顆燈珠原理圖
image
圖1.8 MCU連接WS2812控制引腳
————————————————以下為引文start————————————————
WS2812通訊協議:
數據協議采用單線歸零碼的通訊方式, 像素點在上電復位以后, DIN端接受從控制器傳輸過來的數據, 首先送過來的24bit數據被第一個像素點提取后, 送到像素點內部的數據鎖存器, 剩余的數據經過內部整形處理電路整形放大后通過DO端口開始轉發輸出給下一個級聯的像素點, 每經過一個像素點的傳輸, 信號減少24bit。 像素點采用自動整形轉發技術, 使得該像素點的級聯個數不受信號傳送的限制, 僅僅受限信號傳輸速度要求

image
從圖中可以看出,數字“1”使用長脈寬來編碼(占空比為68%),“0”使用短脈寬來編碼(占空比為32%)。數據線低電平保持時間大於50us時,為復位信號。復位后,每個LED讀取“Din”線上開始的24bit(綠:紅:藍為8:8:8)數據到驅動芯片內部緩存。除了開始的24bit數據,后面的數據都通過“Dout”腳傳遞到下一個LED,即每經過一個像素點的傳輸,信號減少24bit。內部緩存數據在下一個復位脈沖后被寫入PWM控制器。一個bit為1.25us,一個LED有38bits=24bits,傳輸完  需要241.25us=30us。
數據傳輸方式:
image
————————————————end————————————————
版權聲明:本文為CSDN博主「皮克斯之旅」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/cheng_nnan/article/details/105490778

3.2.2 軟件設計

我們將DIN配置為PWM+DMA的方式去驅動WS2812B,初始化配置如圖1.9所示
image
圖1.9 DIN引腳配置
MCU主頻為72M,Counter period=89,即計數周期=1/72*89約等於1.23us

#define BIT_1 61u //1比較值為61 850us
#define BIT_0 28u //0比較值為28 400us

我們的代碼中配置0碼和1碼如上,

1碼計算:1/7261約等於0.84us
0碼計算:1/72
28約等於0.38us

滿足規格書中對傳輸時間的要求;代碼實現,請參考示例源碼;

3.2.3 下載驗證

我們把固件程序下載進去可以,可以看到板載的5050燈珠,進行七彩變化;
image

3.3 實例Eg3_Mouse

目標是模擬鼠標功能。

3.3.1硬件設計

如圖2.0所示,我們將使用VRX1和VRY1作為鼠標相對坐標,SW1作為鼠標中鍵
image
圖2.0 Joystick原理圖
image
如上圖2.1,UP,DN,LF,RG分別代表鼠標滾輪向上,向下,鼠標左鍵,右鍵;

3.3.2 軟件設計

我們將usbd_custom_hid_if.c中CUSTOM_HID_ReportDesc_FS修改為鼠標的報告描述符;然后按照報告描述符上面定義的數據,修改main.c中的Joystick_Report數組;詳見代碼

3.3.3 下載驗證

我們把固件程序下載進去,搖動搖桿,桌面鼠標指針對應移動,按對應按鍵,鼠標按鍵作出相對應的反應;

3.4 實例Eg4_ComDev_GM

目標是實現Gamepad和Mouse的組合,即把實例1和實例三組合成一個設備,通過傳感按鍵SW7切換;

3.4.1硬件設計

參考原理圖,本實例除了ws2812燈珠,其他硬件皆用到;

3.4.2 軟件設計

本節重點在軟件部分,在於如何增加接口端點去上報需要組合兩個設備的Raw Data,下面是我們總結的步驟;
STM32 USB HAL庫CustomerHID類設備增加接口端點步驟:

  1. 為端點增加PAM:
    定位到MX_USB_DEVICE_Init->USBD_Init->USBD_LL_Init;在USBD_LL_Init函數中找到HAL_PCDEx_PMAConfig,通過該接口為EP(端點)配置PMA(Packet Buffer Memory Area ,即USB硬件緩沖區))Eg:
    HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData,MOUSE_HID_EPIN_ADDR , PCD_SNG_BUF,0x98);
    
  2. 打開和配置端點:
    定位到USBD_CUSTOM_HID->USBD_CUSTOM_HID_Init通過USBD_LL_OpenEP函數中和pdev->ep_in[EP_ADDR & 0xFU].is_used = 1U;打開並使能端點,同時將USBD_LL_PrepareReceive中第四個參數改為大(如果用到接收端點);Eg:
    USBD_LL_OpenEP(pdev, MOUSE_HID_EPIN_ADDR, USBD_EP_TYPE_INTR,MOUSE_HID_EPIN_SIZE);
    pdev->ep_in[MOUSE_HID_EPIN_ADDR & 0xFU].is_used = 1U;
    USBD_LL_PrepareReceive(pdev, CUSTOM_HID_EPOUT_ADDR, hhid->Report_buf,
                            USBD_CUSTOMHID_OUTREPORT_BUF_SIZE);
    
  3. 根據接口索引修改獲取描述符的請求:
    定位到USBD_CUSTOM_HID->USBD_CUSTOM_HID_Setup在USB_REQ_GET_DESCRIPTOR請求中通過req->wIndex增加報告描述符的請求;Eg:
    if(req->wIndex==0)
    {
        len = MIN(USBD_MOUSE_HID_REPORT_DESC_SIZE, req->wLength);
        pbuf = ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->MouseReport;
    }
    
  4. 修改配置、接口、端點描述符:定位到USBD_CUSTOM_HID->USBD_CUSTOM_HID_GetFSCfgDesc->USBD_CUSTOM_HID_CfgFSDesc正確修改即可,Eg:略
  5. 增加報告描述符:在usbd_custom_hid_if.c中增加報告描述符及其大小;
  6. 修改發送報告函數:在usbd_customhid.c中修改USBD_CUSTOM_HID_SendReport中的USBD_LL_Transmit的第二個參數地址;

3.4.3 下載驗證

7我們把固件程序下載進去,搖動搖桿,按住SW7大於5s,切換成鼠標模式,桌面鼠標指針對應移動,按對應按鍵,鼠標按鍵作出相對應的反應;

3.5 實例Eg5_Keyboard

目標是實現Keyboard,模擬鍵盤;實現鍵盤的shift、1~8鍵,分別對應評估板的SW1(搖桿上的按鍵)、SW2、SW3、SW4、SW5、SW9、SW8、SW7、SW6;

3.5.1硬件設計

參考原理圖;

3.5.2 軟件設計

本節重點在軟件部分,在於如何修改配置描述符,看懂報告描述符;以及如何把按鍵數據解析為報文;

3.5.3 下載驗證

我們把固件程序下載進去,pc端的設備與打印機面板顯示枚舉成功的鍵盤設備;按下SW1即是shift鍵按下,SW2、SW3、SW4、SW5、SW9、SW8、SW7、SW6按下也對應是主鍵盤上的1~8鍵按下,按住“shift+1”也可以打印“!”,其他組合鍵也同理可得。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM