文章首发于浩瀚先森博客

CRC的全称为Cyclic Redundancy Check,中文名称为循环冗余校验。它是一类重要的线性分组码,编码和解码方法简单,检错和纠错能力强,在通信领域广泛地用于实现差错控制。实际上,除 数据通信外,CRC在其它很多领域也是大有用武之地的。例如我们读软盘上的文件,以及解压一个ZIP文件时,偶尔会碰到“Bad CRC”错误,由此它在数据存储方面的应用可略见一斑。

差错控制理论是在代数理论基础上建立起来的。这里我们着眼于介绍CRC的算法与实现,对原理只能捎带说明一下。若需要进一步了解线性码、分组码、循环码、纠错编码等方面的原理,可以阅读有关资料。

利用CRC进行检错的过程可简单描述为:在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的r位监督 码(CRC码),附在原始信息后边,构成一个新的二进制码序列数共k+r位,然后发送出去。在接收端,根据信息码和CRC码之间所遵循的规则进行检验,以 确定传送中是否出错。这个规则,在差错控制理论中称为“生成多项式”。

下面提供C#实现的代码:

#region 计算CRC校验码
/// <summary>
/// 计算CRC校验码,并转换为十六进制字符串
/// Cyclic Redundancy Check 循环冗余校验码
/// 是数据通信领域中最常用的一种差错校验码
/// 特征是信息字段和校验字段的长度可以任意选定
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static string get_CRC16_C(byte[] data)
{
byte num = 0xff;
byte num2 = 0xff; byte num3 = 1;
byte num4 = 160;
byte[] buffer = data; for (int i = 0; i < buffer.Length; i++)
{
//位异或运算
num = (byte)(num ^ buffer[i]); for (int j = 0; j <= 7; j++)
{
byte num5 = num2;
byte num6 = num; //位右移运算
num2 = (byte)(num2 >> 1);
num = (byte)(num >> 1); //位与运算
if ((num5 & 1) == 1)
{
//位或运算
num = (byte)(num | 0x80);
}
if ((num6 & 1) == 1)
{
num2 = (byte)(num2 ^ num4);
num = (byte)(num ^ num3);
}
}
}
return byteToHexStr(new byte[] { num, num2 },2);
} #endregion //获取并校验两数据是否一致
public static bool checkCRC(byte[] srcData, byte[] desData)
{
string crc = get_CRC16_C(srcData);
if (crc == byteToHexStr(desData,desData.Length))
return true;
else
return false;
} /// <summary>
/// 字节数组转16进制字符串
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
public static string byteToHexStr(byte[] bytes, int size)
{
string returnStr = "";
if (bytes != null)
{
for (int i = 0; i < size; i++)
{
returnStr += bytes[i].ToString("X2");
}
}
return returnStr;
}

下面提供C实现的代码:

uint16_t CalcCRC(uint8_t *u8Data, uint8_t u8Size)
{
uint16_t ReturnData;
uint8_t num = 0xff;
uint8_t num2 = 0xff; uint8_t num3 = 1;
uint8_t num4 = 160;
uint8_t buffer[5];
memcpy(buffer,u8Data,u8Size); for (int i = 0; i < u8Size; i++)
{
num = (uint8_t)(num ^ buffer[i]); for (int j = 0; j <= 7; j++)
{
uint8_t num5 = num2;
uint8_t num6 = num; num2 = (uint8_t)(num2 >> 1);
num = (uint8_t)(num >> 1); if ((num5 & 1) == 1)
{
num = (uint8_t)(num | 0x80);
}
if ((num6 & 1) == 1)
{
num2 = (uint8_t)(num2 ^ num4);
num = (uint8_t)(num ^ num3);
}
}
}
ReturnData = num;
ReturnData = ReturnData<<8;
ReturnData |= num2;
return ReturnData; } ITStatus checkCRC(uint8_t *srcData, uint8_t u8srcSize, uint8_t *desData)
{
uint16_t returnData = CalcCRC(srcData, u8srcSize); if(((returnData>>8) == *desData) && ((returnData&0x00ff)==*(desData+1)))
return SET;
else
return RESET; }
 

C#和C实现通过CRC-16 (Modbus)获取CRC值并校验数据(代码)的更多相关文章

  1. Modbus CRC 16 (C#)

    算法 1.预置一个值为 0xFFFF 的 16 位寄存器,此寄存器为 CRC 寄存器. 2.把第 1 个 8 位二进制数据(即通信消息帧的第 1 个字节)与 16 位的 CRC 寄存器相异或,异或的结 ...

  2. 基于MODBUS的CRC

    %ws   WCHAR wszName CRC原理 设编码前的原始信息多项式为P(x),P(x)的最高幂次加1等于k:生成多项式为G(x),G(x)的最高幂次等于r:CRC多项式为R(x):编码后的带 ...

  3. Modbus协议 CRC 校验码

    CRC(循环冗余校验)在线计算 http://www.ip33.com/crc.html 里面的8005的多项式值,但网上看到的算法都是用A001来异或的 ---------------------- ...

  4. CRC(16位)多项式为 X16+X15+X2+1

    其对应校验二进制位列为1 1000 0000 0000 0101,可这有17位啊,我怎么和16位信息进行异或啊?是不是不要最高位的1 你没有弄明白crc的意思.这17位后面再添上16个零,然后开始抑或 ...

  5. Modbus RTU CRC校验码计算方法

    在CRC计算时只用8个数据位,起始位及停止位,如有奇偶校验位也包括奇偶校验位,都不参与CRC计算. CRC计算方法是: 1.  加载一值为0XFFFF的16位寄存器,此寄存器为CRC寄存器. 2.   ...

  6. php 将16进制数串转换为二进制数据的函数

    /**     * 将16进制数串转换为二进制数据的函数     * @param $hexdata     * @return string bindata     */     function ...

  7. C# CRC - 16

    using System; static class Program { static void Main() { string input = "8000"; var bytes ...

  8. HJ212 CRC 16 (C#)

    算法 CRC16 校验寄存器赋值为 0xFFFF: 取被校验串的第一个字节赋值给临时寄存器: 临时寄存器与 CRC16 校验寄存器的高位字节进行"异或"运算,赋值给 CRC16 校 ...

  9. 国内A股16家上市银行的財务数据与股价的因子分析报告(1)(工具:R)

    分析人:BUPT_LX 研究目的 用某些算法对2014年12月份的16家国内A股上市的商业银行当中11项財务数据(资产总计.负债合计.股本.营业收入.流通股A.少数股东权益.净利润.经营活动的现金流量 ...

随机推荐

  1. Idea开发环境中搭建Maven并且使用Maven打包部署程序

    1.配置Maven的环境变量 a.首先我们去maven官网下载Maven程序,解压到安装目录,如图所示: b.配置M2_HOME的环境变量,然后将该变量添加到Path中 备注:必须要有JAVA_HOM ...

  2. Thinkcmf:页面常用函数

    Thinkcmf:页面常用函数 全站seo: 文章列表: {$site_seo_title}        <!--SEO标题--> {$site_seo_keywords}   < ...

  3. jquery attr()方法

    在JS中设置节点的属性与属性值用到setAttribute(),获得节点的属性与属性值用到getAttribute(),而在jquery中,用一个attr()就可以全部搞定了,赞一个先 ^^ jque ...

  4. iOS Block简介

    Block是对象,它封装了一段代码,这段代码可以在任何时候执行.block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值.它和传统的函数指针很类似,但是有区别:block是inli ...

  5. SharePoint 2013 Ajax 造成页面无法编辑

    1.如下图,在编辑页面的时候,出现如下错误“此网页自上次打开后已被修改,必须再次打开该网页”,页面上没有什么特别的设置,就是default.aspx: 2.编辑之前页面,只有一个内容编辑器部件,和若干 ...

  6. Android开发学习——android存储

    Android的存储 内部存储空间RAM内存:运行内存,相当于电脑的内存ROM内存:存储内存,相当于电脑的硬盘外部存储空间 SD卡:相当于电脑的移动硬盘    * 2.2之前,sd卡路径:sdcard ...

  7. Android 更新UI的几种方式

    1.Activity的 runOnUiThread textView = (TextView) findViewById( R.id.tv ); new Thread(new Runnable() { ...

  8. PHP魔术常量

    与J2E相比PHP没有九个内置对象,但他有八个魔术变量分别是: '__LINE__' 文件中的当前行号. '__FILE__ 文件的完整路径和文件名. '__DIR__' 文件所在的目录. '__FU ...

  9. iOS 实用博客整理(连载版)

    iOS 实用博客整理(连载版) 本博客为本人觉得不错的博客的暂存地,并不是本人所写. 1.iOS开发 如何适配iOS10? 2.UIWebView和WKWebView的比较和选择 3. 如何快速的开发 ...

  10. Adobe AIR 中为不同尺寸和分辨率屏幕适配

    在 Adobe AIR 中为不同屏幕尺寸的多种设备提供支持 http://www.adobe.com/cn/devnet/air/articles/multiple-screen-sizes.html ...