同步串行端口读/写
本文关键字:串行端口 同步 | 更新日期: 2023-09-27 17:55:45
我正在尝试在Visual Studio 2010中编写一个通过串行连接与微控制器通信的c#程序。我可以很好地读取和写入端口,我只是不确定如何让 send 方法等到收到上一个发送命令中的所有数据后再执行。我已经实现了数据接收事件处理程序,以便它确定何时在串行端口上接收了请求的适当数量的数据。我只需要知道如何让它告诉发送方法端口是免费的。
我曾计划使用互斥锁,但我相信问题不是由于多线程造成的。同一线程在串行端口上一个接一个地发送字符串,并且响应第一个请求而接收的数据与第二个请求冲突。
此外,如果通信由一个线程完成,让该线程等待是否会导致接收的数据事件处理程序无法执行?
(两种方法在同一个类中)
我的发送数据方法:
//method for sending data
public void send(String s)
{
sp.Write(s + "'r");
}
我的数据接收事件处理程序:
//data received event handler
private void dataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string tmp;
tmp = sp.ReadExisting();
//put all received data into the read buffer
readBuffer += tmp;
//add various flag checks to determine end of transmission
if (firmwareFlag)
{
if (readBuffer.EndsWith("'n"))
{
firmwareFlag = false;
//trigger event to tell object owner data is ready
dataReady(this, new CustomEventArgs(readBuffer, "firmware"));
readBuffer = "";
}
}
else if (parameterFlag)
{
if (System.Text.RegularExpressions.Regex.IsMatch(readBuffer, "K90", System.Text.RegularExpressions.RegexOptions.IgnoreCase))
{
parameterFlag = false;
dataReady(this, new CustomEventArgs(readBuffer, "parameters"));
readBuffer = "";
}
}
else
{
dataReady(this, new CustomEventArgs(readBuffer, null));
readBuffer = "";
}
}
我会在类中只使用一个布尔变量和一个计时器。当计时器滴答作响时,您检查该布尔值并在允许的情况下发送数据。
boolean isAllowed;
DispatcherTimer tmr1;
//...etc
我过去有同样的问题,我用这种方式解决了:
我添加了 SendAndWaitResponse 方法,该方法接收端口要发送的缓冲区、响应的预期长度、以秒为单位的超时(以防万一)和回调,当收到预期的响应时:
//System.IO.Ports.SerialPort port;
//port.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived);
void SendAndWaitResponse(String buffer, int expectedLenght, int timeoutInSeconds, Action<String> callback)
{
TimeSpan _timeout = new TimeSpan(0, 0, 0, timeoutInSeconds);
//may not be necesary
if (!string.IsNullOrEmpty(buffer) && buffer != "" && port != null)
{
//Remove current dataReceived event handler, as we will manually manage it for now, will restore later!
this.port.DataReceived -= port_DataReceived;
if (!this.port.IsOpen) this.port.Open(); // open the port if it was closed
this.send(buffer); // send buffer, changed port.write(buffer) so it now usses your own send
DateTime startToWait = DateTime.Now; //start timeout
bool isTimeout = false;
int totalRead = 0;
String read = "";
while (!(isTimeout) && totalRead < expectedLenght)
{
do
{
if (port.BytesToRead > 0)
{
read += (char)this.port.ReadByte();
totalRead++;
//you can add a System.Threading.Thread.Sleep(int); if all bytes come in parts
}
} while (port.BytesToRead > 0);
isTimeout = (DateTime.Now.Subtract(_timeout) >= startToWait);
}
this.port.DataReceived += port_DataReceived; // restore listener
callback(read); //invoke callback!!!
}
}
如果要
检查是否有字节未发送到设备(写入缓冲区中的字节),则可以读取 BytesToWrite 属性。
SerialPort.BytesToWrite 属性