原创 CRC32运算实际根本没如此复杂~~~有2种方法~~~

2009-4-16 21:15 5973 6 5 分类: MCU/ 嵌入式
McuIsp 发表于 2009-4-15 23:24 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

楼主: 夜深了,出个解决方案,让stm32f的CRC32主流化:


//CopyRight:www.mcuisp.com
//版权: 单片机在线编程网
详细代码请到www.mcuisp.com下载

hotpower 发表于 2009-4-16 08:00 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

6楼: 站在硬件设计师的角度来分析,“非主流”乃“裸奔”也~~~


爽~~~

CRC-1x + 1 (most hardware; also known as parity bit)0x1 or 0x1 (0x1)
CRC-4-ITUx4 + x + 1 (ITU G.704, p. 12)0x3 or 0xC (0x9)
CRC-5-ITUx5 + x4 + x2 + 1 (ITU G.704, p. 9)0x15 or 0x15 (0x1A)
CRC-5-USBx5 + x2 + 1 (USB token packets)0x05 or 0x14 (0x12)
CRC-6-ITUx6 + x + 1 (ITU G.704, p. 3)0x03 or 0x30 (0x21)
CRC-7x7 + x3 + 1 (telecom systems, MMC,SD)0x09 or 0x48 (0x44)
CRC-8-ATMx8 + x2 + x + 1 (ATM HEC)0x07 or 0xE0 (0x83)
CRC-8-CCITTx8 + x7 + x3 + x2 + 1 (1-Wire bus)0x8D or 0xB1 (0xC6)
CRC-8-Dallas/Maximx8 + x5 + x4 + 1 (1-Wire bus)0x31 or 0x8C (0x98)
CRC-8x8 + x7 + x6 + x4 + x2 + 10xD5 or 0xAB (0xEA [5])
CRC-8-SAE J1850x8 + x4 + x3 + x2 + 10x1D or 0xB8 (0x8E)
CRC-10x10 + x9 + x5 + x4 + x + 10x233 or 0x331 (0x319)
CRC-11x11 + x9 + x8 + x7 + x2 + 1 (FlexRay)0x385 or 0x50E (0x5C2)
CRC-12x12 + x11 + x3 + x2 + x + 1 (telecom systems, [8][9] )0x80F or 0xF01 (0xC07)
CRC-15-CANx15 + x14 + x10 + x8 + x7 + x4 + x3 + 10x4599 or 0x4CD1 (0x62CC)
CRC-16-FletcherNot a CRC; see Fletcher's checksumUsed in Adler-32 A & B CRCs
CRC-16-CCITTx16 + x12 + x5 + 1 (G.hn PHY headers, 802.15.4, X.25, V.41, CDMA, Bluetooth, XMODEM, HDLC,PPP, IrDA, BACnet; known as CRC-CCITT, MMC,SD)0x1021 or 0x8408 (0x8810 [5])
CRC-16-DNPx16 + x13 + x12 + x11 + x10 + x8 + x6 + x5 + x2 + 1 (DNP, IEC 870, M-Bus)0x3D65 or 0xA6BC (0x9EB2)
CRC-16-IBMx16 + x15 + x2 + 1 (SDLC, USB, many others; also known as CRC-16)0x8005 or 0xA001 (0xC002)
CRC-24-Radix-64x24 + x23 + x18 + x17 + x14 + x11 + x10 + x7 + x6 + x5 + x4 + x3 + x + 1 (FlexRay)0x864CFB or 0xDF3261 (0xC3267D)
CRC-30x30 + x29 + x21 + x20 + x15 + x13 + x12 + x11 + x8 + x7 + x6 + x2 + x + 1 (CDMA)0x2030B9C7 or 0x38E74301 (0x30185CE3)
CRC-32-AdlerNot a CRC; see Adler-32See Adler-32
CRC-32-IEEE 802.3x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 (V.42, MPEG-2, PNG [10], POSIX cksum)0x04C11DB7 or 0xEDB88320 (0x82608EDB [7])
CRC-32C (Castagnoli)x32 + x28 + x27 + x26 + x25 + x23 + x22 + x20 + x19 + x18 + x14 + x13 + x11 + x10 + x9 + x8 + x6 + 1 (G.hn payload)0x1EDC6F41 or 0x82F63B78 (0x8F6E37A0 [7])
CRC-32K (Koopman)x32 + x30 + x29 + x28 + x26 + x20 + x19 + x17 + x16 + x15 + x11 + x10 + x7 + x6 + x4 + x2 + x + 10x741B8CD7 or 0xEB31D82E (0xBA0DC66B [7])
CRC-64-ISOx64 + x4 + x3 + x + 1 (HDLC — ISO 3309)0x000000000000001B or 0xD800000000000000 (0x800000000000000D)
CRC-64-ECMA-182x64 + x62 + x57 + x55 + x54 + x53 + x52 + x47 + x46 + x45 + x40 + x39 + x38 + x37 + x35 + x33 + x32 + x31 + x29 + x27 + x24 + x23 + x22 + x21 + x19 + x17 + x13 + x12 + x10 + x9 + x7 + x4 + x + 1 (as described in ECMA-182 p.51)0x42F0E1EBA9EA3693 or 0xC96C5795D7870F42 (0xA17870F5D4F51B49)


香水城 发表于 2009-4-16 08:27 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

7楼: 哈哈,楼主这个CRC32主流化似乎是个非典应用


看看这个区别,最主要的是第1、2点:

//可以看出,stm32f与主流计算工具有三点差别:
//1、输入位序颠倒,只需数据输入前颠倒位序
//2、输出位序颠倒,获得结果后再颠倒回来。
//3、异或0xffffffff


哈哈,最终证实了我的怀疑——所谓主流化CRC32是个非典应用。

Netjob 发表于 2009-4-16 11:06 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

8楼: 那么 就将【非典】 进行到底!



如果要非典(主流)就把下面的FALSE 设为TRUE
要ST的就都设为FALSE
ST的CRC 最后还要异或FINAL_XOR_VALUE
我这样改改:


typedef unsigned long  crc_16_32;

#define CRC_NAME           "CRC-32"
#define POLYNOMIAL         0x04C11DB7L
#define INITIAL_REMAINDER  0xFFFFFFFF
#define FINAL_XOR_VALUE    0xFFFFFFFF
#define REFLECT_DATA       FALSE
#define REFLECT_REMAINDER  FALSE




#define WIDTH    (8 * sizeof(crc_16_32))

#define TOPBIT   ((crc_16_32)1 << (WIDTH - 1))

#if (REFLECT_DATA == TRUE)

#undef  REFLECT_DATA
//#define REFLECT_DATA(X)     (crc_16_32)reflect((X), 8))

//#define REFLECT_DATA(X)        ((crc_16_32)reflect((X), WIDTH))
#define REFLECT_DATA(X)            ((crc_16_32)revbit(X))

#define reflect_data(X)    (crc_16_32)revbit(X))
//#define reflect_data(X)        ((crc_16_32)reflect((X),WIDTH))

#else

#undef  REFLECT_DATA
#define REFLECT_DATA(X)            (X)
#define reflect_data(X)            (X)
#endif

#if (REFLECT_REMAINDER == TRUE)
#undef  REFLECT_REMAINDER

//#define REFLECT_REMAINDER(X)    ((crc_16_32)reflect((X), WIDTH) ^ FINAL_XOR_VALUE)
#define REFLECT_REMAINDER(X)    ((crc_16_32)revbit(X)^FINAL_XOR_VALUE)

#define reflect_rmder(X)    ((crc_16_32)revbit(X)^FINAL_XOR_VALUE)
//#define reflect_rmder(X)    ((crc_16_32)reflect((X), WIDTH) ^ FINAL_XOR_VALUE)

#else
#undef  REFLECT_REMAINDER
#define REFLECT_REMAINDER(X)  (X)
#define reflect_rmder(X)       (X)
#endif

unsigned long reflect(unsigned long data, unsigned char nBits)
{
  return(revbit(data));//网上有reflect的通用代码
};
crc_16_32 revbit(crc_16_32 data)
{
  asm("rbit r0,r0");
  return data;
};

crc_16_32 cal_crc(crc_16_32 *ptr, int len)
{   
    crc_16_32    xbit;
    crc_16_32    data;
    crc_16_32    CRC = INITIAL_REMAINDER;
    while (len--)
    {
        xbit = (crc_16_32)1 << 31;//
        data = *ptr++;// 下一个数
//      data=revbit(data);//输入位序颠倒一下
        data=reflect_data(data);        
        for ( int bits = 0; bits < 32; bits++)// 主流是从( 32 到 0 )
        {
            if (CRC & TOPBIT)
            {
                CRC = (CRC<<1)^POLYNOMIAL;
            }
            else
            {             
                CRC = (CRC<<1);
            }
            if (data & xbit)
            {
              CRC ^= POLYNOMIAL;
            }
            xbit >>= 1;
        }//end bit        
    }        
//    CRC=revbit(CRC);
//    CRC^=0xFFFFFFFF;//输出位序颠倒一下
//    return(CRC);
   return (reflect_rmder(CRC));    
   
}//end sub

hotpower 发表于 2009-4-16 20:49 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

9楼: 实际根本没如此复杂~~~有2种方法~~~


1.输入数据crcdword移动,菜农喜欢的方法,它实际与i的位置无关
function crc32l(crcdword)
{
var i,temp;
  for(i = 0; i < 32; i++){
    temp = crcvalue ^ crcdword;//记录方向端点(D31)
    crcvalue <<= 1;//前面已记录,此时不管三七二十一左移1次
    crcdword <<= 1;//此句可以在以下任何地方~~~
    if(temp & 0x80000000) {//方向端点跳变,需要变换,实际“左环移”
      crcvalue ^= crcval;//0x04C11DB7,注意D0肯定为1~~~
    }
//    crcdword <<= 1;//上面的写法可以看出它实际和crcvalue一起移动的。
  }
}

2.输入数据crcdword不移动,这估计是大多数人想到的~~~
  从上例可以看出,crcvalue和crcdword是一同移动的~~~
  它永远记录方向端点(D31),故和位置i无关
  这样就可以动态跟踪位置i的跳变

function crc32l(crcdword)
{
var i,temp;
  temp = crcvalue;//暂存CRC,应为它必须移动,但temp可以不移动
  for(i = 31; i >= 0; i--){
    crcvalue <<= 1;//不管三七二十一左移1次
//下面(1 << i)实际可以用xbit= 1<< 31;然后xbit>>=1,这里主要表现与位置i有关
    if((temp ^ crcdword) & (1 << i)) {//判断记录方向可变端点(D31~D0)
      crcvalue ^= crcval;//0x04C11DB7,注意D0肯定为1~~~
    }
  }
}

可以看出例2在硬件上实现比例1难度增加,假若硬件是33位,那么程序可简化为:

function crc32l(crcdword)
{
var i;//省去temp;//i实际是32个脉冲时钟
  for(i = 32; i > 0; i--){//33位计数器,倒数肯定简单(与0比较)
    crcvalue <<= 1;//不管三七二十一左移1次,因为是33位的寄存器~~~
    crcdword <<= 1;//不管三七二十一左移1次,因为是33位的寄存器~~~
    if((crcvalue ^ crcdword) >= 0x100000000) {//记录方向端点(D32),硬件只需检测D32即可
      crcvalue ^= crcval;//0x04C11DB7,注意D0肯定为1~~~
    }
  }
}//出口是32位的CRC结果crcvalue,D32不输出,只输出D31~D0
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
6
关闭 站长推荐上一条 /3 下一条