using Bro.Common.Helper;
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Reflection;
|
using static Bro.Common.Helper.EnumHelper;
|
|
namespace Bro.Common.Model
|
{
|
#region DataFrame
|
public interface IModbusDataFrame
|
{
|
ModbusOrder Order { get; set; }
|
|
int Address { get; set; }
|
int Length { get; set; }
|
List<int> OpValue { get; set; }
|
byte[] Frame { get; set; }
|
|
string GetFrameString();
|
}
|
|
public class ModbusDataFrame_Send : IModbusDataFrame
|
{
|
public ModbusOrder Order { get; set; }
|
|
private int address = -1;
|
public int Address
|
{
|
get
|
{
|
return address;
|
}
|
set
|
{
|
if (value != address)
|
{
|
address = value;
|
SetFrame();
|
}
|
}
|
}
|
|
private int length = -1;
|
public int Length
|
{
|
get
|
{
|
return length;
|
}
|
set
|
{
|
if (value != length)
|
{
|
length = value;
|
SetFrame();
|
}
|
}
|
}
|
|
private List<int> sendValue;
|
public List<int> OpValue
|
{
|
get
|
{
|
return sendValue;
|
}
|
set
|
{
|
if (value != sendValue)
|
{
|
sendValue = value;
|
SetFrame();
|
}
|
}
|
}
|
|
public byte[] Frame { get; set; }
|
|
public ModbusDataFrame_Send() { }
|
|
public ModbusDataFrame_Send(ModbusOrder order, int address, int length, List<int> value)
|
{
|
Order = order;
|
Address = address;
|
Length = length;
|
OpValue = value;
|
}
|
|
public void SetFrame(bool enforce = false)
|
{
|
if (enforce || (Address != -1 && Length != -1 && OpValue != null))
|
{
|
FrameAttribue attr = Order.GetType().GetField(Order.ToString()).GetCustomAttribute<FrameAttribue>();
|
if (attr != null)
|
{
|
Frame = attr.GetSendFrame(Address, Length, OpValue);
|
}
|
}
|
}
|
|
public string GetFrameString()
|
{
|
return string.Format("{0}\tAddr:{1}\tLength:{2}\tData:{3}", Order.ToString(), Address, Length, string.Join(",", OpValue ?? new List<int>()));
|
}
|
}
|
|
public class ModbusDataFrame_Receive : IModbusDataFrame
|
{
|
//private int address = -1;
|
public int Address { get; set; }
|
//{
|
// get
|
// {
|
// if (address == -1)
|
// {
|
// byte[] addressBytes = new byte[2];
|
// Array.Copy(Frame, 1, addressBytes, 0, 2);
|
|
// address = addressBytes.BytesToInt();
|
// }
|
|
// return address;
|
// }
|
|
// set
|
// {
|
// //throw new NotImplementedException();
|
// }
|
//}
|
|
private byte[] frame = null;
|
public byte[] Frame
|
{
|
get
|
{
|
return frame;
|
}
|
set
|
{
|
if (value != null)
|
{
|
frame = value;
|
AnalyzeReceivedData();
|
}
|
}
|
}
|
|
//private int length = 0;
|
public int Length { get; set; }
|
//{
|
// get
|
// {
|
// if (length == 0)
|
// {
|
|
// }
|
|
// return length;
|
// }
|
|
// set
|
// {
|
// //throw new NotImplementedException();
|
// }
|
//}
|
|
//private ModbusOrder order = ModbusOrder.Read_Coil;
|
public ModbusOrder Order { get; set; }
|
|
//private List<int> opValue;
|
public List<int> OpValue { get; set; }
|
//{
|
// get
|
// {
|
// if (opValue == -1)
|
// {
|
|
// }
|
|
// return opValue;
|
// }
|
|
// set
|
// {
|
// //throw new NotImplementedException();
|
// }
|
//}
|
|
public ModbusDataFrame_Receive() { }
|
|
public ModbusDataFrame_Receive(byte[] datas)
|
{
|
Frame = datas;
|
}
|
|
public void AnalyzeReceivedData()
|
{
|
Order = (ModbusOrder)Frame[0];
|
FrameAttribue attr = Order.GetType().GetField(Order.ToString()).GetCustomAttribute<FrameAttribue>();
|
if (attr != null)
|
{
|
bool flag = attr.AnalyzeReceiveFrame(Frame, out List<int> valueList, out int addressResult, out int lengthResult);
|
|
if (!flag)
|
{
|
//throw new Common.Helper.UserException("Modbus返回数据解析失败");
|
throw new Exception("Modbus返回数据解析失败");
|
}
|
|
OpValue = valueList;
|
Address = addressResult;
|
Length = lengthResult;
|
}
|
else
|
{
|
//throw new Common.Helper.UserException("Modbus返回数据不在解析范围中");
|
throw new Exception("Modbus返回数据不在解析范围中");
|
}
|
}
|
|
public string GetFrameString()
|
{
|
return string.Format("{0}\tAddr:{1}\tLength:{2}\tData:{3}", Order.ToString(), Address, Length, string.Join(",", OpValue ?? new List<int>()));
|
}
|
}
|
#endregion
|
|
#region Tcp Frame
|
public interface IModbusFrame_TCP
|
{
|
#region MBAP Head
|
byte[] ModbusFlag { get; set; }
|
|
int Head { get; set; }
|
|
int Length { get; set; }
|
|
int UnitNum { get; set; }
|
#endregion
|
|
#region Modbus Body
|
IModbusDataFrame BodyFrame { get; set; }
|
#endregion
|
|
byte[] Frame { get; set; }
|
|
string GetFrameString();
|
}
|
|
public class ModbusFrame_Send_TCP : IModbusFrame_TCP
|
{
|
#region MBAP Head
|
|
public byte[] ModbusFlag { get; set; } = { 0x00, 0x00 };
|
|
private int head = 0;
|
public int Head
|
{
|
get
|
{
|
return head;
|
}
|
set
|
{
|
if (head != value)
|
{
|
head = value;
|
SetFrame();
|
}
|
}
|
}
|
|
private int length = 0;
|
public int Length
|
{
|
get
|
{
|
return length;
|
}
|
set
|
{
|
if (length != value)
|
{
|
length = value;
|
SetFrame();
|
}
|
}
|
}
|
|
private int unitNum = 1;
|
public int UnitNum
|
{
|
get
|
{
|
return unitNum;
|
}
|
set
|
{
|
if (unitNum != value)
|
{
|
unitNum = value;
|
SetFrame();
|
}
|
}
|
}
|
#endregion
|
|
#region Modbus Body
|
private IModbusDataFrame bodyFrame = null;
|
public IModbusDataFrame BodyFrame
|
{
|
get
|
{
|
return bodyFrame;
|
}
|
set
|
{
|
if (bodyFrame != value)
|
{
|
bodyFrame = value;
|
SetFrame();
|
}
|
}
|
}
|
#endregion
|
|
public byte[] Frame { get; set; }
|
|
public void SetFrame()
|
{
|
if (BodyFrame == null || BodyFrame.Frame == null || BodyFrame.Frame.Length == 0)
|
{
|
return;
|
}
|
|
List<byte> all = new List<byte>();
|
|
#region MBAP
|
all.AddRange(Head.IntToBytes());
|
all.AddRange(ModbusFlag);
|
all.AddRange(new byte[] { 0x00, 0x00 }); //预设长度
|
all.AddRange(UnitNum.IntToBytes(1));
|
#endregion
|
|
all.AddRange(BodyFrame.Frame);
|
|
Length = BodyFrame.Frame.Length + 1;
|
|
byte[] lengthBytes = Length.IntToBytes();
|
all[2 + 2 + 0] = lengthBytes[0];
|
all[2 + 2 + 1] = lengthBytes[1];
|
|
Frame = all.ToArray();
|
}
|
|
public ModbusFrame_Send_TCP() { }
|
|
public ModbusFrame_Send_TCP(ModbusOrder _order, int _address, int _length, List<int> valueList, int _headId = 1, int _unitNum = 1)
|
{
|
Head = _headId;
|
UnitNum = _unitNum;
|
|
BodyFrame = new ModbusDataFrame_Send(_order, _address, _length, valueList);
|
}
|
|
public ModbusFrame_Send_TCP(PLCItem item, int _unitNum = 1, int _headId = 1)
|
{
|
ModbusOrder order = ModbusOrder.Read_Coil;
|
|
if (((int)item.PLCOpType & (int)PLCOpType.Read) == (int)PLCOpType.Read)
|
{
|
switch (item.Address[0])
|
{
|
case '0':
|
order = ModbusOrder.Read_Coil;
|
break;
|
case '1':
|
order = ModbusOrder.Read_Input;
|
break;
|
case '3':
|
order = ModbusOrder.Read_InputRegister;
|
break;
|
case '4':
|
order = ModbusOrder.Read_HoldingRegister;
|
break;
|
}
|
}
|
else
|
{
|
switch (item.Address[0])
|
{
|
case '1':
|
if (item.ItemLength > 1)
|
{
|
order = ModbusOrder.Write_MultipleOutputs;
|
}
|
else
|
{
|
order = ModbusOrder.Write_SingleOutput;
|
}
|
break;
|
case '4':
|
if (item.ItemLength > 1)
|
{
|
order = ModbusOrder.Write_MultipleRegister;
|
}
|
else
|
{
|
order = ModbusOrder.Write_SingleRegister;
|
}
|
break;
|
}
|
}
|
|
//int address = Convert.ToInt16(item.ADDRESS.Substring(1), 16);
|
int address = int.Parse(item.Address.Substring(1));
|
|
//address = address - 1; //PLC地址比Modbus地址少一位。例如PLC40001读取Modbus40000
|
|
Head = _headId;
|
UnitNum = _unitNum;
|
|
//List<int> valueList = new List<int>();
|
|
//if (!string.IsNullOrWhiteSpace(item.ItemValues))
|
//{
|
// valueList = item.ItemValues.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList().ConvertAll(s => int.Parse(s)).ToList();
|
//}
|
|
BodyFrame = new ModbusDataFrame_Send(order, address, item.ItemLength, item.ItemValues);
|
}
|
|
public string GetFrameString()
|
{
|
string desc = string.Format("Send\t{0}\r\n", string.Join(" ", Array.ConvertAll(Frame, b => b.ToString("X2"))));
|
desc += string.Format("{0}\r\n", BodyFrame?.GetFrameString());
|
return desc;
|
}
|
}
|
|
public class ModbusFrame_Receive_TCP : IModbusFrame_TCP
|
{
|
private byte[] frame = null;
|
public byte[] Frame
|
{
|
get
|
{
|
return frame;
|
}
|
set
|
{
|
if (value != null)
|
{
|
frame = value;
|
AnalyzeFrame();
|
}
|
}
|
}
|
|
//private int head = 0;
|
public int Head { get; set; }
|
//{
|
// get
|
// {
|
// if (head == 0)
|
// {
|
// byte[] headBytes = new byte[2];
|
// Array.Copy(Frame, 0, headBytes, 0, 2);
|
|
// head = headBytes.BytesToInt();
|
// }
|
|
// return head;
|
// }
|
|
// set
|
// {
|
// //throw new NotImplementedException();
|
// }
|
//}
|
|
//private int length = 0;
|
public int Length { get; set; }
|
//{
|
// get
|
// {
|
// if (length == 0)
|
// {
|
// byte[] lengthBytes = new byte[2];
|
// Array.Copy(Frame, 4, lengthBytes, 0, 2);
|
|
// length = lengthBytes.BytesToInt();
|
// }
|
|
// return length;
|
// }
|
|
// set
|
// {
|
// //throw new NotImplementedException();
|
// }
|
//}
|
|
public byte[] ModbusFlag { get; set; } = { 0x00, 0x00 };
|
|
//private int unitNum = -1;
|
public int UnitNum { get; set; }
|
//{
|
// get
|
// {
|
// if (unitNum == -1)
|
// {
|
// unitNum = Frame[6];
|
// }
|
|
// return unitNum;
|
// }
|
|
// set
|
// {
|
// //throw new NotImplementedException();
|
// }
|
//}
|
|
//private IModbusDataFrame bodyFrame = null;
|
public IModbusDataFrame BodyFrame { get; set; }
|
|
public ModbusFrame_Receive_TCP() { }
|
|
public ModbusFrame_Receive_TCP(byte[] datas)
|
{
|
Frame = datas;
|
}
|
|
public void AnalyzeFrame()
|
{
|
byte[] headBytes = new byte[2];
|
Array.Copy(Frame, 0, headBytes, 0, 2);
|
Head = headBytes.BytesToInt();
|
|
byte[] lengthBytes = new byte[2];
|
Array.Copy(Frame, 4, lengthBytes, 0, 2);
|
Length = lengthBytes.BytesToInt();
|
|
UnitNum = Frame[6];
|
|
BodyFrame = new ModbusDataFrame_Receive(Frame.Skip(2 + 2 + 2 + 1).ToArray());
|
}
|
|
public string GetFrameString()
|
{
|
string desc = string.Format("Rec\t{0}\r\n", string.Join(" ", Array.ConvertAll(Frame, b => b.ToString("X2"))));
|
desc += string.Format("{0}\r\n", BodyFrame?.GetFrameString());
|
return desc;
|
}
|
}
|
#endregion
|
|
#region RTU Frame
|
public interface IModbusFrame_RTU
|
{
|
int UnitNum { get; set; }
|
|
IModbusDataFrame BodyFrame { get; set; }
|
|
byte[] CRCBytes { get; set; }
|
|
byte[] Frame { get; set; }
|
|
string GetFrameString();
|
}
|
|
public class ModbusFrame_Send_RTU : IModbusFrame_RTU
|
{
|
private int unitNum = 1;
|
public int UnitNum
|
{
|
get
|
{
|
return unitNum;
|
}
|
set
|
{
|
if (unitNum != value)
|
{
|
unitNum = value;
|
SetFrame();
|
}
|
}
|
}
|
|
private IModbusDataFrame bodyFrame = null;
|
public IModbusDataFrame BodyFrame
|
{
|
get
|
{
|
return bodyFrame;
|
}
|
set
|
{
|
if (bodyFrame != value)
|
{
|
bodyFrame = value;
|
SetFrame();
|
}
|
}
|
}
|
|
public byte[] CRCBytes { get; set; }
|
|
public byte[] Frame { get; set; }
|
|
public void SetFrame()
|
{
|
if (BodyFrame == null || BodyFrame.Frame == null || BodyFrame.Frame.Length == 0)
|
{
|
return;
|
}
|
|
List<byte> all = new List<byte>();
|
|
all.AddRange(UnitNum.IntToBytes(1));
|
all.AddRange(BodyFrame.Frame);
|
|
byte[] temp = all.ToArray();
|
CRCBytes = CRCHelper.Crc16InBytes(temp, temp.Length);
|
|
all.AddRange(CRCBytes);
|
|
Frame = all.ToArray();
|
}
|
|
public ModbusFrame_Send_RTU() { }
|
|
public ModbusFrame_Send_RTU(ModbusOrder _order, int _address, int _length, List<int> valueList, int _unitNum = 1)
|
{
|
UnitNum = _unitNum;
|
BodyFrame = new ModbusDataFrame_Send(_order, _address, _length, valueList);
|
}
|
|
public string GetFrameString()
|
{
|
string desc = string.Format("Send\t{0}\r\n", string.Join(" ", Array.ConvertAll(Frame, b => b.ToString("X2"))));
|
desc += string.Format("{0}\r\n", BodyFrame?.GetFrameString());
|
return desc;
|
}
|
}
|
|
public class ModbusFrame_Receive_RTU : IModbusFrame_RTU
|
{
|
private byte[] frame = null;
|
public byte[] Frame
|
{
|
get
|
{
|
return frame;
|
}
|
set
|
{
|
if (value != null)
|
{
|
frame = value;
|
AnalyzeFrame();
|
}
|
}
|
}
|
|
public byte[] ModbusFlag { get; set; } = { 0x00, 0x00 };
|
|
public int UnitNum { get; set; }
|
|
public byte[] CRCBytes { get; set; }
|
|
public IModbusDataFrame BodyFrame { get; set; }
|
|
public ModbusFrame_Receive_RTU() { }
|
|
public ModbusFrame_Receive_RTU(byte[] datas)
|
{
|
Frame = datas;
|
}
|
|
public void AnalyzeFrame()
|
{
|
UnitNum = Frame[0];
|
CRCBytes = Frame.Skip(Frame.Length - 2).ToArray();
|
BodyFrame = new ModbusDataFrame_Receive(Frame.Skip(1).Take(Frame.Length - 1 - 2).ToArray());
|
}
|
|
public string GetFrameString()
|
{
|
string desc = string.Format("Rec\t{0}\r\n", string.Join(" ", Array.ConvertAll(Frame, b => b.ToString("X2"))));
|
desc += string.Format("{0}\r\n", BodyFrame?.GetFrameString());
|
return desc;
|
}
|
}
|
#endregion
|
|
public enum ModbusOrder
|
{
|
[FrameAttribue(0x01, true, false, true)]
|
Read_Coil = 0x01,
|
[FrameAttribue(0x02, false, true, true)]
|
Read_Input = 0x02,
|
[FrameAttribue(0x03, false, true, true)]
|
Read_HoldingRegister = 0x03,
|
[FrameAttribue(0x04, false, true, true)]
|
Read_InputRegister = 0x04,
|
[FrameAttribue(0x05, true, false, false)]
|
Write_SingleOutput = 0x05,
|
[FrameAttribue(0x06, false, false, false)]
|
Write_SingleRegister = 0x06,
|
[FrameAttribue(0x0f, true, true, false)]
|
Write_MultipleOutputs = 0x0f,
|
[FrameAttribue(0x10, false, true, false)]
|
Write_MultipleRegister = 0x10,
|
}
|
|
public class FrameAttribue : Attribute
|
{
|
public byte Code { get; set; }
|
public bool IsRead { get; set; }
|
public bool IsMultiple { get; set; }
|
public bool IsCoil { get; set; }
|
|
public FrameAttribue(byte code, bool isCoil, bool isMultiple, bool isRead = true)
|
{
|
Code = code;
|
IsRead = isRead;
|
IsMultiple = isMultiple;
|
IsCoil = isCoil;
|
}
|
|
public byte[] GetSendFrame(int address, int length, List<int> valueList)
|
{
|
List<byte> all = new List<byte>
|
{
|
Code
|
};
|
all.AddRange(address.IntToBytes());
|
|
if (IsRead)
|
{
|
all.AddRange(length.IntToBytes());
|
}
|
else
|
{
|
if (!IsMultiple)
|
{
|
if (IsCoil)
|
{
|
all.AddRange(valueList[0] == 1 ? new byte[] { 0xff, 0x00 } : new byte[] { 0x00, 0x00 });
|
}
|
else
|
{
|
all.AddRange(valueList[0].IntToBytes());
|
}
|
}
|
else
|
{
|
all.AddRange(valueList.Count.IntToBytes(2));//寄存器数量
|
|
if (IsCoil)
|
{
|
int divide = valueList.Count / 8;
|
int remainder = length % 8;
|
if (remainder > 0)
|
{
|
divide++;
|
}
|
all.AddRange(divide.IntToBytes(1)); //字节长度
|
|
for (int i = 0; i < divide; i++)
|
{
|
string s = "";
|
for (int j = 0; j < 8; j++)
|
{
|
int index = j + i * 8;
|
if (valueList.Count > index)
|
{
|
s = valueList[index].ToString() + s;
|
}
|
else
|
{
|
s = "0" + s;
|
}
|
}
|
|
all.Add((byte)Convert.ToInt16(s, 2));
|
}
|
}
|
else
|
{
|
all.Add((byte)(valueList.Count * 2));//字节长度
|
valueList.ForEach(u =>
|
{
|
all.AddRange(u.IntToBytes());
|
});
|
}
|
}
|
}
|
|
return all.ToArray();
|
}
|
|
public bool AnalyzeReceiveFrame(byte[] data, out List<int> opValue, out int address, out int length)
|
{
|
opValue = new List<int>();
|
address = -1;
|
length = 0;
|
|
if (IsRead)
|
{
|
if (IsCoil)
|
{
|
length = data[1];
|
|
for (int i = 0; i < length; i++)
|
{
|
int index = i + 2; //头两位是Code和Length
|
|
if (index > data.Length)
|
{
|
return false;
|
}
|
|
int value8 = data[index];
|
|
for (int j = 0; j < 8; j++)
|
{
|
opValue.Add((value8 >> j) & 0x01);
|
}
|
}
|
}
|
else
|
{
|
length = data[1] / 2;
|
|
for (int i = 0; i < length; i++)
|
{
|
byte[] res = new byte[2];
|
Array.Copy(data, i * 2 + 2, res, 0, 2);
|
|
opValue.Add(res.BytesToInt());
|
}
|
}
|
}
|
else
|
{
|
if (data.Length < 5)
|
{
|
return false;
|
}
|
|
byte[] addbytes = new byte[2];
|
Array.Copy(data, 1, addbytes, 0, 2);
|
|
address = addbytes.BytesToInt();
|
|
if (IsMultiple)
|
{
|
byte[] writeLengthBytes = new byte[2];
|
Array.Copy(data, 3, writeLengthBytes, 0, 2);
|
|
length = writeLengthBytes.BytesToInt();
|
}
|
else
|
{
|
byte[] writeValueBytes = new byte[2];
|
Array.Copy(data, 3, writeValueBytes, 0, 2);
|
|
opValue.Add(writeValueBytes.BytesToInt());
|
}
|
}
|
|
return true;
|
}
|
}
|
|
public class CRCHelper
|
{
|
private static readonly byte[] aucCRCHi = {
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
0x00, 0xC1, 0x81, 0x40
|
};
|
private static readonly byte[] aucCRCLo = {
|
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
|
0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
|
0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
|
0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
|
0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
|
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
|
0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
|
0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
|
0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
|
0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
|
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
|
0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
|
0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
|
0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
|
0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
|
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
|
0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
|
0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
|
0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
|
0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
|
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
|
0x41, 0x81, 0x80, 0x40
|
};
|
/// <summary>
|
/// CRC效验
|
/// </summary>
|
/// <param name="pucFrame">效验数据</param>
|
/// <param name="usLen">数据长度</param>
|
/// <returns>效验结果</returns>
|
public static int Crc16(byte[] pucFrame, int usLen)
|
{
|
int i = 0;
|
byte ucCRCHi = 0xFF;
|
byte ucCRCLo = 0xFF;
|
while (usLen-- > 0)
|
{
|
ushort iIndex = (UInt16)(ucCRCLo ^ pucFrame[i++]);
|
ucCRCLo = (byte)(ucCRCHi ^ aucCRCHi[iIndex]);
|
ucCRCHi = aucCRCLo[iIndex];
|
}
|
return (ucCRCHi << 8 | ucCRCLo);
|
}
|
|
public static byte[] Crc16InBytes(byte[] pucFrame, int usLen)
|
{
|
int i = 0;
|
byte ucCRCHi = 0xFF;
|
byte ucCRCLo = 0xFF;
|
while (usLen-- > 0)
|
{
|
ushort iIndex = (UInt16)(ucCRCLo ^ pucFrame[i++]);
|
ucCRCLo = (byte)(ucCRCHi ^ aucCRCHi[iIndex]);
|
ucCRCHi = aucCRCLo[iIndex];
|
}
|
return new byte[2] { ucCRCLo, ucCRCHi };
|
}
|
}
|
}
|