- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个程序可以从 C# 中的串口读取数据。我需要快速写入一个端口,从中读取,然后关闭它。我不能让它打开。我知道串行端口读取和写入速度很慢,我尝试将 ReadTimeout 和 WriteTimeout 属性设置为高,并添加了一个 thread.Sleep 以尝试将设备的读取和写入时间拖出。这是一些代码:
我写入端口的方法:
private void CheckPorts(string testMessage)
{
foreach (string s in SerialPort.GetPortNames())
{
portNumber = Int32.Parse(s.Remove(0, 3));
testSerial = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
if (testSerial.IsOpen)
{
testSerial.Close();
}
testSerial.ReadTimeout = 2000;
testSerial.WriteTimeout = 1000;
testSerial.Open();
if (testSerial.IsOpen)
{
string received;
testSerial.DiscardInBuffer();
try
{
//testSerial.DataReceived += new SerialDataReceivedEventHandler(testSerialPort_DataReceived);
testSerial.Write(testMessage);
System.Threading.Thread.Sleep(2000);
received = testSerial.ReadExisting(); //EITHER I USE THIS OR EVENT HANDLER, NOT BOTH
}
catch (TimeoutException e)
{
testSerial.Close();
continue;
}
if (received.Length > 0)
{
MessageReceived(received);
}
testSerial.Close();
}
}
}
private void testSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string received = testSerial.ReadExisting();
int y = received.IndexOf("\r");
while (y == -1)
{
received = received + testSerial.ReadExisting();
y = received.IndexOf("\r");
}
if (testSerial.IsOpen)
{
testSerial.Close();
}
}
我想知道,如果我绝对必须使用数据处理程序,我如何保持串行端口打开足够长的时间以从中读取数据,但在需要打开下一个端口之前关闭串行端口?
看,第一个方法被调用了几次,它遍历了一个 foreach 循环,尝试在几个端口上发送消息,然后尝试读取响应。所以,在某些时候我必须关闭端口,否则下次它通过它时,它不能正常工作,因为端口仍然打开
这是我更新后的代码(仍然无法使用):
private void CheckPorts(string testMessage, int baudRate)
{
foreach (string s in SerialPort.GetPortNames())
{
var interval = 3000; // ms
var timer = new System.Timers.Timer(interval);
timer.Elapsed += (o, e) =>
{
timer.Enabled = false;
if (testSerial.IsOpen)
testSerial.Close(); // may not be necessary with Dispose?
testSerial.Dispose();
timer.Dispose();
};
portNumber = Int32.Parse(s.Remove(0, 3));
testSerial = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
testSerial.ReadTimeout = 2000;
testSerial.WriteTimeout = 2000;
if (testSerial.IsOpen)
{
testSerial.Close();
}
testSerial.Open();
timer.Enabled = true;
if (testSerial.IsOpen)
{
string received;
//testSerial.DiscardInBuffer();
//autoEvent = new AutoResetEvent(false);
try
{
// testSerial.DataReceived += new SerialDataReceivedEventHandler(testSerialPort_DataReceived);
// autoEvent.Reset();
lblPortNum.Content = s;
lblPortNum.Refresh();
testSerial.Write(testMessage);
//System.Threading.Thread.Sleep(2000);
//testSerial.NewLine = "\r\n";
byte[] rBuff = new byte[2];
int rCnt = testSerial.Read(rBuff, 0, 2);
System.Text.Encoding enc = System.Text.Encoding.ASCII;
received = enc.GetString(rBuff);
//received = testSerial.ReadLine();
}
catch (TimeoutException e)
{
testSerial.Close();
continue;
}
if (received.Length > 0)
{
MessageReceived(received, Int16.Parse(s.Remove(0, 3)));
}
/*
if (autoEvent.WaitOne(2000))
{
// the port responded
// testSerial.Close();
autoEvent.Dispose();
lblPortNum.Content = "HEY I RESPONDED";
}
else
{
testSerial.Close();
autoEvent.Dispose();
continue;
// port did not respond within 2 seconds
}*/
//testSerial.Close();
}
}
}
再次更新(仍然无法正常工作)
private void CheckPorts(string testMessage, int baudRate)
{
foreach (string s in SerialPort.GetPortNames())
{
portNumber = Int32.Parse(s.Remove(0, 3));
// MUST BE LOCAL
var serialOneOfMany = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
serialOneOfMany.ReadTimeout = 2000;
serialOneOfMany.WriteTimeout = 2000;
if (serialOneOfMany.IsOpen)
{
serialOneOfMany.Close();
}
// timer must be defined _after_ serialOneOfMany
var interval = 3000; // ms
var timer = new System.Timers.Timer(interval);
timer.Elapsed += (o, e) =>
{
timer.Enabled = false;
if (serialOneOfMany.IsOpen)
serialOneOfMany.Close(); // may not be necessary with Dispose?
serialOneOfMany.Dispose();
timer.Dispose();
};
if (serialOneOfMany.IsOpen)
{
string received;
try
{
lblPortNum.Content = s;
lblPortNum.Refresh();
serialOneOfMany.Write(testMessage);
byte[] rBuff = new byte[2];
int rCnt = serialOneOfMany.Read(rBuff, 0, 2);
System.Text.Encoding enc = System.Text.Encoding.ASCII;
received = enc.GetString(rBuff);
}
catch (TimeoutException e)
{
serialOneOfMany.Close();
continue;
}
if (received.Length > 0)
{
CheckIfTheMessageMatches(received, Int16.Parse(s.Remove(0, 3)));
}
}
}
}
所以在这个更新中,它只是通过代码,我可以逐行通过代码,但它不会停止 3 秒。如果我在没有任何调试中断的情况下运行它,它只会在几分之一秒内通过它
11 月 25 日更新
private void CheckPorts(string testMessage, int baudRate)
{
foreach (string s in SerialPort.GetPortNames())
{
string received = "";
testSerial = new SerialPort(s,baudRate, Parity.None, 8, StopBits.One);
lblStatus.Content = "Scanning...";
lblStatus.Refresh();
if (testSerial.IsOpen)
{
testSerial.Close();
}
else
{
testSerial.Open();
}
if (testSerial.IsOpen)
{
try
{
testSerial.NewLine = "\r";
lblPortNum.Content = s;
lblPortNum.Refresh();
testSerial.WriteTimeout= 500;
testSerial.ReadTimeout = 1000;
testSerial.WriteLine(testMessage);
System.Threading.Thread.Sleep(500);
/*THIS DOESN'T WORK
byte[] buffer = new byte[testSerial.BytesToRead];
int rCnt = testSerial.Read(buffer, 0, buffer.Length);
received = enc.GetString(buffer);*/
//received = Convert.ToString(testSerial.BaseStream.Read(buffer, 0, (int)buffer.Length));
received = testSerial.ReadLine();
int y = received.IndexOf("\r");
while (y == -1)
{
received = received + testSerial.ReadExisting();
y = received.Length;
}
if (lblInfo.Dispatcher.Thread == Thread.CurrentThread)
{
CheckIfTheMessageMatches(received, s);
received = received + lblInfo.Content;
lblInfo.Content = received;
}
else
{
lblInfo.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadCheck(threadCheck), received);
}
if (testSerial.IsOpen)
{
testSerial.Close();
}
/*I USE THIS WITH THE sPort.Read() METHOD
while (rCnt > 0)
{
if (lblInfo.Dispatcher.Thread == Thread.CurrentThread)
{
CheckIfTheMessageMatches(received, s);
rCnt = 0;
received = received + lblInfo.Content;
lblInfo.Content = received;
}
else
{
lblInfo.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadCheck(threadCheck), received);
}
}
*/
if (testSerial.IsOpen)
{
testSerial.Close();
}
}
catch (TimeoutException e)
{
testSerial.Close();
continue;
}
received = null;
}
}
lblStatus.Content = "Finished Scanning.";
lblPortNum.Content = "";
}
更新代码这是一些新代码,仍然无法正常工作,甚至没有调用 dataeventhandler 一次。我知道它正在接收消息,因为我有另一个与串行设备一起使用的程序
private void CheckPorts(string testMessage, int baudRate)
{
foreach (string s in SerialPort.GetPortNames())
{
var serialOneOfMany = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
serialOneOfMany.ReadTimeout = 700;
serialOneOfMany.WriteTimeout = 100;
var interval = 500; // ms
var timer = new System.Timers.Timer(interval);
timer.Elapsed += (o, e) =>
{
timer.Enabled = false;
if (serialOneOfMany.IsOpen)
serialOneOfMany.Close(); // may not be necessary with Dispose?
serialOneOfMany.Dispose();
timer.Dispose();
};
timer.Enabled = true;
lblStatus.Content = "Scanning...";
lblStatus.Refresh();
if (serialOneOfMany.IsOpen)
{
serialOneOfMany.Close();
}
else
{
serialOneOfMany.Open();
}
if (serialOneOfMany.IsOpen)
{
string received;
try
{
lblPortNum.Content = s;
lblPortNum.Refresh();
serialOneOfMany.WriteLine(testMessage);
System.Threading.Thread.Sleep(400);
serialOneOfMany.DataReceived += new SerialDataReceivedEventHandler(testSerialPort_DataReceived);
}
catch (TimeoutException e)
{
serialOneOfMany.Close();
continue;
}
}
}
lblStatus.Content = "Finished Scanning.";
lblPortNum.Content = "";
}
private void testSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort receivingSerial = sender as SerialPort;
string received = receivingSerial.ReadExisting();
int y = received.IndexOf("\r");
while (y == -1)
{
received = received + receivingSerial.ReadExisting();
y = received.IndexOf("\r");
}
if (lblInfo.Dispatcher.Thread == Thread.CurrentThread)
{
string name = receivingSerial.PortName;
received = received + lblInfo.Content;
lblInfo.Content = received;
CheckIfTheMessageMatches(received, name);
}
else
{
lblInfo.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadCheck(threadCheck), received);
}
if (receivingSerial.IsOpen)
{
receivingSerial.Close();
}
}
最佳答案
您应该能够同时执行这些操作(假设没问题)。然后,您将在引发 DataReceived
事件(删除无关代码)时关闭它们。只是不要关闭 CheckPorts
中的端口。
private void testSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort localSerialPort = sender as SerialPort;
... // use localSerialPort instead of global/class variable
if (localSerialPort.IsOpen)
{
localSerialPort.Close();
}
}
编辑:回应评论。
您可以随时添加一个计时器。如果你把它放在 foreach 循环中,你会为每个串行端口获得一个计时器,该计时器将在 3 秒后处理其给定的串行端口。在 foreach 循环中声明计时器在这里很重要。
var interval = 3000; // ms
var timer = new System.Timers.Timer(interval);
timer.Elapsed += (o,e) =>
{
timer.Enabled = false;
if (testSerial.IsOpen)
testSerial.Close(); // may not be necessary with Dispose?
testSerial.Dispose();
timer.Dispose();
}
timer.Enabled = true;
编辑:代码已更新,所以我会更新
范围对于我提供的代码非常重要。您应该摆脱非本地 testSerial 或在此处使用完全不同的名称。
portNumber = Int32.Parse(s.Remove(0, 3));
// MUST BE LOCAL
var serialOneOfMany = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
serialOneOfMany.ReadTimeout = 2000;
serialOneOfMany.WriteTimeout = 2000;
if (serialOneOfMany.IsOpen)
{
serialOneOfMany.Close();
}
// timer must be defined _after_ serialOneOfMany
var interval = 3000; // ms
var timer = new System.Timers.Timer(interval);
timer.Elapsed += (o, e) =>
{
timer.Enabled = false;
if (serialOneOfMany.IsOpen)
serialOneOfMany.Close(); // may not be necessary with Dispose?
serialOneOfMany.Dispose();
timer.Dispose();
};
关于c# - serialport 响应 EventHandler,但不响应 ReadExisting 或 ReadLine?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7572596/
我有一个 SerialPort 用于连接到虚拟 COM 端口。由于连接是持久的,我必须保留对 SerialPort 的引用,以便打开、关闭和管理端口。我还在我的类上实现了 IDisposable(不是
我正在尝试使用node.js串行端口模块在运行时获取设备的COM端口。 const SerialPort = require('serialport'); var fs = require('fs')
我目前有一个使用 VB6 代码制作的程序,该程序使用 MSCOMM 控件从串行端口拉回数据。这成功地从我的串行端口接收数据,其中连接了 Denso BHT-904B 设备。 我现在正尝试将此代码移至
从 SerialPort 对象外部看,写入缓冲区的大小以及是否已满似乎没有区别。 使用同步写入,write 方法会阻塞,直到所有数据都已发送且缓冲区为空。 使用异步写入,数据排队,程序继续运行。直到写
我正在用 C# 开发一个 .NET 4.0 WPF 应用程序,它通过 RS232 控制电机。我在退出应用程序时遇到问题,应用程序有时会在关闭端口时死锁。 在互联网上进行一些研究后,我注意到这是一个常见
这个问题的灵感来自这里的问题和答案: Passing a Command to a Comm Port Using C#'s SerialPort Class 这个问题本身回答了我遇到的一些问题,但也
假设我们有以下代码: SerialPort port = new SerialPort("COM2", 115200); port.Open(); // Thread.Sleep(5000); //
使用串行端口库的人注意到了这一点,还是只有我?我发现(非常)很少有人处于相同的情况,但我没有找到解决方案。 这是我使用 ruby serialport 得到的示例: ff d8 ff e0 00
我正在使用 Ruby 1.8.7 SerialPort gem 通过 FTDI232 USB 转串口转换器与 AVR 通信。我似乎遇到了 SerialPort 初始化新 SerialPort 的问题。
我正在开发需要与 COM 端口交互的程序。 从这个问答中学习:.NET SerialPort DataReceived event not firing , 我这样写我的代码。 namespace C
我正在监听串口 5 个字节的信息。轮询的完整答案需要 5 个字节。我的代码监听 serialport data_received 事件并检查 bytesToRead。有时,事件会触发并且 bytesT
我有一个 USB 电话连接到我的电脑上 我如何使用串口检测它所在的 COM? 最佳答案 遍历所有 COM 端口并尝试从每个端口获取一个标识。下面是一个最小的示例,应该对其进行扩展以进行更好的错误检查等
因为我是多线程应用程序的新手,所以我想在开始编写代码之前从更有经验的人那里得到一些建议... 我需要在串口事件中对串口接收到的数据进行排队,以便进一步处理。 所以我有以下事件处理程序: voi
我正在开发需要与 COM 端口交互的程序。 从这个问答中学习:.NET SerialPort DataReceived event not firing , 我这样写我的代码。 namespace C
偶尔,我的一些集成测试会因上述消息而失败。我正在使用下面的代码来准备端口。 for(int i = 0; i < 5; i++) {
我有两个设备想通过串行接口(interface)连接,但它们的连接不兼容。为了解决这个问题,我将它们都连接到我的 PC,并且我正在开发一个 C# 程序,它将 COM 端口 X 上的流量路由到 COM
我在尝试让串行端口接收正确消息时遇到了很多问题。它不断截断消息。这是我的代码,我将在代码之后尝试详细说明。 public SerialComms(SerialPort sp) { this.sp
我正在使用串行通信,我想知道是否应该保持 SerialPort 打开? 我正在创建一个命令队列,一次只会运行一个。我应该创建一个 SerialPort 并在每个命令中打开/关闭它,还是应该有另一个类来
我一直在尝试使用模块 Win32::SerialPort在 perl 5.10 (也许它与 5.14 有一些问题)。我必须向串行端口发出命令并获取它们的输出。我已经发现 write 将为我完成前面的部
我有一个 WPF 测试应用程序,用于评估基于事件的串行端口通信(与轮询串行端口)。问题是 DataReceived 事件似乎根本没有触发。 我有一个非常基本的 WPF 表单,其中包含用于用户输入的 T
我是一名优秀的程序员,十分优秀!