ZHCAAO5A June 2020 – August 2021 ADS112C04 , ADS112U04 , ADS114S06 , ADS114S08 , ADS122C04 , ADS122U04 , ADS1235 , ADS1235-Q1 , ADS124S06 , ADS124S08 , ADS1259 , ADS1259-Q1 , ADS125H01 , ADS125H02 , ADS1260 , ADS1260-Q1 , ADS1261 , ADS1262 , ADS1263 , ADS127L01 , ADS131A02 , ADS131A04 , ADS131M04 , ADS131M06 , ADS131M08
软件按位运算函数忽略多项式值中的最高位。在对余数进行异或运算之前会将最高位移出,因此可以忽略该位。例如,CRC-16-CCITT 的多项式为 x16 + x12 + x5 + 1 (11021h),由 10001000000100001b 表示。不过,最高位被丢弃,按位运算中用于计算的值变为 1021h。
对于 8 位 CRC-8-ATM (HEC),多项式是 X8 + X2 + X + 1 (107h),由 100000111b 表示。同样地,最高位被忽略,用于按位运算的值为 7h。
以下代码函数适用于 CRC-16-CCITT,但可以轻松适应其他多项式以及长度。该函数复制硬件实现并根据 CRC 长度的大小返回一个值,该值由 crc_t 的类型定义表示。在该代码示例中,返回值是一个无符号的 16 位值。传递的参数是指向待计算数据 包的指针和数据包的长度 (字节数)。该函数通过与余数执行按位异或运算来处理每个数据字节。REMAINDER_INIT 的初始值是起始种子值,会因使用的 ADC 而异。
typedef uint16_t crc_t; // 对于 8 位 CRC,使用 uint8_t
#define POLYNOMIAL 0x1021 // CRC16-CCITT,但对于 8 位 CRC,使用 CRC-8-ATM (HEC)
// 和多项式值 0x07
#define REMAINDER_INIT 0xFFFF // 对于 ADS1xC04 和 ADS1x2U04 上的 16 位 CRC,使用 0xFFFF
// 对于 ADS1260、ADS1261 和 ADS1235 上的 8 位 CRC,使用 0xFF
// 对于 ADS124S0x、ADS114S0x、ADS1262 和 ADS1263 上的 8 位 CRC,使用 0x00
#define WIDTH (8 * sizeof(crc_t))
/**
* 计算一系列数据字节的 CRC。
*
* \详细信息:通过与所需的多项式进行异或运算来计算一系列字节的 CRC。
*
* \参数 uint8_t *data 是指向数据数组的指针。
* \参数 uint32_t length 是数据数组的长度。
*
* \返回 crc_t remainder。
*/
crc_t crcBitwise(uint8_t *data, uint32_t length)
{
crc_t remainder = REMAINDER_INIT;
uint32_t byte, bit;
// 对数据包中的每个字节
// 执行多项式长除法
for(byte = 0; byte < length; byte++)
{
remainder ^= (data[byte] << (WIDTH - 8)); // 将下一个字节取到余数中
for(bit = 8; bit > 0; bit--) // 对于余数中的每个字节
{
if(remainder & (1 << (WIDTH - 1)))
remainder = (remainder << 1) ^ POLYNOMIAL; // 如果最高位置 1,则将余数
// 左移并将其与除数异或,
else // 然后将结果存储
// 在余数中
remainder = (remainder << 1); // 如果最高位清零,则左移
// 余数
}
}
return remainder;
}
该代码示例对于确定数据的 CRC 余数很有用。对于具有传入和传出 CRC 数据完整性检查的器件,需要计算出余数。不过,如果仅针对 ADC 的传输验证数据(例如转换数据),则可将传输的 CRC 值添加到数据数组中。如果计算中包含 CRC 余数,并且 CRC 与计算值以及传输值都匹配,则余数将为零。换句话说,CRC 计算有一个重要的特性,即在匹配字节中移位会强制将 CRC 移位寄存器中的值设置为零。非零结果将指示传输错误。使用该方法则无需对传输的 CRC 和计算的 CRC 进行直接比较,从而简化验证。