想做一个串口的握手功能,遇到下面的问题:
当baudRateList 只有一个9600时,通讯可以成功;
但当baudRateList 中有多个波特率时,就通讯不上了。
求指教,在线等。
using System.IO.Ports;
public class MySerialPort : SerialPort
{
// public readonly int[] baudRateList = { 9600 };
private readonly int[] baudRateList = { 115200, 57600, 38400, 19200, 9600 };
public string receivedString;
public ManualResetEvent receivedFlag = new ManualResetEvent(false);
public bool HandShake()
{
bool ret = false;
int handShakeLimits = 4;
int retryCount;
foreach (int baudRate in baudRateList)
{
this.BaudRate = baudRate;
this.Close();
this.Open();
this.DiscardInBuffer();
this.DiscardOutBuffer();
this.Write(GetInstructions.serialNum + "\n");
// 等待100毫秒,检查 receivedFlag是否设置为true。如果没有,继续循环
retryCount = 0;
while (!receivedFlag.WaitOne(100))
{
if (retryCount++ >= handShakeLimits)
{
receivedFlag.Reset();
break;
}
}
if (retryCount < handShakeLimits)
{
ret = true;
break;
}
}
return ret;
}
public void GppSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
receivedFlag.Set();
if (sender is SerialPort serialPort)
{
// 将缓冲区回车符前所有内容读取出来
ReceivedString = serialPort.ReadLine();
serialPort.DiscardInBuffer();
serialPort.DiscardOutBuffer();
}
}
}
我随手写一个看看,没设备。所以只是演示如何做这种传统的异步回调的同步模拟方法
public class MySerialPort : SerialPort
{
public MySerialPort(string portName) : base(portName)
{
}
private readonly int[] baudRateList = { 115200, 57600, 38400, 19200, 9600 };
public bool CheckHandShake()
{
bool ret = false;
int handShakeLimits = 4;
int retryCount;
foreach (int baudRate in baudRateList)
{
if (this.IsOpen)
{
this.Close();
}
this.BaudRate = baudRate;
this.Open();
this.DiscardInBuffer();
this.DiscardOutBuffer();
this.Write("xxx" + "\n");
if (CheckProtcol())
{
break;
}
}
return ret;
}
private bool CheckProtcol()
{
//你这里都用传统代码,所以我们也不用啥task异步一类的玩意,免得废半天劲,你来句我net2的
ManualResetEvent receivedFlag = new ManualResetEvent(false);
bool Received = false;
SerialDataReceivedEventHandler mye = null;
//这里直接定义局部委托,使用函数式手段将逻辑封在一个方法,避免传统的vb,net1.1时代那种事件割裂逻辑,造成你原来那种看着的费劲的代码
mye = ((send, e) =>
{
//这里其实还有一些协议内容检查,我就不想写了,但是你那里不能已是否收到数据为基准,比如modbus你发给他不认识的,他会回发一个error封包,所以还是以双方约定的协议内容为基准,而不是以收到为基准
this.DataReceived -= mye;
Received = true;
receivedFlag.Set();
});
this.DataReceived += mye;
receivedFlag.WaitOne(400); //这里直接使用400ms超时,不需要用哪个看着郁闷的计数器,逻辑上是有符合需要的数据set就通过了,没有符合的数据最多等待400ms
if (!Received)
{
this.DataReceived -= mye; //如果没有复合的数据,把临时给的委托注销掉,避免后续进入
}
return Received;
}
}
代码写的不太好看。所以我就不仔细看了。
所以我就说2个点
1.检查那个锁。单个能进,多个不能进,那么我怀疑这个锁(当然这里为啥弄个锁也是很奇怪啊)
2。检查isopen的情况,串口是独占,他不能重复打开,所以尝试修改波特率前需要保证串口是关闭的