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