STM32 HAL Custom HID

1.设置CubeMx

 

2.代码

修改usbd_custom_hid_if.c中结构体数据:

__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
  /* USER CODE BEGIN 0 */
    0x06, 0x00, 0xff,              // USAGE_PAGE (Vendor Defined Page 1)
    0x09, 0x01,                    // USAGE (Vendor Usage 1)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Vendor Usage 1)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x95, 0x40,                    //   REPORT_COUNT (64)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x09, 0x01,                    //   USAGE (Vendor Usage 1)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x95, 0x40,                    //   REPORT_COUNT (64)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)
  /* USER CODE END 0 */
  0xC0    /*     END_COLLECTION                 */
};

确认下usbd_conf.h中以下三个宏定义:

/*----------输出数据长度 -----------*/

#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE     64
/*----------报文符长度,就是CUSTOM_HID_ReportDesc_FS结构体长度 -----------*/
#define USBD_CUSTOM_HID_REPORT_DESC_SIZE     34
/*----------这个是设置速度默认为5,速度可以达到16KB, 修改为1后速度为64KB -----------*/
#define CUSTOM_HID_FS_BINTERVAL     0x1

 

修改usbd_customhid.h文件中的发送与接收长度为64,原先默认值为0x02

  #define CUSTOM_HID_EPIN_SIZE                  0x40

  #define CUSTOM_HID_EPOUT_SIZE              0x40

 

USB 收到数据后会触发事件,在usbd_custom_hid_if.c中的CUSTOM_HID_OutEvent_FS函数,这里的程序将上位机发送数据后,下位机将数据发送回上位机。

static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)
{
  /* USER CODE BEGIN 6 */
    USBD_CUSTOM_HID_HandleTypeDef   *hhid; //定义一个指向USBD_CUSTOM_HID_HandleTypeDef结构体的指针
    hhid = (USBD_CUSTOM_HID_HandleTypeDef*)hUsbDeviceFS.pClassData;//得到USB接收数据的储存地址
    USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, hhid->Report_buf, 64);
    return (USBD_OK);
  /* USER CODE END 6 */
}

 

将程序刷入stm32.以下是上位机代码 vs2013 unicode 控制台版本。

// usb_stm32.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <windows.h>
#include <setupapi.h>
 #include <hidsdi.h>
#include <locale.h>

#pragma comment(lib,"Setupapi.lib")
#pragma comment(lib,"Hid.lib")

#define     USB_VID         0x0483
#define     USB_PID         0x5750

void UsbOperation();
int _tmain(int argc, _TCHAR* argv[])
{
    setlocale(LC_ALL, "chs");//设置中文显示
     UsbOperation();    
    return 0;
}

//获得设备路径,同时获取设备描述
void GetDevPath(TCHAR *pStrDevPath)
{
    TCHAR szDevPath[MAX_PATH] = { 0 };

    TCHAR szVid[20] = { 0 };
    TCHAR szPid[20] = { 0 };

    _stprintf_s(szVid, _T("vid_%04x"), USB_VID);
    _stprintf_s(szPid, _T("pid_%04x"), USB_PID);

    GUID Guid;
    HidD_GetHidGuid(&Guid);

    HDEVINFO info;
    info = SetupDiGetClassDevs(&Guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

    if (info == INVALID_HANDLE_VALUE)
    {
        return;
    }

    DWORD devIndex;
    SP_INTERFACE_DEVICE_DATA ifData;
    ifData.cbSize = sizeof(ifData);

    for (devIndex = 0; SetupDiEnumDeviceInterfaces(info, NULL, &Guid, devIndex, &ifData); ++devIndex)
    {
        DWORD needed;

        SetupDiGetDeviceInterfaceDetail(info, &ifData, NULL, 0, &needed, NULL);

        PSP_INTERFACE_DEVICE_DETAIL_DATA detail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)new BYTE[needed];
        detail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
        SP_DEVINFO_DATA did = { sizeof(SP_DEVINFO_DATA) };

        if (SetupDiGetDeviceInterfaceDetail(info, &ifData, detail, needed, NULL, &did))
        {
            if ((_tcsstr(detail->DevicePath, szVid) == NULL) || (_tcsstr(detail->DevicePath,szPid) == NULL ))
            {
                delete[](PBYTE)detail;
                continue;
            }

            _tprintf(_T("dev path: %s\r\n"), detail->DevicePath);
            _tcscpy_s(pStrDevPath, MAX_PATH, (TCHAR *)detail->DevicePath);
         
            TCHAR szProduct[MAX_PATH] = { 0 };
            if (SetupDiGetDeviceRegistryProperty(info, &did, SPDRP_DEVICEDESC, NULL, (PBYTE)szProduct, MAX_PATH, NULL))
            {
                _tprintf(_T("dev Prod: %s\r\n"), szProduct);
            }

            delete[](PBYTE)detail;
            break;
        }

        delete[](PBYTE)detail;
    }
    SetupDiDestroyDeviceInfoList(info); 
}

HANDLE OpenHidevice(TCHAR *pstrDevPath)
{
    HANDLE hidHandle = NULL;
    
    hidHandle = CreateFile(pstrDevPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (hidHandle != INVALID_HANDLE_VALUE)
    {
        PHIDD_ATTRIBUTES Attributes = (PHIDD_ATTRIBUTES)malloc(sizeof(HIDD_ATTRIBUTES));
        if (HidD_GetAttributes(hidHandle, Attributes))
        {
            printf("Info:  VID->0x%X PID->0x%X VersionNum->0x%X\r\n", Attributes->VendorID, Attributes->ProductID, Attributes->VersionNumber);
        }
    }
    return hidHandle;
}


void GetDeviceCapabilities(HANDLE hidDevObj, HIDP_CAPS &hidCaps)
{
    PHIDP_PREPARSED_DATA    hidPredata;
    HidD_GetPreparsedData(hidDevObj, &hidPredata);

    HidP_GetCaps(hidPredata, &hidCaps);

    printf("%s%X\r\n", "Usage Page:                      \t\t", hidCaps.UsagePage);
    printf("%s%d\r\n", "Input Report Byte Length:        \t\t", hidCaps.InputReportByteLength);
    printf("%s%d\r\n", "Output Report Byte Length:       \t\t", hidCaps.OutputReportByteLength);
    printf("%s%d\r\n", "Feature Report Byte Length:      \t\t", hidCaps.FeatureReportByteLength);
    printf("%s%d\r\n", "Number of Link Collection Nodes: \t\t", hidCaps.NumberLinkCollectionNodes);
    printf("%s%d\r\n", "Number of Input Button Caps:     \t\t", hidCaps.NumberInputButtonCaps);
    printf("%s%d\r\n", "Number of InputValue Caps:       \t\t", hidCaps.NumberInputValueCaps);
    printf("%s%d\r\n", "Number of InputData Indices:     \t\t", hidCaps.NumberInputDataIndices);
    printf("%s%d\r\n", "Number of Output Button Caps:    \t\t", hidCaps.NumberOutputButtonCaps);
    printf("%s%d\r\n", "Number of Output Value Caps:     \t\t", hidCaps.NumberOutputValueCaps);
    printf("%s%d\r\n", "Number of Output Data Indices:   \t\t", hidCaps.NumberOutputDataIndices);
    printf("%s%d\r\n", "Number of Feature Button Caps:   \t\t", hidCaps.NumberFeatureButtonCaps);
    printf("%s%d\r\n", "Number of Feature Value Caps:    \t\t", hidCaps.NumberFeatureValueCaps);
    printf("%s%d\r\n", "Number of Feature Data Indices:  \t\t", hidCaps.NumberFeatureDataIndices);
    HidD_FreePreparsedData(hidPredata);
}
 
void ReadUsbData(HANDLE hHidDevObj, DWORD dwCnt )
{
    DWORD NumberOfBytesRead;
    BYTE InputReport[256] = { 0 };
    BYTE OutputReport[256] = { 0 };
    DWORD bytes = 0;
    int Result = 0;

    for (DWORD i = 0; i < dwCnt; i++)
    {
        OutputReport[i] = (BYTE)i;
    }

    while (TRUE)
    {
        if (hHidDevObj != INVALID_HANDLE_VALUE)
        {
            //CancelIo(hHidDevObj);
            OutputReport[1] ++;//OutputReport[0]代表报告ID
            Result = WriteFile(hHidDevObj, OutputReport, dwCnt, &bytes, NULL);
            Result = ReadFile(hHidDevObj, &InputReport, dwCnt, &NumberOfBytesRead, NULL);
            for (DWORD i = 0; i < dwCnt; i++)
            {
                printf(" %d ", InputReport[i]);
            } 
        }

        Sleep(1000);
        printf("\r\n\r\n");
    }
}

void UsbOperation()
{
    TCHAR strDevicePath[MAX_PATH] = { 0 };
    HANDLE HidDeviceObject = INVALID_HANDLE_VALUE;
    HIDP_CAPS hidCap = { 0 };
    
    BYTE OutputReport[256] = { 0 };

    GetDevPath(strDevicePath);
    HidDeviceObject = OpenHidevice(strDevicePath);
    GetDeviceCapabilities(HidDeviceObject, hidCap);
    ReadUsbData(HidDeviceObject, hidCap.InputReportByteLength);
}

 

测试结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值