不一定。CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,接收设备也执行类似的算法,以保证数据传输的正确性和完整性。
用CRC校验来实现判断自身完整性的,这种办法是先取得一个原始的crc值,再通过运行后取得现在的crc值,两者比对,如果一致就视为软件没有被修改,否则就视为修改了。
从你上面的代码片段来看,获取crc值的功能已经有了,下一步需要将这个与原始值进行比较,这个原始值通常要保存在外部(因为这个值在编译之前是未知的),过程可以这样:首先,代码先编写完成,比如:
if crc<>0 then
begin
Edit2Text:=PChar(IntToHex(crc,6));
if Edit2Text = GetMyCrc() then
//如果校验相等
else
//如果校验不相等……
end;
编译完成后,获取这个文件的CRC码(你上面的Edit2Text),将这个值保存到这个值你可以保存到文件、注册表等等地方,还可以将这个值进行加密处理。
GetMyCrc()这个函数的功能,是取得你保存的文件、注册表等等地方CRC值,取得后,再跟现在的CRC值进行比较就可以了。
为保证传输过程的正确性,需要对通信过程进行差错控制。差错控制最常用的方法是自动请求重发方式(ARQ)、向前纠错方式(FEC)和混合纠错(HEC)。在传输过程误码率比较低时,用FEC方式比较理想。在传输过程误码率较高时,采用FEC容易出现“乱纠”现象。HEC方式则是ARQ和FEC的结合。在许多数字通信中,广泛采用ARQ方式,此时的差错控制只需要检错功能。实现检错功能的差错控制方法很多,传统的有:奇偶校验、校验和检测、重复码校验、恒比码校验、行列冗余码校验等,这些方法都是增加数据的冗余量,将校验码和数据一起发送到接受端。接受端对接受到的数据进行相同校验,再将得到的校验码和接受到的校验码比较,如果二者一致则认为传输正确。但这些方法都有各自的缺点,误判的概率比较高。
循环冗余校验CRC(Cyclic Redundancy Check)是由分组线性码的分支而来,其主要应用是二元码组。编码简单且误判概率很低,在通信系统中得到了广泛的应用。下面重点介绍了CRC校验的原理及其算法实现。
CRC校验可以100%地检测出所有奇数个随机错误和长度小于等于k(k为g(x)的阶数)的突发错误。所以CRC的生成多项式的阶数越高,那么误判的概率就越小。
CRC代码的一些基本概念和运算:
CRC多项式:
例:
代码:1010111 对应的多项式为:X6+X4+X2+X+1
多项式X5+X3+X2+X1+1对应的代码为101111
CRC生成多项式:
首位和最后一位必须是1。CRC生成多项式是给定的,在传输过程中不变,即发送和接收端生成码相同。
一些常用的校验码为:
CRC8=X8+X5+X4+1
CRC-CCITT=X16+X12+X5+1
CRC16=X16+X15+X5+1
CRC12=X12+X11+X3+X2+1
CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+1
CRC的运算本质是异或运算(模2除法)
例:原信息码为1011001
生成码为11001
校验码计算过程
① 将信息码左移4位(生成码长-1);得到10110010000
② 异或运算
10110010000
11001
01111010000(前面的数进行异或运算,后面的直接抄下来)
11001
0011110000(和生成码异或运算的必须从1开始)
11001
00111000
11001
001010
这样得到的结果为1010,即为所需要的校验码,添加到信息码后,得到发送的代码为:
10110011010
我把上面的手算过程用c#写了一段程序,如下:
using System;
namespace mainClass
{
public class mainProgress
{
public static void Main()
{
byte[] msg={1,0,1,1,0,0,1};//信息码
byte[] gmsg=new byte[msgLength+4];
crc c = new crc();
gmsg=ccode(msg);
ConsoleWrite("编码后字符串为:");
for (int i = 0; i < gmsgLength; i++)
{
ConsoleWrite("{0}", gmsg[i]ToString());
}
ConsoleWrite("\n");
byte[] gmsg1={ 1, 0, 1, 1, 0, 1, 1 };//接收到的代码
bool r = cdet(gmsg1);
if (r)
{
ConsoleWriteLine("传输正确");
}
else
{ ConsoleWriteLine("传输错误"); }
}
}
public class crc//CRC编码类
{
private byte[] g = { 1,1,0,0,1};//生成码
public byte[] code(byte[] msg)//编码
{
byte[] gmsg=new byte[gLength+msgLength-1];
msgCopyTo(gmsg, 0);//
for (int i = 0; i < msgLength; i++)//完成异或运算,即模2除法
{
if (gmsg[i] == 1)
{
for (int j = 0; j < gLength; j++)
{
if (gmsg[i + j] == g[j])
gmsg[i + j] = 0;
else
gmsg[i + j] = 1;
}
}
}
msgCopyTo(gmsg, 0);
return gmsg;
}
private bool f=true;
//接收端检测
public bool det(byte[] gmsg)
{
for (int i = 0; i < gmsgLength - gLength+1; i++)
{
if(gmsg[i]==0)
continue;
for (int j = 0; j < gLength; j++)
{
if (gmsg[i + j] == g[j])
gmsg[i + j] = 0;
else
gmsg[i + j] = 1;
}
}
for (int i = 0; i < gmsgLength; i++)
{
if (gmsg[i] == 1)
f = false;
}
return f;
}
}
}
using System;
using SystemCollectionsGeneric;
using SystemLinq;
using SystemText;
namespace ConvertToCRC16
{
public static class CRC16Util
{
// CRC高位字节表
private static readonly byte[] m_CRCHighOrderByteTable = new byte[]
{
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
};
// CRC低位字节表
private static readonly byte[] m_CRCLowOrderByteTable = new byte[]
{
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
};
/// <summary>
/// 获得CRC16效验码
/// </summary>
/// <param name="buffer"></param>
/// <returns></returns>
public static void CalculateCrc16(byte[] buffer, out byte crcHighOrderByte, out byte crcLowOrderByte)
{
// CRC高位字节/低位字节
crcHighOrderByte = crcLowOrderByte = 0xff;
for (int i = 0; i < bufferLength; i++)
{
// 计算CRC查找索引
int crcIndex = crcHighOrderByte ^ buffer[i];
crcHighOrderByte = (byte)(crcLowOrderByte ^ m_CRCHighOrderByteTable[crcIndex]);
crcLowOrderByte = (byte)m_CRCLowOrderByteTable[crcIndex];
}
}
}
}
// 工具函数如上
程序问题,CRC错误是程序自带的一个自校验程序,可以自动检验你所安装的程序是否跟原程序一致,如果不一致就会出现CRC错误,建议你换个网站下 你的问题 是所有的文件都这样? 那就是你电脑的问题 100%确定你的内存有问题,可能是不兼容,或是坏了特别是两根内存最可能出现这种情况,检查主板bios或做成单通道都可以解决
unsigned short crc_dsp(unsigned short reg, unsigned char data_crc)
//reg为crc寄存器, data_crc为将要处理的8bit数据流
{
unsigned short msb; //crc寄存器将移出的最高1bit
unsigned short data;
unsigned short gx = 0x8005, i = 0; //i为左移次数, gx为生成多项式
data = (unsigned short)data_crc;
data = data << 8;
reg = reg ^ data;
do
{
msb = reg & 0x8000;
reg = reg << 1;
if(msb == 0x8000)
{
reg = reg ^ gx;
}
i++;
}
while(i < 8);
return (reg);
}
以上就是关于FX读写CRC校验程序要独立写两个吗全部的内容,包括:FX读写CRC校验程序要独立写两个吗、怎么用CRC实现 软件自身的完整性检查功能 Delphi、关于CRC效验等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)