本文记录利用STM32的USB设备以HID方式实现与PC的自定义包大小通信的上下位机开发过程.
关键字: USB, HID, HID读写,Report Descriptor
要解决的问题 : 假定某一串行通信协议, 命令的最大长度为64个字节, 而现在改用USB- HID方式来通信, 通信协议不变, 我们如何实现?
芯片: STM32F103ZE; 基础代码: 官方USB固件库V3.2.0; PC端工具: VS2005;调试工具: USBLyzer
适当修改官方固件库中的Custom_HID工程中与Board相差的配置, 然后编译运行, 便可以在设备管理器看到
HID已经识别成功了.
在该工程中, 实现了三个通信过程, 其中两个IN传输: ADC采样输入, 按钮输入; 一个属于OUT传输:LED灯控制; 每次传输两个字节, 一个数据和一个报告ID, 而在平常使用中, 大家总是希望通信过程能够模拟串口那种以多字节包的方式来输入和输出, 显然, 官方的示例并不能实现我们的目标。要实现目标, 我们动手修改源代码。。。。。
1、修改Endpoint Descriptor
官方代码中, 在CustomHID_ConfigDescriptor串末尾定义了两个Endpoint Descriptor,我们在它的基础上修改Endpoint 的最大传输字节。
2、修改Endpoint 的最大接收与发送包大小
在CustomHID_Reset函数中,修改语句以设置最大包:
SetEPTxCount();
SetEPRxCount();
3、修改Report Descriptor
要解决我们的问题, 我们仅需要实现两个Report , 一个IN, 一个OUT, 大小均是64个字节, 根据这些要求, 使用USB.ORG提示的HID Descriptor TOOL生成Report Descriptor.
4、修改IN传输的函数:
__IO uint8_t Send_Buffer[65];
void vUSBSendBytes(void)
{
uint8_t i;
Send_Buffer[0] = 0x01;
for(i = 1; i< 65; i++)
{
Send_Buffer++;
}
/* Write the descriptor through the endpoint */
USB_SIL_Write(EP1_IN, (uint8_t*) Send_Buffer, 65);
}
5、修改IN传输的调用 函数
在MAIN函数中改写while()循环
while (1)
{
Delay(20000000);
vUSBSendBytes();
}
至些, 与USB有关的修改已经结束, 接下来可以删除与本应用无关的代码, 如ADC\LED相关.
编译代码, 运行, 在USBlyzer可以看到以下信息
IN传输成功完成, 下面开始编写上位机代码
1、环境配置及头文件、库的包含
环境: DDK或者WDK编译环境
头文件包含:
extern "C"
{
#include "setupapi.h"
#include "hidsdi.h"
#include "dbt.h"
}
库文件:
#pragma comment(lib,"hid.lib")
#pragma comment(lib,"setupapi.lib")
2、设备发现
查询HID设备的代码很多, 略
特殊提示: 使用
HIDP_CAPS Capabilities;
PHIDP_PREPARSED_DATA PreparsedData;
HidD_GetPreparsedData(handle,&PreparsedData);
HidP_GetCaps (PreparsedData,&Capabilities);
可以获取HIDP_CAPS参数, 其参数结构如下:
typedef struct _HIDP_CAPS
{
USAGE Usage;
USAGE UsagePage;
USHORT InputReportByteLength;
USHORT OutputReportByteLength;
USHORT FeatureReportByteLength;
USHORT Reserved[17];
USHORT NumberLinkCollectionNodes;
USHORT NumberInputButtonCaps;
USHORT NumberInputValueCaps;
USHORT NumberInputDataIndices;
USHORT NumberOutputButtonCaps;
USHORT NumberOutputValueCaps;
USHORT NumberOutputDataIndices;
USHORT NumberFeatureButtonCaps;
USHORT NumberFeatureValueCaps;
USHORT NumberFeatureDataIndices;
} HIDP_CAPS, *PHIDP_CAPS;
其中关键参数 InputReportByteLength,OutputReportByteLength就是关键的IN与OUT包的大小, 在READ与WRITE函数调用时需要用到。
3、读写操作
略, 仅提供示例函数:
1) 读
bRet = ReadFile(handle, rBuffer, 65, &dwRet, NULL);
2) 写
wBuffer[0] = 0x02;//report id
BOOL bRet = WriteFile(handle, wBuffer, 65, &dwRet, NULL);
至此, 我们就可以通过VC来完成对HID设备的读写操作了。 IN与OUT双向传输,最大包64个字节并可以随意修改,灵活吗?
时间有限, 仅能粗略讲述一下开发过程, 敬请谅解!
文章评论(0条评论)
登录后参与讨论