Windows 10-64。去年秋天,我编写了一个小型VB应用程序,用于从RS-232端口驱动"PR-705“串行设备。它运行得天衣无缝。现在,每当我启动该代码时,PR-705的响应都不是很好?我最初使用的是基于FTDI的USB转RS232适配器(Thunderlinx1000),它工作得很好。我想,问题可能和“司机”有关?因此,我添加了一个PCI-Express串行端口卡从StarTech到我的PC。结果:没有改进-同样的反复无常的行为?出于好奇,今天早上,我启动了我值得信赖的Windows HyperTerminal,它工作得天衣无缝(从PCI-e端口出来)!所以我知道问题不是来自设备本身(叹气!)而是在通信链中的某处。
我遇到的问题如下(希望你能检测到一个“模式”):
a)打开串行端口b)以ASCII字符串(例如,"M1") <-设备返回数据以从设备获取所有数据,但是,我必须发送额外的命令: c) "D2“d) "D3”e) "D4“f) "D5”
当我从HyperTerminal运行这些命令时,我得到了出色的行为。
然而,在我的应用程序中,额外的命令("D2“、"D3”、"D4“和"D5")不知何故无法到达设备?例如,当我发送"D2“时,我得到的是"XYZ”数据,这是正常的。但是当我继续使用"D3“时,我仍然得到相同的"XYZ”数据吗?这就好像新命令("D3")从未到达设备?
我的(丑陋的)解决方法是重新发送相同的命令,然后我得到新的数据(大多数时候)。
下面是我的一些代码:
Dim myPort As New IO.Ports.SerialPort("COM2") With {
.BaudRate = 9600,
.DataBits = 8,
.StopBits = IO.Ports.StopBits.One,
.Parity = IO.Ports.Parity.None,
.Handshake = IO.Ports.Handshake.RequestToSend,
.RtsEnable = True,
.DtrEnable = True,
.ReadTimeout = 1000000,
.WriteTimeout = 10000
}
myPort.Open()
myPort.WriteLine("M1")
myPort.WriteLine("D2")
Incoming = myPort.ReadLine()
myPort.WriteLine("D2")
Incoming = myPort.ReadLine()
myPort.WriteLine("D3")
Incoming = myPort.ReadLine()
myPort.WriteLine("D4")
Incoming = myPort.ReadLine()
myPort.WriteLine("D5")
Incoming = myPort.ReadLine()我知道TimeOut的值是“极端的”,但设备可能需要15分钟才能回复,这取决于具体情况。我不能在设备响应之前关闭端口,否则我会收到一个错误,这与CTS有关,然后设备会自动重新启动--这不是很理想。我不是RS-232专家,但我用我的一点知识尽我所能做到最好。
发布于 2020-02-25 22:57:52
我找到了我的串口问题的部分答案,但这个解决方案并非没有它自己的问题。我发现了一些我改编的c#代码,其中串行端口“接收”被分成了自己的“事件”。这个很好用。正如您将在下面的代码中看到的,它可以完成这项工作。但现在我面临的问题是,如何“连续”轮询端口以获取仪器返回的所有数据?
下面是c#代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
namespace WindowsApplication14
{
public partial class Form1 : Form
{
string Operation, MesureM1, MesureD2, MesureD3, MesureD4;
SerialPort _serialPort;
// delegate is used to write to a UI control from a non-UI thread
private delegate void SetTextDeleg(string text);
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
try
{
if (!_serialPort.IsOpen)
_serialPort.Open();
_serialPort.Write("PR705\r\n");
}
catch (Exception ex)
{
MessageBox.Show("Error opening serial port :: " + ex.Message, "Error!");
}
}
private void Form1_Load(object sender, EventArgs e)
{
_serialPort = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One);
_serialPort.Handshake = Handshake.RequestToSend;
_serialPort.RtsEnable = true;
_serialPort.DtrEnable = true;
_serialPort.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
_serialPort.ReadTimeout = 500;
_serialPort.WriteTimeout = 500;
_serialPort.Open();
_serialPort.Write("PR705\r\n");
}
private void btnM1_Click(object sender, EventArgs e)
{
Operation = "M1";
_serialPort.Write("M1\r\n"); // 0000,111,3.896e+002,0.3371,0.3563
Thread.Sleep(500);
}
private void btnD2_Click(object sender, EventArgs e)
{
Operation = "D2";
_serialPort.Write("D2\r\n");
Thread.Sleep(500);
}
private void btnD3_Click(object sender, EventArgs e)
{
Operation = "D3";
_serialPort.Write("D3\r\n");
Thread.Sleep(500);
}
private void btnD4_Click(object sender, EventArgs e)
{
Operation = "D4";
_serialPort.Write("D4\r\n");
Thread.Sleep(500);
}
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(500);
string data = _serialPort.ReadLine();
this.BeginInvoke(new SetTextDeleg(si_DataReceived), new object[] { data });
}
private void si_DataReceived(string data)
{
String Result = data.Trim();
textBox1.Text = Result;
switch (Operation)
{
case "M1":
MesureM1= Result; // MesureBase = "0000,111,3.884e+002,0.3377,0.3570"
break;
case "D2":
MesureD2 = Result; // MesureD2 = "0000,111,3.674e+002,3.884e+002,3.322e+002"
break;
case "D3":
MesureD3 = Result; // MesureD3 = "0000,111,3.884e+002,0.2044,0.4862"
break;
case "D4":
MesureD4 = Result; //
break;
default:
break;
}
}
}
}在我的主窗体中,我有四个按钮和一个文本框。M1按钮用于进行测量(向仪器发送"M1“命令)。按钮D2、D3和D4用于从仪器中检索数据。
在我以前的VB应用程序中,我使用如下代码从仪器中连续检索数据:
myPort.WriteLine("M1")
myPort.WriteLine("D2")
Incoming = myPort.ReadLine()
myPort.WriteLine("D3")
Incoming = myPort.ReadLine()
myPort.WriteLine("D4")
Incoming = myPort.ReadLine()但是我不知道如何在c#中使用“分离”的方法来完成同样的事情?我尝试将读取操作集中在与M1按钮相同的"event“子按钮中,如下所示:
private void btnM1_Click(object sender, EventArgs e)
{
Operation = "M1";
_serialPort.Write("M1\r\n"); // 0000,111,3.896e+002,0.3371,0.3563
Thread.Sleep(500);
Operation = "D2";
_serialPort.Write("D2\r\n");
Thread.Sleep(500);
Operation = "D3";
_serialPort.Write("D3\r\n");
Thread.Sleep(500);
Operation = "D4";
_serialPort.Write("D4\r\n");
Thread.Sleep(500);
}但它不工作,我只得到最后一个串口读取,D4。代码不会经过D2和D3。
你觉得我该怎么做呢?我还没有向你展示D5,…D5操作是最复杂的,因为我必须进行“两次读取”,一次是针对一段数据,然后是201次连续读取,以检索波长数据,如下所示:
myPort.WriteLine("D5")
Incoming = myPort.ReadLine()
Temp = Split(Incoming, ",")
PeakWL = Convert.ToDouble(Temp(2))
For i = 1 To 201
Incoming = myPort.ReadLine()
Temp = Split(Incoming, ",")
nmValue(i) = CDbl(Temp(0))
SpectralValue(i) = CDbl(Temp(1))
Next我会试着自己解决我的问题,但我希望得到一些建议。
https://stackoverflow.com/questions/60367045
复制相似问题