.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必须使用/结尾.
随机推荐
- 通过adb命令查看SN、CID码等信息
用ADB命令来查看自己手机的相关硬件以及其他的参数信息,相信许多机友已经早已查看过,而新入门感兴趣的机友可以尝试一下. 运用这些ADB命令可以很直观的查看到你手机上的硬件与软件方面的详细信息. 下 ...
- 7、jmeter-定时器介绍与使用
jmeter-定时器介绍与使用 固定定时器 Uniform Random Timer Precise Throughput Timer Constant Throughput Timer 高斯随机定时 ...
- XX Russia Team Open, High School Programming Contest St Petersburg, Barnaul, Tbilisi, Almaty, Kremenchug, November 30, 2019
ContestLink easy: AFI medium-easy: BDH medium: CGKL ???: EJ A. Attractive Flowers 签到. B. Blocking th ...
- P3224 [HNOI2012]永无乡(平衡树合并)
题目描述 永无乡包含 nn 座岛,编号从 11 到 nn ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 nn 座岛排名,名次用 11 到 nn 来表示.某些岛之间由巨大的桥连接,通过桥可以从 ...
- 2019-3-15-在-Windows-Defender-设置文件夹白名单提升-VisualStudio-编译速度
title author date CreateTime categories 在 Windows Defender 设置文件夹白名单提升 VisualStudio 编译速度 lindexi 2019 ...
- centos6.8 oracle 11.2.0.4 11g安装
配置Linux系统参数 配置阿里云yum源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup ...
- C/C++通用Makefile
最近的项目又回到了Linux上运行,这就需要在Linux下编译项目,写Makefile针对习惯了Windows的程序员来说是一件痛苦的事,如果有一个通用的Makefile该多好啊,本着这样的目的,我再 ...
- Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci...
最近刚接触mysql,今天用mysql插入中文字符的时候,程序报错“Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_g ...
- margin与padding
1.不加内边距的div: <div style="width:150px; height:150px; "> <div style="width: ...
- The chance for love doesn't come around every day.
The chance for love doesn't come around every day.爱的机会不是每天都有的.