.Net串口通讯中的若干问题(C#多串口硬件识别、热插拔、Close方法报错问题、IsOpen的可靠性问题)
一、需求场景
最近有时间静下心来研究SDK,串口通讯的。要求实现识别cp210x和cp2303驱动的两款硬件,并且2303的优先级高,即有2303识别之,没有再识别210x;要求实现热插拔,拔掉自动断开,插上自动连接。
二、问题一:如何实现串口硬件的识别呢?
1、如果方便的话,SerialPort的Handshake这个字段值得深入研究,可以利用这个实现;
2、添加自定义的握手协议,本人用一个5字节的串进行校验(第三位是硬件版本标识),校验算法如下:
for (int i = ; i < btData.Length; i++)
{
if ((i % ) == ) commit = ;
if (btData[i].ToString().Equals(byteMitt[i % ]) || i % == )
commit++;
if (commit == )
{
SendMessage(EnumDataConverter.GetCommandStatus(SendCommandType.Test) +
intDeviceCount.ToString().PadLeft(, ''));
tpVersion = btData[].ToString();
IsConnected = true;
strDeviceName = tempPort.Value;
return true;
}
} //校验完毕没有成功,进入下次循环
二、热插拔的监听问题
经过实践,cp210x可以在串口设备表中查询到,cp2303不可不发现,故而采用查询计算机设备表的方式
备注:
System.IO.Ports.SerialPort.GetPortNames()只能获取设备名,不能获取详细信息(类型等),我下面用来进行一些比对的逻辑操作
private void CreateUSBWatcher()
{
Ports = System.IO.Ports.SerialPort.GetPortNames();
//建立监听
ManagementScope scope = new ManagementScope("root\\CIMV2");
scope.Options.EnablePrivileges = true;
//建立插入监听
try
{
WqlEventQuery USBInsertQuery = new WqlEventQuery("__InstanceCreationEvent", "TargetInstance ISA 'Win32_PnPEntity'");
USBInsertQuery.WithinInterval = new TimeSpan(, , );
USBInsert = new ManagementEventWatcher(scope, USBInsertQuery);
USBInsert.EventArrived += USBInsert_EventArrived;
USBInsert.Start();
}
catch (Exception ex)
{
if (USBInsert != null)
{
USBInsert.Stop();
}
throw ex;
}
//建立拔出监听
try
{
WqlEventQuery USBRemoveQuery = new WqlEventQuery("__InstanceDeletionEvent", "TargetInstance ISA 'Win32_PnPEntity'");
USBRemoveQuery.WithinInterval = new TimeSpan(, , );
USBRemove = new ManagementEventWatcher(scope, USBRemoveQuery);
USBRemove.EventArrived += USBRemove_EventArrived;
USBRemove.Start();
}
catch (Exception ex)
{
if (USBRemove != null)
{
USBRemove.Stop();
}
throw ex;
}
}
/// <summary>
/// USB设备插入
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void USBInsert_EventArrived(object sender, EventArrivedEventArgs e)
{
string[] tempPorts = System.IO.Ports.SerialPort.GetPortNames();
if (tempPorts.Count() == Ports.Count())
return;
else
Ports = tempPorts; if (IsConnected)
return; if (blnDesireConnected && Open())
commExecuteInterface?.DeviceArrivaled();
} /// <summary>
/// USB设备拔出
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void USBRemove_EventArrived(object sender, EventArrivedEventArgs e)
{
string[] tempPorts = System.IO.Ports.SerialPort.GetPortNames();
if (tempPorts.Count() == Ports.Count())
return;
else
Ports = tempPorts; if (!IsConnected)
return; IsConnected = false;
spUSB.Close();
commExecuteInterface?.DeviceRemoved();
}
三、调用Close方法会提示“ unsafe handler 已关闭”
微软的方法有问题的,微软的SerialPort的这个类有问题,一但断开硬件的连接,会触发部分对象资源的释放(SerialPort不是单纯的托管资源,非托管资源被释放了),因此调用Close会出问题,除非此进程完全退出,所以SerialPort的资源需要重置;SerialPort的初始化方法中有一个是有IContainer参数的,IContainer提供了非托管资源的管理方法,因此,把SerialPort对象放到一个容器中可解决Close问题;即,想实现热插拔,必须把SerialPort放到容器中!
spUSB = new SerialPort(container);
KeyValuePair<string, string> tempPort = queueSerialPorts.Dequeue();
spUSB.BaudRate = ;
spUSB.PortName = tempPort.Key; spUSB.Open();
SendMessage(EnumDataConverter.GetCommandStatus(SendCommandType.ECC)); //尝试让主控机复位 byte[] btData = ReadData();
四、IsOpen属性并不可靠,尽量少用
有问题可以加qq群:568055323
.Net串口通讯中的若干问题(C#多串口硬件识别、热插拔、Close方法报错问题、IsOpen的可靠性问题)的更多相关文章
- vue中使用ts后,父组件获取执行子组件方法报错问题
一.问题产生背景: 子组件的一个方法: update () { this.$nextTick(() => { this.ul_slots.forEach((ul, cur_slots_index ...
- 项目实体类使用@Data注解,但是项目业务类中使用getA(),setA()方法报错,eclipse中配置lombok
@Data注解来源与Lombok,可以减少代码中大量的set get方法,大量减少冗余代码,但是今天部署项目时候,发现实体类使用@Data注解,但是项目业务类中使用getA(),setA()方法报错. ...
- eclipse中运行 main 方法报错,找不到类
eclipse (maven 项目)中运行 main 方法报错,找不到类 ** 发现:在 eclipse中的 "Marker" 控制面板中 ,发现问题所在 只要删除 maven 仓 ...
- C# 16进制与字符串、字节数组之间的转换(串口通讯中)
1.c#中如何将十进制数的字符串转化成十六进制数的字符串//十进制转二进制 Console.WriteLine("十进制166的二进制表示: "+Convert.ToString( ...
- C#串口通讯中常用的16进制的字节转换
1.对于通讯协议的十六进制数值进行简单转换 //二进制转十进制Console.WriteLine("二进制 111101 的十进制表示: "+Convert.ToInt32(&qu ...
- php中使用end方法报错
<b>Strict Standards</b>: Only variables should be passed by reference in <b> 1.如果 ...
- Node.js中读取文件后用Json.parse方法报错
今天,在调试一个node项目时,发现了一个很大的坑,在此分享给大家! 大家都知道,Json.parse()方法对格式要求是很严格的,格式不对极其容易报错,但是有时候格式看似是正确的也会报错. 比如这一 ...
- Node.js中读取文件后用Json.parse方法报错解决方案
今天,在调试一个node项目时,发现了一个很大的坑,在此分享给大家! 大家都知道,Json.parse()方法对格式要求是很严格的,格式不对极其容易报错,但是有时候格式看似是正确的也会报错. 比如这一 ...
- django中使用POST方法报错 URL via POST, but the URL doesn't end in a slash
该方式是因为URL路径没有使用slash(斜线"/")结尾造成的. 因此在使用POST的JavaScript函数的路径参数中,路径URL必须使用/结尾.
随机推荐
- Promise 的深度学习
1.Promise 是什么? Promise 是异步编程的一种解决方案,比传统的解决方案–回调函数和事件--更合理和更强大.Promise ,简单说就是一个容器,里面保存着某个未来才回结束的事件(通常 ...
- createBottomTabNavigator: 怎么在切换tab的时候让页面重新渲染
1.import withNavigationFocus from react-navigation to your class . 2.hen export your like this : exp ...
- 框架集 frameset
框架集和内联框架的作用类似,都用于在一个页面中引入其他的外部的页面 框架集可以同时引入多个页面,而内联框架引入一个, 在h5标准中,推荐使用框架集,而不使用内联框架 使用 frameset 来创建一个 ...
- Xcode使用篇-重新安装Xcode
卸载Xcode sudo rm -rf /Applications/Xcode.app sudo rm -rf /Library/Preferences/com.apple.dt.Xcode.plis ...
- uuencode - 对二进制文件编码
总览 (SYNOPSIS) uuencode [-m] [ file ] name uudecode [-o outfile] [ file ]... 描述 (DESCRIPTION) Uuencod ...
- js 购物车的数量加减,对应的总价也随机变化
html相关的源码: <div class="goods_num clearfix"> <div class="num_name fl"> ...
- ul -- li 模拟select下拉框
在写项目中 用到下拉框,一般用 <select name="" id=""> <option value=</option> &l ...
- sublime中Snippe的使用
Sublime Text号称最性感的编辑器, 并且越来越多人使用, 美观, 高效 关于如何使用Sublime text可以参考我的另一篇文章, 相信你会喜欢上的..Sublime Text 2使用心得 ...
- Java再谈方法
1.3再谈方法 1.3.1 什么是方法(函数) ①方法是类或对象行为特征的抽象,也称为函数. ②Java里的方法不能独立存在,所有的方法必须定义在类里. 修饰符 返回值类型 方法名(参数类型 形参1, ...
- CSS四种定位及应用
定位(position) 如果,说浮动, 关键在一个 “浮” 字上面, 那么 我们的定位,关键在于一个 “位” 上. PS: 定位是我们CSS算是数一数二难点的了,但是,你务必要学好它,我们CSS离不 ...