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
#include
#include
#include
#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);
}
测试结果: