zoukankan      html  css  js  c++  java
  • C#开发usb通知之bulk传输

    usb通信分为4种传输方式,下位机通信协议用的是块传输,也就是bulk传输,C#下实现的usb通信使用的是开源的LibUsbDotNet,主要的就是需要在C#中添加LibUsbDotNet.dll引用文件,安装后的LibUsbDotNet里面有

    我是参考bulk传输实例,这个需要libusb-1.0.dll文件放在程序的根目录下或者在windows/system32/目录下,否则会报错,提示找不到这个文件:

    using System;
    using System.Runtime.InteropServices;
    using MonoLibUsb.Transfer;
    using Usb = MonoLibUsb.MonoUsbApi;
    
    namespace MonoLibUsb.ShowInfo
    {
        internal enum TestMode
        {
            Sync,
            Async
        }
    
        internal class BulkReadWrite
        {
            #region DEVICE SETUP
            private const int MY_CONFIG = 1;
            private const byte MY_EP_READ = 0x81;//读端点口地址
            private const byte MY_EP_WRITE = 0x01;//写端点口地址
            private const int MY_INTERFACE = 0;//接口地址
            private const short MY_PID = 0x0053;//设备的VID PID信息
            private const short MY_VID = 0x04d8;
            #endregion
    
            #region TEST SETUP
            private const int MY_TIMEOUT = 2000;//读写超时时间
            private const int TEST_LOOP_COUNT = 1;
    
            private const int TEST_READ_LEN = 64;
    
            private const bool TEST_REST_DEVICE = true;
            private const int TEST_WRITE_LEN = 8;
    
            private static TestMode TEST_MODE = TestMode.Async;
            #endregion
    
            private static MonoUsbSessionHandle sessionHandle  = null;
    
            private static void fillTestData(byte[] data, int len)
            {
                int i;
                for (i = 0; i < len; i++)
                    data[i] = (byte) (65 + (i & 0xf));
            }
    
            private static void memset(byte[] data, int value, int len)
            {
                int i;
                for (i = 0; i < len; i++)
                    data[i] = (byte) (value);
            }
    
            // This function originated from bulk_transfer_cb()
            // in sync.c of the Libusb-1.0 source code.
            private static void bulkTransferCB(MonoUsbTransfer transfer)
            {
                Marshal.WriteInt32(transfer.PtrUserData, 1);
                /* caller interprets results and frees transfer */
            }
    
            // This function originated from do_sync_bulk_transfer()
            // in sync.c of the Libusb-1.0 source code.
            private static MonoUsbError doBulkAsyncTransfer(MonoUsbDeviceHandle dev_handle,
                                                              byte endpoint,
                                                              byte[] buffer,
                                                              int length,
                                                              out int transferred,
                                                              int timeout)
            {
                transferred = 0;
                MonoUsbTransfer transfer = new MonoUsbTransfer(0);
                if (transfer.IsInvalid) return MonoUsbError.ErrorNoMem;
    
                MonoUsbTransferDelegate monoUsbTransferCallbackDelegate = bulkTransferCB;
                int[] userCompleted = new int[] {0};
                GCHandle gcUserCompleted = GCHandle.Alloc(userCompleted, GCHandleType.Pinned);
    
                MonoUsbError e;
                GCHandle gcBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                transfer.FillBulk(
                    dev_handle,
                    endpoint,
                    gcBuffer.AddrOfPinnedObject(),
                    length,
                    monoUsbTransferCallbackDelegate,
                    gcUserCompleted.AddrOfPinnedObject(),
                    timeout);
    
                e = transfer.Submit();
                if ((int) e < 0)
                {
                    transfer.Free();
                    gcUserCompleted.Free();
                    return e;
                }
                int r;
                Console.WriteLine("Transfer Submitted..");
                while (userCompleted[0] == 0)
                {
                    e = (MonoUsbError) (r = Usb.HandleEvents(sessionHandle));
                    if (r < 0)
                    {
                        if (e == MonoUsbError.ErrorInterrupted)
                            continue;
                        transfer.Cancel();
                        while (userCompleted[0] == 0)
                            if (Usb.HandleEvents(sessionHandle) < 0)
                                break;
                        transfer.Free();
                        gcUserCompleted.Free();
                        return e;
                    }
                }
    
                transferred = transfer.ActualLength;
                e = MonoUsbApi.MonoLibUsbErrorFromTransferStatus(transfer.Status);
                transfer.Free();
                gcUserCompleted.Free();
                return e;
            }
    
            public static int Main(string[] args)
            {
                MonoUsbDeviceHandle device_handle = null;
    
                int r = 0;
                int transferred;
                byte[] testWriteData = new byte[TEST_WRITE_LEN];
                byte[] testReadData = new byte[TEST_READ_LEN];
    
                if (args.Length > 0)
                {
                    switch (args[0].ToLower())
                    {
                        case "sync":
                            TEST_MODE = TestMode.Sync;
                            break;
                        case "async":
                            TEST_MODE = TestMode.Async;
                            break;
                    }
                }
    
                fillTestData(testWriteData, TEST_WRITE_LEN);
                memset(testReadData, 0, TEST_READ_LEN);
    
                int loopCount = 0;
                do
                {
                    try
                    {
                        do
                        {
                            sessionHandle=new MonoUsbSessionHandle();
                            if (sessionHandle.IsInvalid) throw new Exception("Invalid session handle.");
    
                            Console.WriteLine("Opening Device..");
                            device_handle = MonoUsbApi.OpenDeviceWithVidPid(sessionHandle, MY_VID, MY_PID);
                            if ((device_handle == null) || device_handle.IsInvalid) break;
    
                            // If TEST_REST_DEVICE = True, reset the device and re-open
                            if (TEST_REST_DEVICE)
                            {
                                MonoUsbApi.ResetDevice(device_handle);
                                device_handle.Close();
                                device_handle = MonoUsbApi.OpenDeviceWithVidPid(sessionHandle, MY_VID, MY_PID);
                                if ((device_handle == null) || device_handle.IsInvalid) break;
                            }
    
                            // Set configuration
                            Console.WriteLine("Set Config..");
                            r = MonoUsbApi.SetConfiguration(device_handle, MY_CONFIG);
                            if (r != 0) break;
    
                            // Claim interface
                            Console.WriteLine("Set Interface..");
                            r = MonoUsbApi.ClaimInterface(device_handle, MY_INTERFACE);
                            if (r != 0) break;
    
                            /////////////////////
                            // Write test data //
                            /////////////////////
                            int packetCount = 0;
                            int transferredTotal = 0;
                            do
                            {
                                Console.WriteLine("Sending test data..");
    
                                // If the Async TEST_MODE enumeration is set, use
                                // the internal transfer function
                                if (TEST_MODE == TestMode.Async)
                                {
                                    r = (int)doBulkAsyncTransfer(device_handle,
                                                                    MY_EP_WRITE,
                                                                    testWriteData,
                                                                    TEST_WRITE_LEN,
                                                                    out transferred,
                                                                    MY_TIMEOUT);
                                }
                                else
                                {
                                    // Use the sync bulk transfer API function 
                                    r = MonoUsbApi.BulkTransfer(device_handle,
                                                                           MY_EP_WRITE,
                                                                           testWriteData,
                                                                           TEST_WRITE_LEN,
                                                                           out transferred,
                                                                           MY_TIMEOUT);
                                }
                                if (r == 0)
                                {
                                    packetCount++;
                                    transferredTotal += transferred;
                                }
                                // Keep writing data until an error occurs or
                                // 4 packets have been sent.
                            } while (r == 0 && packetCount < 5);
    
    
                            if (r == (int) MonoUsbError.ErrorTimeout)
                            {
                                // This is considered normal operation
                                Console.WriteLine("Write Timed Out. {0} packet(s) written ({1} bytes)", packetCount, transferredTotal);
                            }
                            else if (r != (int) MonoUsbError.ErrorTimeout && r != 0)
                            {
                                // An error, other than ErrorTimeout was received. 
                                Console.WriteLine("Write failed:{0}", (MonoUsbError) r);
                                break;
                            }
                            ////////////////////
                            // Read test data //
                            ////////////////////
                            Console.WriteLine("Reading test data..");
                            packetCount = 0;
                            transferredTotal = 0;
                            do
                            {
                                // If the Async TEST_MODE enumeration is set, use
                                // the internal transfer function
                                if (TEST_MODE == TestMode.Async)
                                {
                                    r = (int) doBulkAsyncTransfer(device_handle,
                                                                    MY_EP_READ,
                                                                    testReadData,
                                                                    TEST_READ_LEN,
                                                                    out transferred,
                                                                    MY_TIMEOUT);
                                }
                                else
                                {
                                    // Use the sync bulk transfer API function 
                                    r = MonoUsbApi.BulkTransfer(device_handle,
                                                                           MY_EP_READ,
                                                                           testReadData,
                                                                           TEST_READ_LEN,
                                                                           out transferred,
                                                                           MY_TIMEOUT);
                                }
                                if (r == (int) MonoUsbError.ErrorTimeout)
                                {
                                    // This is considered normal operation
                                    Console.WriteLine("Read Timed Out. {0} packet(s) read ({1} bytes)", packetCount, transferredTotal);
                                }
                                else if (r != 0)
                                {
                                    // An error, other than ErrorTimeout was received. 
                                    Console.WriteLine("Read failed:{0}", (MonoUsbError)r);
                                }
                                else
                                {
                                    transferredTotal += transferred;
                                    packetCount++;
    
                                    // Display test data.
                                    Console.Write("Received: ");
                                    Console.WriteLine(System.Text.Encoding.Default.GetString(testReadData, 0, transferred));
                                }
                                // Keep reading data until an error occurs, (ErrorTimeout)
                            } while (r == 0);
                        } while (false);
                    }
                    finally
                    {
                        // Free and close resources
                        if (device_handle != null)
                        {
                            if (!device_handle.IsInvalid)
                            {
                                MonoUsbApi.ReleaseInterface(device_handle, MY_INTERFACE);
                                device_handle.Close();
                            }
                        }
                        if (sessionHandle!=null)
                        {
                            sessionHandle.Close();
                            sessionHandle = null;
                        }
                    }
                    // Run the entire test TEST_LOOP_COUNT times.
                } while (++loopCount < TEST_LOOP_COUNT);
    
                Console.WriteLine("
    Done!  [Press any key to exit]");
                Console.ReadKey();
    
                return r;
            }
        }
    }

    我在winfrom的主要思路和上面差不多,但是还有有点区别的,毕竟控制端程序和桌面程序在代码上还是有点区别的。由于项目的要求只能放部分代码

    1.设置相关的通信信息,和上面的差不多

            //设置设备信息,包括接口、断点等信息 
            private void setDevice()
            {
                sessionHandle = new MonoUsbSessionHandle();
                if (sessionHandle.IsInvalid) throw new Exception("Invalid session handle.");
                //Console.WriteLine("Opening Device..");
                device_handle = MonoUsbApi.OpenDeviceWithVidPid(sessionHandle, MY_VID, MY_PID);
                if ((device_handle == null) || device_handle.IsInvalid)
                {
                    Console.WriteLine("device_handle为空");
                    isContinue = false;
                    labelInfo.Text = "未找到设备";
                    ScanBtn.Enabled = false;
                }
                else
                {
                    //设置配置信息
                    r = MonoUsbApi.SetConfiguration(device_handle, MY_CONFIG);
                    if (r != 0) { Console.WriteLine("config出错"); };
                    // 索赔接口
                    r = MonoUsbApi.ClaimInterface(device_handle, MY_INTERFACE);
                    if (r != 0) { Console.WriteLine("interface出错"); };
                    labelInfo.Text = "成功打开设备";
                }
            }

    2.然后在按钮的监听器里面实现发送命令的方法:

            private void sendCommand()
            {
                if (device_handle == null)
                {
                    setDevice();
                }
                byte[] data = DataFix.getCommand(interTimes, scanCounts, manual);
                //r = (int)doBulkAsyncTransfer(device_handle, MY_EP_WRITE, command, command.Length, out transferred, MY_TIMEOUT);
                r = MonoUsbApi.BulkTransfer(device_handle, MY_EP_WRITE, data, data.Length, out transferred, MY_TIMEOUT);
                if (r == (int)MonoUsbError.ErrorTimeout)
                {
                    // 写入超时错误信息
                    //Console.WriteLine("Write Timed Out. {0} packet(s) written ({1} bytes)", packetCount, transferredTotal);
                }
                else if (r != (int)MonoUsbError.ErrorTimeout && r != 0)
                {
                    Console.WriteLine("Write failed:{0}", (MonoUsbError)r);
                }
                resultList.Clear();
            }

    3.其实最终的就是第三点,你需要在程序启动的时候就开启一个新的线程,然后里面实现while(true)循环的监听端点口数据的返回

    #region 开启一个新的线程
    xferData = new Thread(DataGetFromPoint);
    xferData.IsBackground = true;
    xferData.Priority = ThreadPriority.Highest;
    xferData.Start();
    #endregion

    DataGetFromPoint()方法

            public void DataGetFromPoint()
            {
                bufDataIn = new byte[inLength];
                while (isContinue)
                {
                    //Console.WriteLine("Reading data....");
                    r = MonoUsbApi.BulkTransfer(device_handle, MY_EP_READ, bufDataIn, inLength, out transferred, MY_TIMEOUT);
                    if (r == (int)MonoUsbError.ErrorTimeout)
                    {
                        //这个可以看出是一个正常的操作
                        //Console.WriteLine("Read Timed Out.");
                    }
                    else if (r != 0)
                    {
                        //除了写入超时错误的信息外,其他的信息会在这里显示
                        Console.WriteLine("Read failed:{0}", (MonoUsbError)r);
                    }
                    else
                    {
                        Console.writeln(DataFix.byteToHexString(bufDataIn));//字节数组转换成16进制字符串显示
                    }
                    //Thread.Sleep(1);//如果线程休眠的话,导致接受的数据不完整....
                }
            }
  • 相关阅读:
    spring mvc 源码简要分析
    tomcat 开启远程debug
    jdk1.5-jdk1.9的主要区别
    关于elasticsearch 6.x及其插件head安装(单机与集群)5分钟解决
    mysql主从配置(5分钟解决问题)
    内部类总结
    Colored Sticks
    vim 将tab转为空格
    shell编程
    vim -- 查找和替换
  • 原文地址:https://www.cnblogs.com/sowhat4999/p/4990960.html
Copyright © 2011-2022 走看看