From a4a95e6cf35312cbedd09fe056789116fc3b00ff Mon Sep 17 00:00:00 2001 From: "GukSang.Jin" Date: Wed, 20 May 2026 11:29:20 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B02026?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Services/IPlcService.cs | 6 +++++- Services/ModbusTcpPlcService.cs | 35 +++++++++++++++++++++++++++++++++ Services/PlcSimulator.cs | 12 +++++++++++ ViewModels/StationViewModel.cs | 6 ++++-- Views/SettingsWindow.xaml.cs | 4 ++-- 5 files changed, 58 insertions(+), 5 deletions(-) diff --git a/Services/IPlcService.cs b/Services/IPlcService.cs index d329a84..7def41d 100644 --- a/Services/IPlcService.cs +++ b/Services/IPlcService.cs @@ -9,14 +9,18 @@ namespace TabletTester2025.Services Task CheckConnectionAsync(); //从 PLC 的指定起始地址,读取 1 个 32 位浮点型(float)数据。 Task ReadFloatAsync(ushort startAddress); - //从 PLC 的指定起始地址,读取 1 个 32 位整型(int)数据。 + //从 PLC 的指定地址,读取 1 个 16 位整型数据。 Task ReadIntAsync(ushort startAddress); + //从 PLC 的指定起始地址,读取 1 个 32 位整型(int)数据。 + Task ReadInt32Async(ushort startAddress); //向 PLC 的指定线圈地址,写入一个布尔值(开关量)。 Task WriteCoilAsync(ushort coilAddress, bool value); //读取 PLC 指定线圈地址的布尔状态,是 WriteCoilAsync 的配套读取方法。 Task ReadCoilAsync(ushort coilAddress); //向 PLC 的指定寄存器地址,写入 1 个 16 位无符号整型(ushort)数据。 Task WriteRegisterAsync(ushort registerAddress, ushort value); + //向 PLC 的指定起始地址,写入 1 个 32 位整型(int)数据。 + Task WriteInt32Async(ushort startAddress, int value); //向 PLC 的指定起始地址,写入 1 个 32 位浮点型(float)数据。 Task WriteFloatAsync(ushort startAddress, float value); //批量读取 PLC 的保持寄存器数据,是工业通信中最高效的批量读取方法。 diff --git a/Services/ModbusTcpPlcService.cs b/Services/ModbusTcpPlcService.cs index 7cede78..af94563 100644 --- a/Services/ModbusTcpPlcService.cs +++ b/Services/ModbusTcpPlcService.cs @@ -105,6 +105,12 @@ namespace TabletTester2025.Services return registers[0]; } + public async Task ReadInt32Async(ushort startAddress) + { + var registers = await ReadHoldingRegistersAsync(startAddress, 2); + return RegistersToInt32(registers[0], registers[1]); + } + public Task WriteCoilAsync(ushort coilAddress, bool value) { return ExecuteAsync(master => master.WriteSingleCoilAsync(_config.SlaveId, coilAddress, value)); @@ -121,6 +127,12 @@ namespace TabletTester2025.Services return ExecuteAsync(master => master.WriteSingleRegisterAsync(_config.SlaveId, registerAddress, value)); } + public Task WriteInt32Async(ushort startAddress, int value) + { + ushort[] registers = Int32ToRegisters(value); + return ExecuteAsync(master => master.WriteMultipleRegistersAsync(_config.SlaveId, startAddress, registers)); + } + public Task WriteFloatAsync(ushort startAddress, float value) { if (!float.IsFinite(value)) @@ -178,6 +190,13 @@ namespace TabletTester2025.Services : WordsToFloat(secondRegister, firstRegister); } + private int RegistersToInt32(ushort firstRegister, ushort secondRegister) + { + return _config.FloatWordOrder == PlcFloatWordOrder.HighWordFirst + ? WordsToInt32(firstRegister, secondRegister) + : WordsToInt32(secondRegister, firstRegister); + } + private static float WordsToFloat(ushort highWord, ushort lowWord) { byte[] bytes = @@ -190,6 +209,11 @@ namespace TabletTester2025.Services return BitConverter.ToSingle(bytes, 0); } + private static int WordsToInt32(ushort highWord, ushort lowWord) + { + return (int)(((uint)highWord << 16) | lowWord); + } + private ushort[] FloatToRegisters(float value) { byte[] bytes = BitConverter.GetBytes(value); @@ -201,6 +225,17 @@ namespace TabletTester2025.Services : new[] { lowWord, highWord }; } + private ushort[] Int32ToRegisters(int value) + { + uint raw = unchecked((uint)value); + ushort highWord = (ushort)(raw >> 16); + ushort lowWord = (ushort)(raw & 0xFFFF); + + return _config.FloatWordOrder == PlcFloatWordOrder.HighWordFirst + ? new[] { highWord, lowWord } + : new[] { lowWord, highWord }; + } + private void CloseConnection() { try { _master?.Dispose(); } catch { } diff --git a/Services/PlcSimulator.cs b/Services/PlcSimulator.cs index 467736b..cf7b0ae 100644 --- a/Services/PlcSimulator.cs +++ b/Services/PlcSimulator.cs @@ -45,6 +45,16 @@ namespace TabletTester2025.Services return Task.FromResult(value); } + public Task ReadInt32Async(ushort startAddress) + { + int value = startAddress switch + { + 400 => 50, // 硬度破损判定 + _ => _rand.Next(0, 1000) + }; + return Task.FromResult(value); + } + public Task WriteCoilAsync(ushort coilAddress, bool value) => Task.CompletedTask; public Task ReadCoilAsync(ushort coilAddress) @@ -55,6 +65,8 @@ namespace TabletTester2025.Services public Task WriteRegisterAsync(ushort registerAddress, ushort value) => Task.CompletedTask; + public Task WriteInt32Async(ushort startAddress, int value) => Task.CompletedTask; + public Task WriteFloatAsync(ushort startAddress, float value) => Task.CompletedTask; public Task ReadHoldingRegistersAsync(ushort startAddress, ushort count) diff --git a/ViewModels/StationViewModel.cs b/ViewModels/StationViewModel.cs index 6f5bdc3..f71d4a2 100644 --- a/ViewModels/StationViewModel.cs +++ b/ViewModels/StationViewModel.cs @@ -409,12 +409,14 @@ namespace TabletTester2025.ViewModels public async Task UpdateRealTimeData() { - if (!IsAnyTestRunning()) return; try { + await LoadMediumTemperatureAsync(); + + if (!IsAnyTestRunning()) return; + if (_isDisintegrationRunning) { - DisintegrationTemp = await _plc.ReadFloatAsync(_plcConfig.DisintegrationTemp); IsBasketMovingUp = await _plc.ReadCoilAsync(_plcConfig.DisintegrationMovingUpCoil); for (int i = 0; i < _plcConfig.DisintegrationCompleteCoils.Length; i++) { diff --git a/Views/SettingsWindow.xaml.cs b/Views/SettingsWindow.xaml.cs index 2fd513d..3a84003 100644 --- a/Views/SettingsWindow.xaml.cs +++ b/Views/SettingsWindow.xaml.cs @@ -210,7 +210,7 @@ namespace TabletTester2025 try { - int value = await App.PlcService.ReadIntAsync(registerAddress); + int value = await App.PlcService.ReadInt32Async(registerAddress); if (value >= 0) HardnessDamageThresholdBox.Text = value.ToString(); } @@ -226,7 +226,7 @@ namespace TabletTester2025 if (registerAddress == 0) throw new InvalidOperationException("硬度破损判定PLC寄存器地址未配置。"); - await App.PlcService.WriteRegisterAsync(registerAddress, (ushort)Math.Clamp(value, 0, ushort.MaxValue)); + await App.PlcService.WriteInt32Async(registerAddress, value); } private static ushort ResolveHardnessDamageThresholdRegister()