基于在线CRC计算,当我输入十六进制字符串data =
503002080000024400003886030400000000010100
I get result CRC-CCITT (0xFFFF) =
0x354E(预期结果)
.
我使用下面的代码,但是CalcCRC16()的结果是0xACEE。下面缺少什么脚本?
using System;
using System.Windows.Forms;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
using System.Diagnostics;
namespace WindowsFormsApplication1 {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
string result = CalcCRC16("503002080000024400003886030400000000010100");
Debug.Print(result);
// result = ACEE
// result expected = 354E
}
// CRC-CCITT (0xFFFF) with poly 0x1021
// input (hex string) = "503002080000024400003886030400000000010100"
// result expected (hex string) = "354E"
public string CalcCRC16(string strInput) {
ushort temp = 0;
ushort crc = 0xFFFF;
byte[] bytes = GetBytesFromHexString(strInput);
for (int j = 0; j < bytes.Length; j++) {
crc = (ushort)(crc ^ bytes[j]);
for (int i = 0; i < 8; i++) {
if ((crc & 0x0001) == 1)
crc = (ushort)((crc >> 1) ^ 0x1021);
else
crc >>= 1;
}
}
crc = (ushort)~(uint)crc;
temp = crc;
crc = (ushort)((crc << 8) | (temp >> 8 & 0xFF));
return crc.ToString("X4");
}
public Byte[] GetBytesFromHexString(string strInput) {
Byte[] bytArOutput = new Byte[] { };
if (!string.IsNullOrEmpty(strInput) && strInput.Length % 2 == 0) {
SoapHexBinary hexBinary = null;
try {
hexBinary = SoapHexBinary.Parse(strInput);
if (hexBinary != null)
bytArOutput = hexBinary.Value;
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}
return bytArOutput;
}
}
}
我找到了答案,我将在这里分享。可能对别人有用。
strInput = 503002080000024400003886030400000000010100
initial = 0xFFFF
poly = 0x1021
strOutput = 354E
reference = Online CRC Calc
public string CalcCRC16(string strInput) {
ushort crc = 0xFFFF;
byte[] data = GetBytesFromHexString(strInput);
for (int i = 0; i < data.Length; i++) {
crc ^= (ushort)(data[i] << 8);
for (int j = 0; j < 8; j++) {
if ((crc & 0x8000) > 0)
crc = (ushort)((crc << 1) ^ 0x1021);
else
crc <<= 1;
}
}
return crc.ToString("X4");
}
public Byte[] GetBytesFromHexString(string strInput) {
Byte[] bytArOutput = new Byte[] { };
if (!string.IsNullOrEmpty(strInput) && strInput.Length % 2 == 0) {
SoapHexBinary hexBinary = null;
try {
hexBinary = SoapHexBinary.Parse(strInput);
if (hexBinary != null) {
bytArOutput = hexBinary.Value;
}
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}
return bytArOutput;
}
下面是一个在我的应用程序中工作的示例。我有点挣扎,现在我知道这是因为我不得不使用char ptrs而不是16位int指针(因为CCIT是LSB顺序优先,所以我们从缓冲区中选择1个字节,将其移位8次使其变为16位以验证上MSB位0x8000)。
当人们与16位CRC斗争时发现的大多数原因(而大多数情况下8位有效):
- Buffer应该被8bit ptr 调用
- 在异或之前移动! 永远不要使用int或unsigned int..但要用短!我的应用程序运行在16位和32位Microchip PIC上,使用整数在16位PIC上产生16位值,在32位平台上产生32位值(这么多零!)。
BOOL = unsigned char。UINT16 = unsigned short;该函数在代码中运行,因此不是while/forloop。完成后,CRC被复制到* CRC所指向的地址。这样所有其他任务(M95调制解调器,MCP的I2C, Flash日志,TCP/IP等)将不会有太大的延迟。
BOOL CRC_16(UINT16 ui16_Bytes, char *src, UINT16 *crc)
{
static BOOL bNew = FALSE;
static UINT16 remainder = 0;
static UINT16 i = 0;
static UINT16 ui16_Loc_bytes;
static char *ptr;
static char locData;
if(!bNew)
{
ui16_Loc_bytes = ui16_Bytes;
ptr = src;
locData = *ptr;
i = 8;
remainder = 0x0000;
bNew = TRUE;
}
if(ui16_Loc_bytes)
{
if(i == 8)
{
remainder ^= (((UINT16)locData)<<8); //Only 8bits at a time filled with zeros
}
if(i)
{
if (remainder & 0x8000)
{
remainder = (remainder << 1);
remainder ^= POLYNOMIAL_16;
}
else
{
remainder = (remainder << 1);
}
i--;
}
else
{
ui16_Loc_bytes--;
ptr++;
locData = *ptr;
//ptr++;
i = 8;
}
}
else
{
bNew = FALSE;
*crc = remainder;
return TRUE;
}
return FALSE;
}
if(SDKaart.ui16_RecBytes >= SDKaart.ui16_ByteLen)//30-5-2018 edited SDKaart.CMD[SDKaart.ui8_ActiefCMD].ui16_RecLen)
{
SD_DESELECT;
if(SDKaart.bInitReady && SDKaart.b_BlockRead)
{
if(CRC_16(512,(char*)&SDKaart.Mem_Block.SD_Buffer[0], &SDKaart.ui16_MemBlock_CRC))
{
if((((UINT16)SDKaart.Mem_Block.SD_Buffer[512]<<8)|(UINT16)SDKaart.Mem_Block.SD_Buffer[513]) == SDKaart.ui16_MemBlock_CRC)
{
SDKaart.bRXReady = TRUE;
SDKaart.TXStat = SPI_IDLE;
printf("CRC16 OK %xrn",SDKaart.ui16_MemBlock_CRC);
}
else
{
SDKaart.bRXReady = TRUE;
SDKaart.TXStat = SPI_IDLE;
printf("CRC16 %u != 0x%x 0x%xrn",SDKaart.ui16_MemBlock_CRC,SDKaart.Mem_Block.SD_Buffer[512], SDKaart.Mem_Block.SD_Buffer[513] );
}
//printf("CRC citt: %urn", Calculate_CRC_CCITT((char *)&SDKaart.Mem_Block.SD_Buffer[0],512));
}
}
else
{
SDKaart.bRXReady = TRUE;
SDKaart.TXStat = SPI_IDLE;
}
}
else
{
if(SD_SPI_TX_READY)
{
SDKaart.bNewSPIByte = TRUE;
SPI1BUF = SD_EMPTY_BYTE;
}
}
我已经使用了许多在网上找到的crcs,但很多都不起作用。请注意,许多在线"示例"确实在XOR后面使用<<1,但必须在XOR之前完成。
POLY_16是0x1021。下一个机会是构建一个表选择器。:)
Greetz约翰。