C# CRC16数据校验支持ModelBus和XMODEM校验模式

C# CRC16数据校验支持ModelBus和XMODEM校验模式

最近在研究C# CRC数据校验规则,之前用过ModelBus模式,但是这次的现场用到的是XMODEM模式,写一篇文章记录实现细节,方便后期快速开发!

using System;
using System.Collections.Generic;

namespace Common
{
    /// <summary>
    /// CRC16 帮助类
    /// </summary>
    public class CRC16Helper
    {
        /// <summary>
        /// CRC ModelBus校验
        /// </summary>
        /// <param name="data">校验数据</param>
        /// <returns>高低8位</returns>
        public static string CRCModelBus(string data)
        {
            string[] datas = data.Split(' ');
            List<byte> bytedata = new List<byte>();

            foreach (string str in datas)
            {
                bytedata.Add(byte.Parse(str, System.Globalization.NumberStyles.AllowHexSpecifier));
            }
            byte[] crcbuf = bytedata.ToArray();
            //计算并填写CRC校验码
            int crc = 0xffff;
            int len = crcbuf.Length;
            for (int n = 0; n < len; n++)
            {
                byte i;
                crc = crc ^ crcbuf[n];
                for (i = 0; i < 8; i++)
                {
                    int TT;
                    TT = crc & 1;
                    crc = crc >> 1;
                    crc = crc & 0x7fff;
                    if (TT == 1)
                    {
                        crc = crc ^ 0xa001;
                    }
                    crc = crc & 0xffff;
                }
            }
            string[] redata = new string[2];
            redata[1] = Convert.ToString((byte)((crc >> 8) & 0xff), 16);
            redata[0] = Convert.ToString((byte)((crc & 0xff)), 16);
            return data + " " + redata[0] + " " + redata[1];
        }

        /// <summary>
        ///CRC ModelBus校验
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static byte[] CRCModelBus(byte[] bytes)
        {
            //计算并填写CRC校验码
            int crc = 0xffff;
            int len = bytes.Length;
            for (int n = 0; n < len; n++)
            {
                byte i;
                crc = crc ^ bytes[n];
                for (i = 0; i < 8; i++)
                {
                    int TT;
                    TT = crc & 1;
                    crc = crc >> 1;
                    crc = crc & 0x7fff;
                    if (TT == 1)
                    {
                        crc = crc ^ 0xa001;
                    }
                    crc = crc & 0xffff;
                }

            }

            var nl = bytes.Length + 2;
            //生成的两位校验码
            byte[] redata = new byte[2];
            redata[0] = (byte)((crc & 0xff));
            redata[1] = (byte)((crc >> 8) & 0xff);

            //重新组织字节数组
            var newByte = new byte[nl];
            for (int i = 0; i < bytes.Length; i++)
            {
                newByte[i] = bytes[i];
            }
            newByte[nl - 2] = (byte)redata[0];
            newByte[nl - 1] = redata[1];

            return newByte;
        }

        /// <summary>
        /// CRC  XMODEM校验模式
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="size">参与校验的数据长度</param>
        /// <returns></returns>
        public static UInt16 CRCXMODEM(byte[] data, int size)
        {
            UInt32 i = 0;
            UInt16 crc = 0;
            for (i = 0; i < size; i++)
            {
                crc = UpdateCRC16(crc, data[i]);
            }
            crc = UpdateCRC16(crc, 0);
            crc = UpdateCRC16(crc, 0);
            return (UInt16)(crc);
        }

        /// <summary>
        /// 更新RCR16校验
        /// </summary>
        /// <param name="crcIn"></param>
        /// <param name="bytee"></param>
        /// <returns></returns>
        private static UInt16 UpdateCRC16(UInt16 crcIn, byte bytee)
        {
            UInt32 crc = crcIn;
            UInt32 ins = (UInt32)bytee | 0x100;
            do
            {
                crc <<= 1;
                ins <<= 1;
                if ((ins & 0x100) == 0x100)
                {
                    ++crc;
                }
                if ((crc & 0x10000) == 0x10000)
                {
                    crc ^= 0x1021;
                }
            }
            while (!((ins & 0x10000) == 0x10000));
            return (UInt16)crc;
        }
    }
}

posted @ 2022-12-03 09:09  星火燎猿*  阅读(677)  评论(0)    收藏  举报