目录
1、基本测试
1.1、通过Bus Hound可以看到设备列表
1.2、 通过API获取到设备接口文件列表
1.3、用BUS Hound收发测试
2、C#上位机
2.1、打开设备
报告ReportID
2.2、发送数据
注意:
测试:
2.3、异步接收
3、其他测试
3.1、中断端点时间测试
下位机这两天已经折腾出一个一二了,在配合上位机完整学习一下,下位机芯片是STM32F103VB
可以看出,每个接口有一个对应的操作对象,三个设备是可以独立操作的。
用 mi_(接口编号) 区别,接口编号对应配置描述表里的接口编号,鼠标0,键盘1,自定义HID 2
此处的复合设备是单独的接口操作的,就会产生对应的操作文件。如果是通过同一个接口,用报告描述符ID来产生的对个设备,将不会出现对个设备文件,操作时需要通过报告描述符ID来寻找设备。
bus hound 不会限制发送长度,下位机端也可以不用报告描述符来描述具体发送数据的意义及格式
C# HID上位机https://download.csdn.net/download/ai5945fei/43657670
参考:
【C#】HID API_beatfan的博客-CSDN博客https://blog.csdn.net/u010875635/article/details/73321066?spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down.none-task-blog-2~default~OPENSEARCH~default-5.nonecase&depth_1-utm_source=distribute.pc_relevant_bbs_down.none-task-blog-2~default~OPENSEARCH~default-5.nonecase其中做了些修改,感觉原先的有点小问题
不建议去打开一些未知的设备,确定是谁再去打开,可以通过VID和PID,接口编号三个参数确定我们的目标设备。
public HID_RETURN OpenDevice(string deviceNme)
{
if (deviceOpened == false)
{
IntPtr device = CreateFile(deviceNme,
DESIREDACCESS.GENERIC_READ | DESIREDACCESS.GENERIC_WRITE,
0,
0,
CREATIONDISPOSITION.OPEN_EXISTING,
FLAGSANDATTRIBUTES.FILE_FLAG_OVERLAPPED,
0);
if (device != INVALID_HANDLE_VALUE)
{
HIDD_ATTRIBUTES attributes;
IntPtr serialBuff = Marshal.AllocHGlobal(512);
HidD_GetAttributes(device, out attributes);
HidD_GetSerialNumberString(device, serialBuff, 512);
string deviceStr = Marshal.PtrToStringAuto(serialBuff);
Marshal.FreeHGlobal(serialBuff);
IntPtr preparseData;
HIDP_CAPS caps;
HidD_GetPreparsedData(device, out preparseData);
HidP_GetCaps(preparseData, out caps);
HidD_FreePreparsedData(preparseData);
outputReportLength = caps.OutputReportByteLength;
inputReportLength = caps.InputReportByteLength;
hidDevice = new FileStream(new SafeFileHandle(device, false), FileAccess.ReadWrite, inputReportLength, true);
deviceOpened = true;
BeginAsyncRead();
hHubDevice = device;
return HID_RETURN.SUCCESS;
}
return HID_RETURN.DEVICE_NOT_FIND;
}
else
return HID_RETURN.DEVICE_OPENED;
}
测试发现:
HIDP_CAPS caps;
HidP_GetCaps(preparseData, out caps);
outputReportLength = caps.OutputReportByteLength;
inputReportLength = caps.InputReportByteLength;
public HID_RETURN Write(report r)
{
if (deviceOpened)
{
try
{
byte[] buffer = new byte[outputReportLength];
int txlen = r.reportBuff.Length;
if (txlen > outputReportLength) txlen = outputReportLength;
buffer[0] = r.reportID;
Array.Copy(r.reportBuff, 0, buffer, 1, txlen);
hidDevice.Write(buffer, 0, buffer.Length);
hidDevice.Flush();//立即发送数据
return HID_RETURN.SUCCESS;
}
catch
{
EventArgs ex = new EventArgs();
OnDeviceRemoved(ex);//发出设备移除消息
CloseDevice();
return HID_RETURN.NO_DEVICE_CONECTED;
}
}
return HID_RETURN.WRITE_FAILD;
}
同时勾选两个上这两个
会发现106.3 发送8个字节,109是9个字节,加上了ReportID,下位机收到的也是8个字节。
private void ReadCompleted(IAsyncResult iResult)
{
byte[] readBuff = (byte[])(iResult.AsyncState);
try
{
hidDevice.EndRead(iResult);//读取结束,如果读取错误就会产生一个异常
byte[] reportData = new byte[readBuff.Length - 1];
for (int i = 1; i < readBuff.Length; i++)
reportData[i - 1] = readBuff[i];
report e = new report(readBuff[0], reportData);
OnDataReceived(e); //发出数据到达消息
if (!deviceOpened) return;
BeginAsyncRead();//启动下一次读操作
}
catch //读写错误,设备已经被移除
{
//MyConsole.WriteLine("设备无法连接,请重新插入设备");
EventArgs ex = new EventArgs();
OnDeviceRemoved(ex);//发出设备移除消息
CloseDevice();
}
}
连续发送两个包,查看发送时间间隔
private void button2_Click(object sender, EventArgs e)
{
SendBytes(new byte[] { 0xA5, 0, 1, 0 });
SendBytes(new byte[] { 0xA5, 0, 2, 0 });
}
OUT端点设置
结果:
点击了两次,连续发送的两个包之间间隔是31ms,设置的端点中断时间为32ms
对比:改成10ms之后,对应间隔变成8ms左右
修改之后,需要删除原来的设备重新安装设备这个值才会刷新,或者修改VID,PID也可以。否则PC会记录并使用以前的值。
所以要是需要下发的数据块速接收到,将 bInterval: Polling Interval 改小即可。