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