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