using System; using WIDESEAWCS_S7Simulator.Core.Interfaces; namespace WIDESEAWCS_S7Simulator.Core.Memory { /// /// T区(定时器区/Timer)实现 /// 用于模拟西门子S7 PLC的定时器区域 /// 每个定时器占用2字节,存储定时器的时间值(毫秒) /// public class TRegion : MemoryRegion, IMemoryRegion { /// /// 区域类型 /// public override string RegionType => "T"; /// /// 每个定时器占用的字节数(S7定时器为2字节) /// private const int TimerSize = 2; /// /// 定时器数量 /// public int TimerCount => Size / TimerSize; /// /// 构造函数 /// /// 定时器数量 /// 当timerCount小于或等于0时抛出 /// 当timerCount * TimerSize超出int范围时抛出 public TRegion(int timerCount) : base(timerCount * TimerSize) { if (timerCount <= 0) throw new ArgumentOutOfRangeException(nameof(timerCount), "定时器数量必须大于0"); // 验证没有溢出 if (timerCount > Size / TimerSize) throw new OverflowException($"定时器数量{timerCount}过大,超出内存限制"); } /// /// 读取定时器值 /// /// 定时器号(从1开始) /// 定时器值(毫秒) /// 当timerNumber为0或超出定时器数量时抛出 public ushort ReadTimer(ushort timerNumber) { if (timerNumber == 0) throw new ArgumentOutOfRangeException(nameof(timerNumber), "定时器号必须大于0(从1开始)"); if (timerNumber > TimerCount) throw new ArgumentOutOfRangeException(nameof(timerNumber), $"定时器号{timerNumber}超出范围,当前定时器总数为{TimerCount}"); ushort offset = (ushort)((timerNumber - 1) * TimerSize); var data = Read(offset, TimerSize); return (ushort)((data[0] << 8) | data[1]); } /// /// 写入定时器值 /// /// 定时器号(从1开始) /// 定时器值(毫秒) /// 当timerNumber为0或超出定时器数量时抛出 public void WriteTimer(ushort timerNumber, ushort value) { if (timerNumber == 0) throw new ArgumentOutOfRangeException(nameof(timerNumber), "定时器号必须大于0(从1开始)"); if (timerNumber > TimerCount) throw new ArgumentOutOfRangeException(nameof(timerNumber), $"定时器号{timerNumber}超出范围,当前定时器总数为{TimerCount}"); ushort offset = (ushort)((timerNumber - 1) * TimerSize); var data = new byte[] { (byte)(value >> 8), (byte)(value & 0xFF) }; Write(offset, data); } } }