@@ -61,7 +61,7 @@ namespace ModbusDemo | |||||
.UseSqlServer(configuration.GetConnectionString("ConnStr")) | .UseSqlServer(configuration.GetConnectionString("ConnStr")) | ||||
.Options; | .Options; | ||||
// 3. 注册 DbContext(作用域生命周期) | |||||
// 3. 注册 DbContext | |||||
containerRegistry.Register<ModbusDbContext>(() => new ModbusDbContext(options)); | containerRegistry.Register<ModbusDbContext>(() => new ModbusDbContext(options)); | ||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -11,7 +11,7 @@ namespace ModbusDemo.Device | |||||
public bool[] ReadCoil(byte slaveAddress, ushort startAddress, ushort numberOfPoints); | public bool[] ReadCoil(byte slaveAddress, ushort startAddress, ushort numberOfPoints); | ||||
public void WriteCoil(byte slaveAddress, ushort startAddress, bool[] data); | |||||
public bool WriteCoil(byte slaveAddress, ushort startAddress, bool[] data); | |||||
public ushort[] ReadRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints); | public ushort[] ReadRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints); | ||||
@@ -16,7 +16,7 @@ namespace ModbusDemo.Device | |||||
private SerialPort _serialPort; | private SerialPort _serialPort; | ||||
//用于操作数据库 | //用于操作数据库 | ||||
private ModbusDbContext _modbusDbContext; | private ModbusDbContext _modbusDbContext; | ||||
public ModbusRTU(SerialPort serialPort,ModbusDbContext modbusDbContext) | |||||
public ModbusRTU(SerialPort serialPort, ModbusDbContext modbusDbContext) | |||||
{ | { | ||||
_serialPort = serialPort; | _serialPort = serialPort; | ||||
_modbusDbContext = modbusDbContext; | _modbusDbContext = modbusDbContext; | ||||
@@ -30,10 +30,12 @@ namespace ModbusDemo.Device | |||||
/// <returns></returns> | /// <returns></returns> | ||||
public bool[] ReadCoil(byte slaveAddress, ushort startAddress, ushort numberOfPoints) | public bool[] ReadCoil(byte slaveAddress, ushort startAddress, ushort numberOfPoints) | ||||
{ | { | ||||
bool[] resultValue = null; | |||||
if (!_serialPort.IsOpen) | if (!_serialPort.IsOpen) | ||||
{ | { | ||||
MessageBox.Show("串口没有链接,请先链接"); | MessageBox.Show("串口没有链接,请先链接"); | ||||
return null; | |||||
return resultValue; | |||||
} | } | ||||
List<byte> sendByteList = new List<byte>(); | List<byte> sendByteList = new List<byte>(); | ||||
//设置从站地址 | //设置从站地址 | ||||
@@ -51,23 +53,44 @@ namespace ModbusDemo.Device | |||||
byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length); | byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length); | ||||
sendByteList.Add(resultCRC[0]); | sendByteList.Add(resultCRC[0]); | ||||
sendByteList.Add(resultCRC[1]); | sendByteList.Add(resultCRC[1]); | ||||
byte[] sendByte = sendByteList.ToArray(); | byte[] sendByte = sendByteList.ToArray(); | ||||
if (_serialPort.IsOpen) | |||||
int maxRetries = 3; // 最大重试次数 | |||||
int attempt = 0; | |||||
while (attempt < maxRetries) | |||||
{ | { | ||||
// 清空接收缓冲区(避免残留数据干扰) | |||||
_serialPort.DiscardInBuffer(); | |||||
try | |||||
{ | |||||
// 清空接收缓冲区(避免残留数据干扰) | |||||
_serialPort.DiscardInBuffer(); | |||||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||||
Thread.Sleep(300); | |||||
byte[] response = new byte[_serialPort.BytesToRead]; | |||||
_serialPort.Read(response, 0, _serialPort.BytesToRead); | |||||
if (response[0] == 0x00) | |||||
{ | |||||
continue; | |||||
} | |||||
resultValue = ParseCoilresponse(sendByte, response, numberOfPoints); | |||||
return resultValue; | |||||
} | |||||
catch (Exception) | |||||
{ | |||||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||||
Thread.Sleep(300); | |||||
byte[] response = new byte[_serialPort.BytesToRead]; | |||||
_serialPort.Read(response, 0, _serialPort.BytesToRead); | |||||
attempt++; | |||||
} | |||||
return ParseCoilresponse(sendByte, response, numberOfPoints); | |||||
} | } | ||||
return null; | |||||
//将操作失败的指令,插入数据库 | |||||
string RequestStr = ByteArrayToString(sendByte); | |||||
ModbusLog m = new ModbusLog(); | |||||
m.OperationType = "读线圈"; | |||||
m.ResponseData = ""; | |||||
m.RequestData = RequestStr; | |||||
_modbusDbContext.Add(m); | |||||
_modbusDbContext.SaveChanges(); | |||||
return resultValue; | |||||
} | } | ||||
@@ -78,20 +101,23 @@ namespace ModbusDemo.Device | |||||
string responseStr = ByteArrayToString(response); | string responseStr = ByteArrayToString(response); | ||||
ModbusLog m = new ModbusLog(); | ModbusLog m = new ModbusLog(); | ||||
m.OperationType = "读线圈"; | m.OperationType = "读线圈"; | ||||
m.ResponseData = responseStr; | |||||
m.ResponseData = RequestStr; | |||||
m.RequestData = responseStr; | m.RequestData = responseStr; | ||||
_modbusDbContext.Add(m); | _modbusDbContext.Add(m); | ||||
_modbusDbContext.SaveChanges(); | _modbusDbContext.SaveChanges(); | ||||
//判断发送回来的数据是否正确 | //判断发送回来的数据是否正确 | ||||
CheckData.CheckResponse(response); | |||||
if (!CRCUitl.ValidateCRC(response)) | |||||
if(CheckData.CheckResponse(response)) | |||||
{ | { | ||||
MessageBox.Show("0x14:CRC校验错误"); | |||||
return null; | |||||
if (!CRCUitl.ValidateCRC(response)) | |||||
{ | |||||
MessageBox.Show("0x14:CRC校验错误"); | |||||
return null; | |||||
} | |||||
} | } | ||||
List<byte> responseList = new List<byte>(response); | List<byte> responseList = new List<byte>(response); | ||||
//移除前两位 | //移除前两位 | ||||
responseList.RemoveRange(0, 3); | responseList.RemoveRange(0, 3); | ||||
@@ -129,8 +155,13 @@ namespace ModbusDemo.Device | |||||
/// <param name="slaveAddress">从站地址</param> | /// <param name="slaveAddress">从站地址</param> | ||||
/// <param name="startAddress">起始地址</param> | /// <param name="startAddress">起始地址</param> | ||||
/// <param name="data">写入的数据</param> | /// <param name="data">写入的数据</param> | ||||
public void WriteCoil(byte slaveAddress, ushort startAddress, bool[] data) | |||||
public bool WriteCoil(byte slaveAddress, ushort startAddress, bool[] data) | |||||
{ | { | ||||
if (!_serialPort.IsOpen) | |||||
{ | |||||
MessageBox.Show("串口没有链接,请先链接"); | |||||
return false; | |||||
} | |||||
List<byte> sendByteList = new List<byte>(); | List<byte> sendByteList = new List<byte>(); | ||||
//设置从站地址 | //设置从站地址 | ||||
sendByteList.Add(slaveAddress); | sendByteList.Add(slaveAddress); | ||||
@@ -167,41 +198,56 @@ namespace ModbusDemo.Device | |||||
byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length); | byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length); | ||||
sendByteList.Add(resultCRC[0]); | sendByteList.Add(resultCRC[0]); | ||||
sendByteList.Add(resultCRC[1]); | sendByteList.Add(resultCRC[1]); | ||||
byte[] sendByte = sendByteList.ToArray(); | byte[] sendByte = sendByteList.ToArray(); | ||||
if (_serialPort.IsOpen) | |||||
int maxRetries = 3; // 最大重试次数 | |||||
int attempt = 0; | |||||
byte[] response = null; | |||||
while (attempt < maxRetries) | |||||
{ | { | ||||
// 清空接收缓冲区(避免残留数据干扰) | |||||
_serialPort.DiscardInBuffer(); | |||||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||||
Thread.Sleep(300); | |||||
byte[] response = new byte[_serialPort.BytesToRead]; | |||||
_serialPort.Read(response, 0, _serialPort.BytesToRead); | |||||
try | |||||
{ | |||||
// 清空接收缓冲区(避免残留数据干扰) | |||||
_serialPort.DiscardInBuffer(); | |||||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||||
Thread.Sleep(300); | |||||
response = new byte[_serialPort.BytesToRead]; | |||||
_serialPort.Read(response, 0, _serialPort.BytesToRead); | |||||
if (response[0] != 0x00) | |||||
{ | |||||
break; | |||||
} | |||||
//将操作的指令,插入数据库 | |||||
string RequestStr = ByteArrayToString(sendByte); | |||||
string responseStr = ByteArrayToString(response); | |||||
ModbusLog m = new ModbusLog(); | |||||
m.OperationType = "写线圈"; | |||||
m.ResponseData = responseStr; | |||||
m.RequestData = responseStr; | |||||
_modbusDbContext.Add(m); | |||||
_modbusDbContext.SaveChanges(); | |||||
} | |||||
catch (Exception) | |||||
{ | |||||
//判断发送回来的数据是否正确 | |||||
CheckData.CheckResponse(response); | |||||
attempt++; | |||||
} | |||||
} | |||||
//将操作的指令,插入数据库 | |||||
string RequestStr = ByteArrayToString(sendByte); | |||||
string responseStr = ByteArrayToString(response); | |||||
ModbusLog m = new ModbusLog(); | |||||
m.OperationType = "写线圈"; | |||||
m.ResponseData = responseStr; | |||||
m.RequestData = RequestStr; | |||||
_modbusDbContext.Add(m); | |||||
_modbusDbContext.SaveChanges(); | |||||
//判断发送回来的数据是否正确 | |||||
if (CheckData.CheckResponse(response)) | |||||
{ | |||||
if (!CRCUitl.ValidateCRC(response)) | if (!CRCUitl.ValidateCRC(response)) | ||||
{ | { | ||||
MessageBox.Show("0x14:CRC校验错误"); | MessageBox.Show("0x14:CRC校验错误"); | ||||
return false; | |||||
} | } | ||||
} | } | ||||
return true; | |||||
} | } | ||||
public ushort[] ReadRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints) | public ushort[] ReadRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints) | ||||
@@ -10,7 +10,7 @@ namespace ModbusDemo.Uitls | |||||
public static class CheckData | public static class CheckData | ||||
{ | { | ||||
public static void CheckResponse(byte[] response) | |||||
public static bool CheckResponse(byte[] response) | |||||
{ | { | ||||
// 检查数组长度是否足够 | // 检查数组长度是否足够 | ||||
if (response.Length > 1) | if (response.Length > 1) | ||||
@@ -24,10 +24,17 @@ namespace ModbusDemo.Uitls | |||||
if (highNibble == 8) | if (highNibble == 8) | ||||
{ | { | ||||
MessageBox.Show($"数据错误:错误码为:0x{response[2]:X2}"); | MessageBox.Show($"数据错误:错误码为:0x{response[2]:X2}"); | ||||
return; | |||||
} | } | ||||
return false; | |||||
} | } | ||||
if(response.Length == 0) | |||||
{ | |||||
MessageBox.Show("返回数据为空","error",MessageBoxButton.OK,MessageBoxImage.Error); | |||||
return false; | |||||
} | |||||
return true; | |||||
} | } | ||||
} | } | ||||
@@ -151,16 +151,16 @@ | |||||
<DataGrid ItemsSource="{Binding ModbusLogList}" AutoGenerateColumns="False" IsReadOnly="True" ColumnWidth="*"> | <DataGrid ItemsSource="{Binding ModbusLogList}" AutoGenerateColumns="False" IsReadOnly="True" ColumnWidth="*"> | ||||
<DataGrid.Columns> | <DataGrid.Columns> | ||||
<!-- 操作类型列 --> | <!-- 操作类型列 --> | ||||
<DataGridTextColumn Header="操作类型" Binding="{Binding OperationType}" Width="100" /> | |||||
<DataGridTextColumn Width="100" Header="操作类型" Binding="{Binding OperationType}" /> | |||||
<!-- 请求数据列 --> | <!-- 请求数据列 --> | ||||
<DataGridTextColumn Header="请求数据" Binding="{Binding RequestData}" /> | |||||
<DataGridTextColumn Header="请求数据" Binding="{Binding RequestData}" /> | |||||
<!-- 响应数据列 --> | <!-- 响应数据列 --> | ||||
<DataGridTextColumn Header="响应数据" Binding="{Binding ResponseData}" /> | <DataGridTextColumn Header="响应数据" Binding="{Binding ResponseData}" /> | ||||
<!-- 操作时间列 --> | <!-- 操作时间列 --> | ||||
<DataGridTextColumn Header="操作时间" Binding="{Binding Time, StringFormat='yyyy-MM-dd HH:mm:ss'}" Width="200"/> | |||||
<DataGridTextColumn Width="200" Header="操作时间" Binding="{Binding Time, StringFormat='yyyy-MM-dd HH:mm:ss'}" /> | |||||
</DataGrid.Columns> | </DataGrid.Columns> | ||||
</DataGrid> | </DataGrid> | ||||
</Grid> | </Grid> | ||||
@@ -55,6 +55,7 @@ | |||||
Height="30" | Height="30" | ||||
Margin="10,0,0,5" | Margin="10,0,0,5" | ||||
HorizontalAlignment="Left" | HorizontalAlignment="Left" | ||||
materialDesign:HintAssist.Hint="COM1" | |||||
SelectedItem="{Binding PortName}"> | SelectedItem="{Binding PortName}"> | ||||
<ComboBoxItem Content="COM1" /> | <ComboBoxItem Content="COM1" /> | ||||
<ComboBoxItem Content="COM2" /> | <ComboBoxItem Content="COM2" /> | ||||
@@ -71,6 +72,7 @@ | |||||
Height="30" | Height="30" | ||||
Margin="10,0,0,5" | Margin="10,0,0,5" | ||||
HorizontalAlignment="Left" | HorizontalAlignment="Left" | ||||
materialDesign:HintAssist.Hint="19200" | |||||
SelectedItem="{Binding BaudRate}"> | SelectedItem="{Binding BaudRate}"> | ||||
<ComboBoxItem Content="4800" /> | <ComboBoxItem Content="4800" /> | ||||
<ComboBoxItem Content="9600" /> | <ComboBoxItem Content="9600" /> | ||||
@@ -118,6 +120,7 @@ | |||||
Height="30" | Height="30" | ||||
Margin="10,0,0,5" | Margin="10,0,0,5" | ||||
HorizontalAlignment="Left" | HorizontalAlignment="Left" | ||||
materialDesign:HintAssist.Hint="8" | |||||
SelectedItem="{Binding DataBits}"> | SelectedItem="{Binding DataBits}"> | ||||
<ComboBoxItem Content="7"> | <ComboBoxItem Content="7"> | ||||
</ComboBoxItem> | </ComboBoxItem> | ||||
@@ -140,7 +143,7 @@ | |||||
Height="30" | Height="30" | ||||
materialDesign:ButtonAssist.CornerRadius="15" | materialDesign:ButtonAssist.CornerRadius="15" | ||||
Style="{StaticResource MaterialDesignRaisedDarkButton}" | Style="{StaticResource MaterialDesignRaisedDarkButton}" | ||||
Content="链接" | |||||
Content="连接" | |||||
Command="{Binding ConnectionCmm}"> | Command="{Binding ConnectionCmm}"> | ||||
</Button> | </Button> | ||||
<Button | <Button | ||||
@@ -150,7 +153,7 @@ | |||||
materialDesign:ButtonAssist.CornerRadius="15" | materialDesign:ButtonAssist.CornerRadius="15" | ||||
Style="{StaticResource MaterialDesignRaisedDarkButton}" | Style="{StaticResource MaterialDesignRaisedDarkButton}" | ||||
Content="断开" | Content="断开" | ||||
Command="{Binding ConnectionCmm}"> | |||||
Command="{Binding DisConnectionCmm}"> | |||||
</Button> | </Button> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
@@ -170,47 +170,83 @@ namespace ModbusDemo.VIewModel | |||||
/// </summary> | /// </summary> | ||||
private void ReadCoil() | private void ReadCoil() | ||||
{ | { | ||||
try | |||||
if (!byte.TryParse(SlaveAddress, out byte slaveAddressValue)) | |||||
{ | { | ||||
bool[] result = _modbusRTU.ReadCoil(byte.Parse(SlaveAddress), | |||||
ushort.Parse(StartAddress), | |||||
ushort.Parse(NumberOfPoints)); | |||||
if (result != null) | |||||
{ | |||||
string temp = ""; | |||||
foreach (var item in result) | |||||
{ | |||||
temp += item; | |||||
temp += " "; | |||||
} | |||||
ReadResult = temp; | |||||
} | |||||
MessageBox.Show("SlaveAddress 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); | |||||
return; | |||||
} | } | ||||
catch (Exception) | |||||
if (!ushort.TryParse(StartAddress, out ushort startAddressValue)) | |||||
{ | { | ||||
MessageBox.Show("StartAddress 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); | |||||
return; | |||||
} | |||||
MessageBox.Show("参数配置错误"); | |||||
if (!ushort.TryParse(NumberOfPoints, out ushort numberOfPointsValue)) | |||||
{ | |||||
MessageBox.Show("NumberOfPoints 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); | |||||
return; | |||||
} | } | ||||
//使用子线程,防止ui线程卡顿 | |||||
Task.Run(() => | |||||
{ | |||||
bool[] result = _modbusRTU.ReadCoil(slaveAddressValue, startAddressValue, numberOfPointsValue); | |||||
if (result == null) | |||||
{ | |||||
MessageBox.Show("读取失败", "error", MessageBoxButton.OK, MessageBoxImage.Error); | |||||
return; | |||||
} | |||||
string temp = ""; | |||||
foreach (var item in result) | |||||
{ | |||||
temp += item; | |||||
temp += " "; | |||||
} | |||||
ReadResult = temp; | |||||
MessageBox.Show("读取成功"); | |||||
ModbusLogList = GetOperateCoil(); | |||||
}); | |||||
} | } | ||||
private void WriteCoil() | private void WriteCoil() | ||||
{ | { | ||||
if (!byte.TryParse(WriteSlaveAddress, out byte writeSlaveAddressValue)) | |||||
{ | |||||
MessageBox.Show("WriteSlaveAddress 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); | |||||
return; | |||||
} | |||||
if (!ushort.TryParse(WriteStartAddress, out ushort WriteStartAddressValue)) | |||||
{ | |||||
MessageBox.Show("WriteStartAddress 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); | |||||
return; | |||||
} | |||||
if (string.IsNullOrEmpty(WriteData)) | |||||
{ | |||||
MessageBox.Show("WriteData 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); | |||||
return; | |||||
} | |||||
//去除字符串中的空格 | //去除字符串中的空格 | ||||
WriteData = WriteData.Replace(" ", ""); | WriteData = WriteData.Replace(" ", ""); | ||||
//转换为布尔数组 | //转换为布尔数组 | ||||
bool[] data = WriteData.Select(m => m == '1').ToArray(); | bool[] data = WriteData.Select(m => m == '1').ToArray(); | ||||
try | |||||
{ | |||||
_modbusRTU.WriteCoil(byte.Parse(WriteSlaveAddress), | |||||
ushort.Parse(WriteStartAddress), | |||||
data); | |||||
} | |||||
catch (Exception) | |||||
//使用子线程执行,避免ui线程卡顿 | |||||
Task.Run(() => | |||||
{ | { | ||||
MessageBox.Show("信息配置错误"); | |||||
} | |||||
bool boo= _modbusRTU.WriteCoil(writeSlaveAddressValue, WriteStartAddressValue, data); | |||||
if (boo) | |||||
{ | |||||
MessageBox.Show("写入成功"); | |||||
} | |||||
ModbusLogList = GetOperateCoil(); | |||||
}); | |||||
} | } | ||||
@@ -220,11 +256,11 @@ namespace ModbusDemo.VIewModel | |||||
/// <returns></returns> | /// <returns></returns> | ||||
private List<ModbusLog> GetOperateCoil() | private List<ModbusLog> GetOperateCoil() | ||||
{ | { | ||||
return _modbusDbContext.ModbusLog | |||||
.Where(log => log.OperationType == "读线圈" || log.OperationType == "写线圈") | |||||
.OrderByDescending(log => log.Time) // 按时间倒序,最新的在前 | |||||
.Take(20) // 只取前20条记录 | |||||
.ToList(); // 执行查询 | |||||
return _modbusDbContext.ModbusLog | |||||
.Where(log => log.OperationType == "读线圈" || log.OperationType == "写线圈") | |||||
.OrderByDescending(log => log.Time) // 按时间倒序,最新的在前 | |||||
.Take(20) // 只取前20条记录 | |||||
.ToList(); // 执行查询 | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -110,6 +110,7 @@ namespace ModbusDemo.VIewModel | |||||
if (_serialPort.IsOpen) | if (_serialPort.IsOpen) | ||||
{ | { | ||||
_serialPort.Close(); | _serialPort.Close(); | ||||
MessageBox.Show("连接已经断开"); | |||||
} | } | ||||
} | } | ||||
@@ -118,18 +119,21 @@ namespace ModbusDemo.VIewModel | |||||
/// </summary> | /// </summary> | ||||
private void Connection() | private void Connection() | ||||
{ | { | ||||
//todo,做数据的判空处理 | |||||
//TODO,做数据的判空处理 | |||||
if (!_serialPort.IsOpen) | if (!_serialPort.IsOpen) | ||||
{ | { | ||||
_serialPort.PortName = GetComboBoxItemValue(this.PortName); | |||||
_serialPort.BaudRate = int.Parse(GetComboBoxItemValue(this.BaudRate)); | |||||
_serialPort.Parity = this.Parity; | |||||
_serialPort.StopBits = this.StopBits; | |||||
_serialPort.DataBits = int.Parse(GetComboBoxItemValue(this.DataBits)); | |||||
//读取超时时间 | |||||
_serialPort.ReadTimeout = 500; | |||||
//写入超时时间 | |||||
_serialPort.WriteTimeout = 500; | |||||
try | try | ||||
{ | { | ||||
_serialPort.PortName = GetComboBoxItemValue(this.PortName); | |||||
_serialPort.BaudRate = int.Parse(GetComboBoxItemValue(this.BaudRate)); | |||||
_serialPort.Parity = this.Parity; | |||||
_serialPort.StopBits = this.StopBits; | |||||
_serialPort.DataBits = int.Parse(GetComboBoxItemValue(this.DataBits)); | |||||
_serialPort.Open(); | _serialPort.Open(); | ||||
MessageBox.Show("串口链接成功"); | MessageBox.Show("串口链接成功"); | ||||
_regionManager.Regions["ModbusRegion"].RequestNavigate("CoilUC"); | _regionManager.Regions["ModbusRegion"].RequestNavigate("CoilUC"); | ||||
@@ -138,7 +142,7 @@ namespace ModbusDemo.VIewModel | |||||
catch (Exception) | catch (Exception) | ||||
{ | { | ||||
MessageBox.Show("串口已经链接,请先断开链接在尝试"); | |||||
MessageBox.Show("串口已经链接,请先断开链接在尝试","warning",MessageBoxButton.OK,MessageBoxImage.Warning); | |||||
} | } | ||||
} | } | ||||