文章首发于浩瀚先森博客

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. jQuery DateTimePicker 日期控件

    在线实例 实例演示 使用方法 <input id="datetimepicker" type="text" > 复制 $('#datetimepic ...

  2. HTML5学习笔记一 简单学习HTML5

    什么是HTML? HTML 是用来描述网页的一种语言. HTML 指的是超文本标记语言: HyperText Markup Language HTML 不是一种编程语言,而是一种标记语言 标记语言是一 ...

  3. 本周进步要点20161023(含李笑来第二场live笔记要点)

    本周主要忙于去武汉参加iDOF2016智能数字油田会议,会上做了题为“油田SOA及云平台的系统思考与实践”的报告,为了准备这篇报告,用到了一些以前学过的知识,具体内容见“参加iDOF2016会议的收获 ...

  4. 二进制配置文件为什么比json等配置文件效率高

    二进制配置文件为什么比json等配置文件高效 项目中用spine做动画,spine可以导出json和二进制的动画配置文件,蛋疼的是spine官方竟然没有提供c的二进制配置解析代码,更没有提供它二进制文 ...

  5. iOS源代码管理工具

    源代码管理工具简介 1.为什么会出现源代码管理工具? 为了解决在软件开发过程中,由源代码引发的各种蛋疼.繁琐的问题 2.源代码管理不当可能会引起的后果? 无法后悔:做错了一个操作后,不能回到之前的操作 ...

  6. 使用FragmentTabHost+TabLayout+ViewPager实现双层嵌套Tab

    大多数应用程序都会在底部使用3~5个Tab对应用程序的主要功能进行划分,对于一些信息量非常大的应用程序,还需要在每个Tab下继续划分子Tab对信息进行分类显示. 本文实现采用FragmentTabHo ...

  7. Feathers组件的宽度或高度属性,为什么我得到的值是0

    Feathers组件使用一个失效系统延迟一会儿繁重的重绘,这样你可以在一个时间内改变多个属性.如果你还没有明确地设置宽度和高度,他们会自动 调整自身到一套“理想”的尺度.然而,这并不会发生,直到他们验 ...

  8. [环境搭建] VS-Visual Studio-IIS Express 支持局域网访问

    使用Visual Studio开发Web网页的时候有这样的情况:想要在调试模式下让局域网的其他设备进行访问,以便进行测试.虽然可以部署到服务器中,但是却无法进行调试,就算是注入进程进行调试也是无法达到 ...

  9. Jsoup解析html终于成功了!!!

    package com.eric.pickupjoke.activity; import java.io.IOException; import java.io.InputStream; import ...

  10. #研发解决方案介绍#基于StatsD+Graphite的智能监控解决方案

    郑昀 基于李丹和刘奎的文档 创建于2014/12/5 关键词:监控.dashboard.PHP.graphite.statsd.whisper.carbon.grafana.influxdb.Pyth ...