我对 COM 端口没有太多经验,我正在尝试创建一个具有以下目标的 Windows 服务:
打开列表中的所有 COM 端口名称,例如(“COM1、COM2、COM3、...”)。
打开可用的 COM 端口,并显示无法打开的错误。 打开的 COM 端口应该能够读取数据,因为数据将随机发送到它们。 根据发送数据的COM口,会经过一个开关来决定它的流程。
问题是,当我运行该服务并使用任何打开的 COM 端口时,它仅适用于该端口,之后就无法与任何其他端口一起使用。 也就是说,在假设的场景中,如果只打开COM3和COM4,两者都应该接收数据,但如果我先使用COM3,COM4不会响应,只剩下COM3。我该如何解决这个问题?
这是我的代码。
开始服务-
sapEntities db = new sapEntities();
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
WriteToFile($"Call COM port is started at {DateTime.Now}");
COMDataLog($"Ready at {DateTime.Now}");
StringCollection stringCollection = Properties.Settings.Default.List_COM;
string[] ports = new string[stringCollection.Count];
stringCollection.CopyTo(ports, 0);
foreach (string portName in ports)
{
try
{
SerialPort sp = new SerialPort(portName, 9600, Parity.None, 8, StopBits.One);
sp.Handshake = Handshake.RequestToSend;
sp.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
sp.Open();
WriteToFile($"{portName} is open at {DateTime.Now}");
}
catch (UnauthorizedAccessException uae)
{
WriteToFile($"{portName} Error UnauthorizedAccessException: {uae.Message} at {DateTime.Now}");
}
catch (ArgumentException ae)
{
WriteToFile($"{portName} Error ArgumentException: {ae.Message} at {DateTime.Now}");
}
catch (IOException ioe)
{
WriteToFile($"{portName} Error IOException: {ioe.Message} at {DateTime.Now}");
}
catch (Exception ex)
{
WriteToFile($"{portName} Error: {ex.Message} at {DateTime.Now}");
}
}
}
catch (Exception ex)
{
WriteToFile($"Error: {ex.Message} at {DateTime.Now}");
}
}
接收数据-
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
try
{
SerialPort sp = (SerialPort)sender;
if (sp != null)
{
Thread.Sleep(100);
string data = sp.ReadExisting();
string cPort = sp.PortName;
ProcessData(db, cPort, data);
}
else
{
WriteToFile($"DataReceivedHandler error: SerialPort object is null at {DateTime.Now}");
}
}
catch (Exception ex)
{
WriteToFile($"DataReceivedHandler error: {ex.Message} at {DateTime.Now} ");
}
}
根据发送信息的COM端口进行数据处理(COM端口选项还有很多,我只放了几个,以免代码太混乱)。
private void ProcessData(sapEntities db, string port, string data)
{
var ins_light = new real_light();
switch (port)
{
case "COM1":
WriteToFile($"COM1 Read: {data} at {DateTime.Now}");
COMDataLog($"COM1 Read: {data}");
ins_light = new real_light
{
lgt_date = DateTime.Now,
lgt_data = data,
lgt_ref = 1
};
db.real_light.Add(ins_light);
try
{
db.SaveChanges();
foreach (var entry in b.ChangeTracker.Entries())
{
entry.State = EntityState.Detached;
}
WriteToFile($"COM1 Data stored correctly: {data} at {DateTime.Now}");
}
catch (Exception ex)
{
foreach (var entry in db.ChangeTracker.Entries())
{
entry.State = EntityState.Detached;
}
WriteToFile($"COM1 Error data stored {ex.Message} at {DateTime.Now}");
}
break;
case "COM2":
WriteToFile($"COM2 Read: {data} at {DateTime.Now}");
COMDataLog($"COM2 Read: {data}");
ins_light = new real_light
{
lgt_date = DateTime.Now,
lgt_data = data,
lgt_ref = 2
};
db.real_light.Add(ins_light);
try
{
db.SaveChanges();
foreach (var entry in db.ChangeTracker.Entries())
{
entry.State = EntityState.Detached;
}
WriteToFile($"COM1 Data stored correctly: {data} at {DateTime.Now}");
}
catch (Exception ex)
{
foreach (var entry in db.ChangeTracker.Entries())
{
entry.State = EntityState.Detached;
}
WriteToFile($"COM1 Error data stored {ex.Message} at {DateTime.Now}");
}
break;
default:
WriteToFile($"Unknown port: {port}");
break;
}
}
搜索有关串口的信息,我忘记添加 2 个重要的东西,现在可以了。
1.- 收藏系列列表
private List<SerialPort> serialPorts = new List<SerialPort>();
2.- 为每个 com 端口分配一个 DataReceived
sp.DataReceived += (sender, e) => DataReceivedHandler(sender, e, portName);
因此,完成了编辑。
private List<SerialPort> serialPorts = new List<SerialPort>();
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
WriteToFile($"Call COM port is started at {DateTime.Now}");
COMDataLog($"Ready at {DateTime.Now}");
StringCollection stringCollection = Properties.Settings.Default.List_COM;
string[] ports = new string[stringCollection.Count];
stringCollection.CopyTo(ports, 0);
foreach (string portName in ports)
{
try
{
SerialPort sp = new SerialPort(portName, 9600, Parity.None, 8, StopBits.One);
sp.Handshake = Handshake.RequestToSend;
sp.DataReceived += (sender, e) => DataReceivedHandler(sender, e, portName);
sp.Open();
serialPorts.Add(sp);
WriteToFile($"{portName} is open at {DateTime.Now}");
}
catch (UnauthorizedAccessException uae)
{
WriteToFile($"{portName} Error UnauthorizedAccessException: {uae.Message} at {DateTime.Now}");
}
catch (ArgumentException ae)
{
WriteToFile($"{portName} Error ArgumentException: {ae.Message} at {DateTime.Now}");
}
catch (IOException ioe)
{
WriteToFile($"{portName} Error IOException: {ioe.Message} at {DateTime.Now}");
}
catch (Exception ex)
{
WriteToFile($"{portName} Error: {ex.Message} at {DateTime.Now}");
}
}
}
catch (Exception ex)
{
WriteToFile($"Error: {ex.Message} at {DateTime.Now}");
}
}