将 CRC 计算从 C# 转换为 C
Convert CRC calculation from C# to C
我目前正在使用串行监视器,以确保某些数据完整性我正在尝试实现 CRC8 校验和,下面是我在发送消息之前对任何消息所做的计算。
public byte Checksum(params byte[] val)
{
if (val == null)
throw new ArgumentNullException("val");
byte c = 0;
foreach (byte b in val)
{
c = table[c ^ b];
}
return c;
}
我使用 0xD8:
生成一个 table
public byte[] GenerateTable(CRC8_POLY polynomial)
{
byte[] csTable = new byte[256];
for (int i = 0; i < 256; ++i)
{
int curr = i;
for (int j = 0; j < 8; ++j)
{
if ((curr & 0x80) != 0)
{
curr = (curr << 1) ^ (int)polynomial;
}
else
{
curr <<= 1;
}
}
csTable[i] = (byte)curr;
}
return csTable;
}
这是我用来测试设置的代码:
private void btnSend_Click(object sender, EventArgs e)
{
ProtoFrame rxFrame = new ProtoFrame();
if (cboParam.Text == "test")
{
rxFrame.Start = 0x73;
rxFrame.Size = 9;
rxFrame.Command = 01;
rxFrame.Unused = 0;
rxFrame.ParamId = 0x0100;
rxFrame.Param = 8000;
}
byte[] rxBuffer = getBytes(rxFrame); //call to byte array formatter
rxBuffer[rxBuffer.Length-1] = Checksum(rxBuffer); //append crc at end of array
ComPort.Write(rxBuffer, 0, rxBuffer.Length);
}
static byte[] getBytes(object str) //input struct
{
int size = Marshal.SizeOf(str) + 1;
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(str, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
据我所知,这段代码按预期工作,我正在使用 table 生成器在我的微控制器中实现硬编码 table,以加快进程。
我不太明白的是我如何实现一个函数来以与我在这里所做的类似的方式计算 CRC。
任何正确方向的帮助或指导都是值得赞赏的。
到目前为止,我想出了这个功能:
uint8_t crc8(uint8_t *crc)
{
uint8_t crcVal;
int m;
for (m = 0; m < PacketSize ;m++ )startbyte
{
*crc = crc8_table[(*crc) ^ m];
*crc &= 0xFF;
}
}
其中 table 是:
uint8_t crc8_table[256] = {0,24,48,40,96,120,80,72,192,216,240,232,160,184,144,136,88,64,104,112,56,32,8,16,
152,128,168,176,248,224,200,208,176,168,128,152,208,200,224,248,112,104,64,88,16,8,
32,56,232,240,216,192,136,144,184,160,40,48,24,0,72,80,120,96,184,160,136,144,216,
192,232,240,120,96,72,80,24,0,40,48,224,248,208,200,128,152,176,168,32,56,16,8,64,
88,112,104,8,16,56,32,104,112,88,64,200,208,248,224,168,176,152,128,80,72,96,120,48,
40,0,24,144,136,160,184,240,232,192,216,168,176,152,128,200,208,248,224,104,112,88,
64,8,16,56,32,240,232,192,216,144,136,160,184,48,40,0,24,80,72,96,120,24,0,40,48,120,
96,72,80,216,192,232,240,184,160,136,144,64,88,112,104,32,56,16,8,128,152,176,168,224,
248,208,200,16,8,32,56,112,104,64,88,208,200,224,248,176,168,128,152,72,80,120,96,40,
48,24,0,136,144,184,160,232,240,216,192,160,184,144,136,192,216,240,232,96,120,80,72,
0,24,48,40,248,224,200,208,152,128,168,176,56,32,8,16,88,64,104,112
};
并且 PacketSize 是从 rxFrame.Size
中找到的
看C#代码应该是:
uint8_t crc8(uint8_t const *crc, size_t size)
{
unit8_t c = 0;
size_t m;
for (m = 0; m < size; m++ )
{
c = crc8_table[c ^ *crc];
crc++;
}
return c;
}
因此您只需将 C# 函数移植到 C
public byte Checksum(params byte[] val)
{
if (val == null)
throw new ArgumentNullException("val");
byte c = 0;
foreach (byte b in val)
{
c = table[c ^ b];
}
return c;
}
我。 C 中没有例外。使用 return 值指示错误并添加一个参数,您将用作 return 值。由您决定是将消息长度作为参数传递还是将其保留在全局范围内:
int checksum(uint8_t const *msg, size_t msglen, uint8_t *result)
二。 foreach
循环转换为 for
循环,其中 i
是索引,msg[i]
是 foreach
:
中的 b
int checksum(uint8_t const *msg, size_t msglen, uint8_t *result)
{
if (msg == NULL || msglen == 0)
return 0;
uint8_t crc = 0;
for (int i = 0; i < msglen; i++)
{
crc = table[crc ^ msg[i]];
}
III。存储结果和 return 成功代码:
int checksum(uint8_t const *msg, size_t msglen, uint8_t *result)
{
if (msg == NULL || msglen == 0)
return 0;
uint8_t crc = 0;
for (int i = 0; i < msglen; i++)
{
crc = table[crc ^ msg[i]];
}
*result = crc;
return 1;
}
IV。用法:
uint8_t crc;
if (!checksum(message, PacketSize, &crc))
report_error();
不要使用指针,转换为数组
public static byte crc8(byte[] crc)
{
byte crcVal;
int m;
for (m = 0; m < PacketSize; m++)
{
crc[m] = crc8_table[crc[m] ^ m];
crc[m] &= 0xFF;
}
return crcVal;
}
我目前正在使用串行监视器,以确保某些数据完整性我正在尝试实现 CRC8 校验和,下面是我在发送消息之前对任何消息所做的计算。
public byte Checksum(params byte[] val)
{
if (val == null)
throw new ArgumentNullException("val");
byte c = 0;
foreach (byte b in val)
{
c = table[c ^ b];
}
return c;
}
我使用 0xD8:
生成一个 tablepublic byte[] GenerateTable(CRC8_POLY polynomial)
{
byte[] csTable = new byte[256];
for (int i = 0; i < 256; ++i)
{
int curr = i;
for (int j = 0; j < 8; ++j)
{
if ((curr & 0x80) != 0)
{
curr = (curr << 1) ^ (int)polynomial;
}
else
{
curr <<= 1;
}
}
csTable[i] = (byte)curr;
}
return csTable;
}
这是我用来测试设置的代码:
private void btnSend_Click(object sender, EventArgs e)
{
ProtoFrame rxFrame = new ProtoFrame();
if (cboParam.Text == "test")
{
rxFrame.Start = 0x73;
rxFrame.Size = 9;
rxFrame.Command = 01;
rxFrame.Unused = 0;
rxFrame.ParamId = 0x0100;
rxFrame.Param = 8000;
}
byte[] rxBuffer = getBytes(rxFrame); //call to byte array formatter
rxBuffer[rxBuffer.Length-1] = Checksum(rxBuffer); //append crc at end of array
ComPort.Write(rxBuffer, 0, rxBuffer.Length);
}
static byte[] getBytes(object str) //input struct
{
int size = Marshal.SizeOf(str) + 1;
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(str, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
据我所知,这段代码按预期工作,我正在使用 table 生成器在我的微控制器中实现硬编码 table,以加快进程。
我不太明白的是我如何实现一个函数来以与我在这里所做的类似的方式计算 CRC。
任何正确方向的帮助或指导都是值得赞赏的。
到目前为止,我想出了这个功能:
uint8_t crc8(uint8_t *crc)
{
uint8_t crcVal;
int m;
for (m = 0; m < PacketSize ;m++ )startbyte
{
*crc = crc8_table[(*crc) ^ m];
*crc &= 0xFF;
}
}
其中 table 是:
uint8_t crc8_table[256] = {0,24,48,40,96,120,80,72,192,216,240,232,160,184,144,136,88,64,104,112,56,32,8,16,
152,128,168,176,248,224,200,208,176,168,128,152,208,200,224,248,112,104,64,88,16,8,
32,56,232,240,216,192,136,144,184,160,40,48,24,0,72,80,120,96,184,160,136,144,216,
192,232,240,120,96,72,80,24,0,40,48,224,248,208,200,128,152,176,168,32,56,16,8,64,
88,112,104,8,16,56,32,104,112,88,64,200,208,248,224,168,176,152,128,80,72,96,120,48,
40,0,24,144,136,160,184,240,232,192,216,168,176,152,128,200,208,248,224,104,112,88,
64,8,16,56,32,240,232,192,216,144,136,160,184,48,40,0,24,80,72,96,120,24,0,40,48,120,
96,72,80,216,192,232,240,184,160,136,144,64,88,112,104,32,56,16,8,128,152,176,168,224,
248,208,200,16,8,32,56,112,104,64,88,208,200,224,248,176,168,128,152,72,80,120,96,40,
48,24,0,136,144,184,160,232,240,216,192,160,184,144,136,192,216,240,232,96,120,80,72,
0,24,48,40,248,224,200,208,152,128,168,176,56,32,8,16,88,64,104,112
};
并且 PacketSize 是从 rxFrame.Size
中找到的看C#代码应该是:
uint8_t crc8(uint8_t const *crc, size_t size)
{
unit8_t c = 0;
size_t m;
for (m = 0; m < size; m++ )
{
c = crc8_table[c ^ *crc];
crc++;
}
return c;
}
因此您只需将 C# 函数移植到 C
public byte Checksum(params byte[] val)
{
if (val == null)
throw new ArgumentNullException("val");
byte c = 0;
foreach (byte b in val)
{
c = table[c ^ b];
}
return c;
}
我。 C 中没有例外。使用 return 值指示错误并添加一个参数,您将用作 return 值。由您决定是将消息长度作为参数传递还是将其保留在全局范围内:
int checksum(uint8_t const *msg, size_t msglen, uint8_t *result)
二。 foreach
循环转换为 for
循环,其中 i
是索引,msg[i]
是 foreach
:
b
int checksum(uint8_t const *msg, size_t msglen, uint8_t *result)
{
if (msg == NULL || msglen == 0)
return 0;
uint8_t crc = 0;
for (int i = 0; i < msglen; i++)
{
crc = table[crc ^ msg[i]];
}
III。存储结果和 return 成功代码:
int checksum(uint8_t const *msg, size_t msglen, uint8_t *result)
{
if (msg == NULL || msglen == 0)
return 0;
uint8_t crc = 0;
for (int i = 0; i < msglen; i++)
{
crc = table[crc ^ msg[i]];
}
*result = crc;
return 1;
}
IV。用法:
uint8_t crc;
if (!checksum(message, PacketSize, &crc))
report_error();
不要使用指针,转换为数组
public static byte crc8(byte[] crc)
{
byte crcVal;
int m;
for (m = 0; m < PacketSize; m++)
{
crc[m] = crc8_table[crc[m] ^ m];
crc[m] &= 0xFF;
}
return crcVal;
}