using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HslCommunication.Serial
{
///
/// 用于CRC16验证的类,提供了标准的验证方法
///
///
/// 本类提供了几个静态的方法,用来进行CRC16码的计算和验证的,多项式码可以自己指定配置,但是预置的寄存器为0xFF 0xFF
///
///
/// 先演示如何校验一串数据的CRC码
///
/// 然后下面是如何生成你自己的CRC校验码
///
///
public class SoftCRC16
{
///
/// 来校验对应的接收数据的CRC校验码,默认多项式码为0xA001
///
/// 需要校验的数据,带CRC校验码
/// 返回校验成功与否
public static bool CheckCRC16(byte[] value )
{
return CheckCRC16( value, 0xA0, 0x01);
}
///
/// 指定多项式码来校验对应的接收数据的CRC校验码
///
/// 需要校验的数据,带CRC校验码
/// 多项式码高位
/// 多项式码低位
/// 返回校验成功与否
public static bool CheckCRC16(byte[] value, byte CH, byte CL)
{
if (value == null) return false;
if (value.Length < 2) return false;
int length = value.Length;
byte[] buf = new byte[length - 2];
Array.Copy(value, 0, buf, 0, buf.Length);
byte[] CRCbuf = CRC16(buf, CH, CL);
if (CRCbuf[length - 2] == value[length - 2] &&
CRCbuf[length - 1] == value[length - 1])
{
return true;
}
return false;
}
///
/// 获取对应的数据的CRC校验码,默认多项式码为0xA001
///
/// 需要校验的数据,不包含CRC字节
/// 返回带CRC校验码的字节数组,可用于串口发送
public static byte[] CRC16(byte[] value )
{
return CRC16( value, 0xA0, 0x01);
}
///
/// 通过指定多项式码来获取对应的数据的CRC校验码
///
/// 需要校验的数据,不包含CRC字节
/// 多项式码地位
/// 多项式码高位
/// 返回带CRC校验码的字节数组,可用于串口发送
public static byte[] CRC16(byte[] value, byte CH, byte CL)
{
byte[] buf = new byte[value.Length + 2];
value.CopyTo(buf, 0);
byte CRC16Lo;
byte CRC16Hi; // CRC寄存器
byte SaveHi;
byte SaveLo;
byte[] tmpData;
int Flag;
// 预置寄存器
CRC16Lo = 0xFF;
CRC16Hi = 0xFF;
tmpData = value;
for (int i = 0; i < tmpData.Length; i++)
{
CRC16Lo = (byte)(CRC16Lo ^ tmpData[i]); // 每一个数据与CRC寄存器低位进行异或,结果返回CRC寄存器
for (Flag = 0; Flag <= 7; Flag++)
{
SaveHi = CRC16Hi;
SaveLo = CRC16Lo;
CRC16Hi = (byte)(CRC16Hi >> 1); // 高位右移一位
CRC16Lo = (byte)(CRC16Lo >> 1); // 低位右移一位
if ((SaveHi & 0x01) == 0x01) // 如果高位字节最后一位为1
{
// 则低位字节右移后前面补1
CRC16Lo = (byte)(CRC16Lo | 0x80);
}
// 否则自动补0
// 如果最低位为1,则将CRC寄存器与预设的固定值进行异或运算
if ((SaveLo & 0x01) == 0x01)
{
CRC16Hi = (byte)(CRC16Hi ^ CH);
CRC16Lo = (byte)(CRC16Lo ^ CL);
}
}
}
buf[buf.Length - 2] = CRC16Lo;
buf[buf.Length - 1] = CRC16Hi;
// 返回最终带有CRC校验码结尾的信息
return buf;
}
}
}