USB HID上位机测试(C#)

目录

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

1、基本测试

1.1、通过Bus Hound可以看到设备列表

 1.2、 通过API获取到设备接口文件列表

 可以看出,每个接口有一个对应的操作对象,三个设备是可以独立操作的。

  • \\?\hid#vid_0480&pid_5750&mi_00#8&eff1a39&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
  • \\?\hid#vid_0480&pid_5750&mi_01#8&32d657fb&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}\kbd
  •  \\?\hid#vid_0480&pid_5750&mi_02#8&1b12cbb6&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}

用   mi_(接口编号)  区别,接口编号对应配置描述表里的接口编号,鼠标0,键盘1,自定义HID 2

 此处的复合设备是单独的接口操作的,就会产生对应的操作文件。如果是通过同一个接口,用报告描述符ID来产生的对个设备,将不会出现对个设备文件,操作时需要通过报告描述符ID来寻找设备。

1.3、用BUS Hound收发测试

bus hound 不会限制发送长度,下位机端也可以不用报告描述符来描述具体发送数据的意义及格式

 

 2、C#上位机

C# HID上位机icon-default.png?t=LA92https://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其中做了些修改,感觉原先的有点小问题

2.1、打开设备

不建议去打开一些未知的设备,确定是谁再去打开,可以通过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;
}    

报告ReportID

测试发现:

  • 如果报告描述符有问题,则获取出来的caps对应值就为0,我开始没设置端点OUT的信息,caps.OutputReportByteLength就为0。
  • 实际的值会默认加上报告描述符描述表ReportID,首字节位置。默认为0,多报告表就对应变化。及caps.OutputReportByteLength = 1字节ReportID + 实际报告表描述的数据长度。
HIDP_CAPS caps;
HidP_GetCaps(preparseData, out caps);
outputReportLength = caps.OutputReportByteLength;
inputReportLength = caps.InputReportByteLength;

2.2、发送数据

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;
}

注意:

  • 写入数据之后调用 hidDevice.Flush,数据才会立即发送,否则就会乱发送。
  • 发送数据的buffer的长度必须和outputReportLength一致,否则会报错,不知缘由。
  • buffer的首字节为ReportID,一个报告下默认为0。(如果有多个时,这个参数就有用了)

测试:

同时勾选两个上这两个

 

会发现106.3 发送8个字节,109是9个字节,加上了ReportID,下位机收到的也是8个字节。

 2.3、异步接收

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();
    }
}
  • 接收到的数据头字节也是ReportID,数据为其后的内容。
  • 如果上传的数据长度和报告描述表里规定的长度不一致,API也收不到数据,但是BusHound能监控到数据。(肯定是哪里有问题,后续再查)

3、其他测试

3.1、中断端点时间测试

连续发送两个包,查看发送时间间隔

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  改小即可。

  • 3
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
赋所有源代码,开发工具vs2010 framework3.5 baidu搜索c# HidUsb都是大同小异案例,而且拿下来基本不能用。大都是围绕public static extern int CreateFile(省略众多参数..);发现没有,copy下来测试基本都是用不了的。 原因很简单:windows不允许你用程序随便就去访问硬件设备。所以在此把之前做过的基于C#开发读写HidUsb设备的项目整理成一个简单的小案例,分享给大家,开发环境VS2010。 该案例重点在public static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile); 看着貌似也是用到CreateFile这个函数,其实并不然,注意到没有"SafeFileHandle",这就是重点! 这样windows是允许程序访问外接hidusb设备的。 当然具体如何运用这个函数现在已经不是您应该 关心的了,因为我已经为您把它封装成一个类,您只要调用相应的方法就OK. 例: //第一步:获取HidUsb设备信息 List slist = new List(); UsbHidDevice usbhid = new UsbHidDevice(); usbhid.GetDeviceList(ref slist); //HidUsb设备信息包含在List数据集中 注:当获取到HidUsb设备信息为:\\?\hid#vid_0e2c&pid;_0112#6&1b44c403;&0&0000;#{4d1e55b2-f16f-11cf-88cb-001111000030}, 注意该字符串里的“vid_0e2c”和“pid_0112”部分,那么: vid为0e2c, pid为:0112 //第二步:创建一个HidUsb设备访问实例 UsbHidDevice Device = new UsbHidDevice(vid, pid); //第三步:连接HidUsb设备 Boolean connBool = Device.Connect(); //第四步:实现数据接收事件 Device.DataReceived += new UsbHidDevice.DataReceivedDelegate(Device_DataReceived); //当HidUsb设备返回信息时触发此事件 void Device_DataReceived(byte[] data) { //处理接收到的数据逻辑 } //第五步:向Hid设备发送数据"0xa0 00 0x12 0x9 0x22" string txt = "0xa0 00 0x12 0x9 0x22"; //把数据转换为字节数组 byte[] data = ConvertHelper.StringToByte(txt2); byte bt = 0; CommandMessage cmdMsg = new CommandMessage(bt, data); Boolean sbool = Device.SendMessage(cmdMsg); //发送数据 //第六步:释放所有资源 Device.Dispose();

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值