一切的STM32芯片都内置了一个硬件的CRC核算模块,能够很方便地应用到需求进行通讯的程序中,这个CRC核算模块运用常见的、在以太网中运用的核算多项式:
X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 +X8 + X7 + X5 + X4 + X2 + X + 1
写成16进制便是:0x04C11DB7
运用这个内置CRC模块的办法十分简略,既首要复位CRC模块(设置CRC_CR=0x01),这个操作把CRC核算的余数初始化为 0xFFFFFFFF;然后把要核算的数据按每32位分割为一组数据字,并逐一地把这组数据字写入CRC_DR寄存器(既下图中的绿色框),写完一切的数据字后,就能够从CRC_DR寄存器(既下图中的兰色框)读出核算的成果。
留意:尽管读写操作都是针对CRC_DR寄存器,但实际上是拜访的不同物理寄存器。
下面是用C言语描绘的这个核算模块的算法,我们能够把它放在通讯的另一端,对通讯的正确性进行验证:
DWORD dwPolynomial = 0x04c11db7;
DWORD cal_crc(DWORD *ptr, int len)
{
DWORD xbit;
DWORD data;
DWORD CRC = 0xFFFFFFFF; // init
while (len–) {
xbit = 1 << 31;
data = *ptr++;
for (int bits = 0; bits < 32; bits++) {
if (CRC & 0x80000000) {
CRC <<= 1;
CRC ^= dwPolynomial;
}
else
CRC <<= 1;
if (data & xbit)
CRC ^= dwPolynomial;
xbit >>= 1;
}
}
return CRC;
}
有几点需求阐明:
1)上述算法中变量CRC,在每次循环完毕包含了核算的余数,它一直是向左移位(既从最低位向最高位移动),溢出的数据位被丢掉。
2)输入的数据一直是以32位为单位,假如原始数据少于32位,需求在低位补0,当然也能够高位补0。
3)假定输入的DWORD数组中每个重量是按小端存储。
4)输入数据是依照最高位最早核算,最低位最终核算的次序进行。
例如:
假如输入0x44434241,内存中按字节寄存的次序是:0x41, 0x42, 0x43, 0x44。核算的成果是:0xCF534AE1
假如输入0x41424344,内存中按字节寄存的次序是:0x44, 0x43, 0x42, 0x41。核算的成果是:0xABCF9A63