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 = ;
private const byte MY_EP_READ = 0x81;//读端点口地址
private const byte MY_EP_WRITE = 0x01;//写端点口地址
private const int MY_INTERFACE = ;//接口地址
private const short MY_PID = 0x0053;//设备的VID PID信息
private const short MY_VID = 0x04d8;
#endregion #region TEST SETUP
private const int MY_TIMEOUT = ;//读写超时时间
private const int TEST_LOOP_COUNT = ; private const int TEST_READ_LEN = ; private const bool TEST_REST_DEVICE = true;
private const int TEST_WRITE_LEN = ; 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 = ; i < len; i++)
data[i] = (byte) ( + (i & 0xf));
} private static void memset(byte[] data, int value, int len)
{
int i;
for (i = ; 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, );
/* 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 = ;
MonoUsbTransfer transfer = new MonoUsbTransfer();
if (transfer.IsInvalid) return MonoUsbError.ErrorNoMem; MonoUsbTransferDelegate monoUsbTransferCallbackDelegate = bulkTransferCB;
int[] userCompleted = new int[] {};
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 < )
{
transfer.Free();
gcUserCompleted.Free();
return e;
}
int r;
Console.WriteLine("Transfer Submitted..");
while (userCompleted[] == )
{
e = (MonoUsbError) (r = Usb.HandleEvents(sessionHandle));
if (r < )
{
if (e == MonoUsbError.ErrorInterrupted)
continue;
transfer.Cancel();
while (userCompleted[] == )
if (Usb.HandleEvents(sessionHandle) < )
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 = ;
int transferred;
byte[] testWriteData = new byte[TEST_WRITE_LEN];
byte[] testReadData = new byte[TEST_READ_LEN]; if (args.Length > )
{
switch (args[].ToLower())
{
case "sync":
TEST_MODE = TestMode.Sync;
break;
case "async":
TEST_MODE = TestMode.Async;
break;
}
} fillTestData(testWriteData, TEST_WRITE_LEN);
memset(testReadData, , TEST_READ_LEN); int loopCount = ;
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 != ) break; // Claim interface
Console.WriteLine("Set Interface..");
r = MonoUsbApi.ClaimInterface(device_handle, MY_INTERFACE);
if (r != ) break; /////////////////////
// Write test data //
/////////////////////
int packetCount = ;
int transferredTotal = ;
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 == )
{
packetCount++;
transferredTotal += transferred;
}
// Keep writing data until an error occurs or
// 4 packets have been sent.
} while (r == && packetCount < ); 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 != )
{
// An error, other than ErrorTimeout was received.
Console.WriteLine("Write failed:{0}", (MonoUsbError) r);
break;
}
////////////////////
// Read test data //
////////////////////
Console.WriteLine("Reading test data..");
packetCount = ;
transferredTotal = ;
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 != )
{
// 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, , transferred));
}
// Keep reading data until an error occurs, (ErrorTimeout)
} while (r == );
} 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("\nDone! [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 != ) { Console.WriteLine("config出错"); };
// 索赔接口
r = MonoUsbApi.ClaimInterface(device_handle, MY_INTERFACE);
if (r != ) { 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 != )
{
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 != )
{
//除了写入超时错误的信息外,其他的信息会在这里显示
Console.WriteLine("Read failed:{0}", (MonoUsbError)r);
}
else
{
Console.writeln(DataFix.byteToHexString(bufDataIn));//字节数组转换成16进制字符串显示
}
//Thread.Sleep(1);//如果线程休眠的话,导致接受的数据不完整....
}
}
C#开发usb通知之bulk传输的更多相关文章
- 李洪强iOS开发之通知的使用
李洪强iOS开发之通知的使用 01 - 在A中发送通知 02 - 在B中监听通知 03 - 在B中通知出发的方法 04 - 在B控制器viewDidLoad调用通知
- Android开发——Notification通知的各种Style详解
本来是想与之前讲解使用Notification通知使用一起写的,查看了资料,觉得有必要将这Style部分单独拿出来讲解 前篇:Android开发——Notification通知的使用及Notifica ...
- Android开发——Notification通知的使用及NotificationCopat.Builder常用设置API
想要看全部设置的请看这一篇 [转]NotificationCopat.Builder全部设置 常用设置: 设置属性 说明 setAutoCancel(boolean autocancel) 设置点击信 ...
- 用DriverStudio开发USB驱动程序
很多写Windows Device Driver的开发人员基本上都是使用Windows DDK进行开发的.但是,现在也有不少人都开始借助一些辅助工具.笔者去年开始接触到DriverStudio,发现它 ...
- iOS开发系列--通知与消息机制
概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知机制就可以告诉用户此时发生的事情.iOS中通知机制又叫消息机制,其包括两类:一类是本地 ...
- ios开发之通知事件
每天学习一点点,总结一点点,成功从良好的习惯开始! 昨天学习了ios开发中的关于通知事件的一些东西,在这里简单总结下,仅供初学者学习,更多的是怕我自己忘了,咩哈哈~~~~ 通知(notificatio ...
- Android Wear开发 - 卡片通知 - 第二节 : 自定义Wear卡片样式
一.前言说明 在上一节添加Android Wear通知特性我们实现了简单的Android Wear卡片拓展,但是默认提供给我们的多张卡片只能实现简单的文字展示,如果想要自定义布局,添加图片等等,则需要 ...
- Android Wear开发 - 卡片通知 - 第一节 : 添加Android Wear通知特性
一. 前言说明 Android Wear大部分显示形式是卡片的形式,而最简单地支持Android Wear方式就是用通知**Notification**.而实现最简单的,非高度自定义的通知,则只需要在 ...
- iOS开发之通知中心(NSNotificationCenter)
前言 面向对象的设计思想是把行为方法封装到每一个对象中,以用来增加代码的复用性.正是这种分散封装,增加了对象之间的相互关联,总是有很多的对象需要彼此了解以及相互操作! 一个简单示例说明这种交互产生的对 ...
随机推荐
- P1579 哥德巴赫猜想(升级版)
程序是人类的财富!!11 ------------------------------------------- 题目链接:MIKU OK,Let's gi; -------------------- ...
- 【转】ROWNUM与ORDER BY先后关系
源地址:http://www.cnblogs.com/accumulater/p/6137385.html
- 最短路【洛谷P3393】 逃离僵尸岛
P3393 逃离僵尸岛 题目描述 小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家. 该国有N个城市,城市之间有道路相连.一共有M条双向道路.保证没有自环和重边. K个城市已经被 ...
- 10.18 NOIP2018提高组模拟题(二)
大水题 1.咒语 (curse.pas/c/cpp) [题目描述] 亮亮梦到自己来到了魔法城堡,但一扇巨大的石门阻拦了他通向城堡内的路.正当他沮丧之际,突然发现门上有一处机关,机关上有一张很长的纸条. ...
- 钉钉jsapi免登获取code中,出现对应企业没有某域名微应用
在使用jsapi中.出现 {"errorMessage":"对应企业没有某域名微应用",:"errorCode":"3" ...
- MySql8最新配置方式(完美)
下载MYSQL8 地址:https://www.mysql.com/downloads/ 1.滑动网页到最下面,选择Community (GPL) Downloads » 2.选择MySQL Comm ...
- freemarker ! 用法
${(user.name)!""} 请注意,是打了()的 也就是它会先判断user是不是为null 在判断user.name 是不是为null
- poj3040 发工资(贪心)
题目传送门 题目大意:给一个人发工资,给出不同数量不同面额,(大面额一定是小面额的倍数),问最多能发几天,(每天实发工资>=应发工资). 思路:首先,将大于等于c的面额的钱直接每个星期给奶牛一张 ...
- java算法外传之靠工资多久能实现小目标...
public static void main(String[] args) { //小目标 final int smallGoal=100_000_000; //月份 int month=1; // ...
- 自动截取sql并合并,生成执行HQL
### 提取SQL语句 FILE_PATH="/data/SCRIPT" cat tables | while read file do echo "-----> ...