c. CRC通用计算程序
由于STM32的硬件CRC计算不能满足SD卡及其标准所规定的CRC数据,本文讨论软件实现通用的CRC计算,以及SD使用到的CRC7和CRC16的数据。
这里的程序并非最简化的程序,实用化之前可以进行优化。
CRC的计算有两个输入量,被校验数据,和多项式
被校验数据描述为字节的起始地址和长度
严格的来讲,CRC是按位计算的bit,而以字节为输入是比较通用和符合效率的,如果以多项式的长度作为输入会增加算法的难度
unsigned int crc_common(unsigned char* dat, unsigned int cnt, unsigned int plnm, unsigned int dgt)
多项式描述为值和值的长度
unsigned int crc_common(unsigned char* dat, unsigned int cnt, unsigned int plnm, unsigned int dgt)
计算每一字节并与以前的结果叠加
while (cc < cnt) {
cbr = crc_byte((cbr<<8)|dat[cc], plnm, dgt);
cc++;
}
在最后需要补足与多项式长度相同的0,长度大于8位,一个字节时重复字节计算
while (cc > 8) {
cbr = crc_byte(cbr<<8, plnm, dgt);
cc -= 8;
}
cbr = crc_byte(cbr<<cc, plnm, dgt);
crc_byte 计算每个附加字节的crc结果
计算CRC结果的最大值
mxw = (0x1 << dgt) - 1;
确定数据的最高位
while ((cwd & crcc)==0) {
crcc >>= 1;
crcp >>= 1;
}
XOR计算
cwd ^= crcp;
crc7和crc16的定义
这里使用的多项式加入了最高位以方便计算
#define crc7pm 0x89
#define crc16pm 0x11021
unsigned char crc7(unsigned char* dat, unsigned int cnt) {
return crc_common(dat, cnt, crc7pm, 7);
}
unsigned int crc16(unsigned char* dat, unsigned int cnt) {
return crc_common(dat, cnt, crc16pm, 16);
}