C#和C实现通过CRC-16 (Modbus)获取CRC值并校验数据(代码)
文章首发于浩瀚先森博客
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值并校验数据(代码)的更多相关文章
- Modbus CRC 16 (C#)
算法 1.预置一个值为 0xFFFF 的 16 位寄存器,此寄存器为 CRC 寄存器. 2.把第 1 个 8 位二进制数据(即通信消息帧的第 1 个字节)与 16 位的 CRC 寄存器相异或,异或的结 ...
- 基于MODBUS的CRC
%ws WCHAR wszName CRC原理 设编码前的原始信息多项式为P(x),P(x)的最高幂次加1等于k:生成多项式为G(x),G(x)的最高幂次等于r:CRC多项式为R(x):编码后的带 ...
- Modbus协议 CRC 校验码
CRC(循环冗余校验)在线计算 http://www.ip33.com/crc.html 里面的8005的多项式值,但网上看到的算法都是用A001来异或的 ---------------------- ...
- CRC(16位)多项式为 X16+X15+X2+1
其对应校验二进制位列为1 1000 0000 0000 0101,可这有17位啊,我怎么和16位信息进行异或啊?是不是不要最高位的1 你没有弄明白crc的意思.这17位后面再添上16个零,然后开始抑或 ...
- Modbus RTU CRC校验码计算方法
在CRC计算时只用8个数据位,起始位及停止位,如有奇偶校验位也包括奇偶校验位,都不参与CRC计算. CRC计算方法是: 1. 加载一值为0XFFFF的16位寄存器,此寄存器为CRC寄存器. 2. ...
- php 将16进制数串转换为二进制数据的函数
/** * 将16进制数串转换为二进制数据的函数 * @param $hexdata * @return string bindata */ function ...
- C# CRC - 16
using System; static class Program { static void Main() { string input = "8000"; var bytes ...
- HJ212 CRC 16 (C#)
算法 CRC16 校验寄存器赋值为 0xFFFF: 取被校验串的第一个字节赋值给临时寄存器: 临时寄存器与 CRC16 校验寄存器的高位字节进行"异或"运算,赋值给 CRC16 校 ...
- 国内A股16家上市银行的財务数据与股价的因子分析报告(1)(工具:R)
分析人:BUPT_LX 研究目的 用某些算法对2014年12月份的16家国内A股上市的商业银行当中11项財务数据(资产总计.负债合计.股本.营业收入.流通股A.少数股东权益.净利润.经营活动的现金流量 ...
随机推荐
- 接入统计Crash的工具Crashlytics-ios
1. 注册账户 登录网站 https://get.fabric.io/ 来注册新的账户 2. account confirmed之后就出现相应的设置页面,设置你的team的名称 3. 出现页面提示下载 ...
- (有趣)chrome不同浏览器版本对display:flex和溢出隐藏显示省略符号的bug
项目中碰到一个十分有趣的情形: 布局要求是这样:右边创建新订单是固定宽度80px,左侧是自适应宽度,溢出隐藏.如下图. 这里布局不用说肯定使用display:flex的.左侧flex:1;右侧widt ...
- 标准BST二叉搜索树写法
本人最近被各种数据结构的实验折磨的不要不要的,特别是代码部分,对数据结构有严格的要求,比如写个BST要分成两个类,一个节点类,要给树类,关键是所以操作都要用函数完成,也就是在树类中不能直接操作节点,需 ...
- hibernate(3) —— 关系映射
hibernate中关系映射指的是实体类与实体类间的关系.和数据库中表与表之间的关系类似,有一对一,多对一,一对多,多对多四种映射关系. 一:一对一映射 两个对象之间是一对一的关系,如人和身份证之间是 ...
- Android+PHP+MYSQL把数据库中的数据显示在Android界面上
俗话说,好记性不如烂笔头.今天终于体会其中的道理了.昨天写好的代码不知道为何找不到了.所以今天我一定得抽出一点时间把我的代码保存起来,以防我的代码再没有了. 还是先上图片. 这个界面是用ListVie ...
- IOS开发之----#import、#include和@class的区别
1. 一般来说,导入objective c的头文件时用#import,包含c/c++头文件时用#include. 2. #import 确定一个文件只能被导入一次,这使你在递归包含中不会出现问题.&l ...
- ThinkPHP3快速入门教程-:基础
一.ThinkPHP的认识: ThinkPHP是一个快速.简单的基于MVC和面向对象的轻量级PHP开发框架. 二.下载后的目录结构: ├─ThinkPHP.php 框架入口文件 ├─Commo ...
- ORACLE清理、截断监听日志文件(listener.log)
在ORACLE数据库中,如果不对监听日志文件(listener.log)进行截断,那么监听日志文件(listener.log)会变得越来越大,想必不少人听说过关于"LISTENER.LOG日 ...
- Linux Bond 技术学习资料
Bond 技术原理 Bond 就是将多块网卡虚拟成为一块网卡的技术,通过 bond 技术让多块网卡看起来是一个单独的以太网接口设备并具有相同的 IP 地址. Bond 的原理是网卡在混杂 (promi ...
- SQL SERVER修改排序规则——脚本篇
在上篇MS SQL 排序规则总结中,大致就数据库服务器排序规则(或者叫数据库实例排序规则).数据库排序规则.列的排序规则粗浅的叙说了一遍,重点讲述了修改数据库服务器排序规则(数据库实例排序规则),其中 ...