5568|7

73

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

夜深了,出个解决方案,让stm32f的CRC32主流化: [复制链接]

//CopyRight:www.mcuisp.com
//版权: 单片机在线编程网
详细代码请到www.mcuisp.com下载
此帖出自stm32/stm8论坛

最新回复

                                 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 相关链接:http://www.hotpower.org/HotPower_CRC.html  详情 回复 发表于 2009-4-16 20:49
点赞 关注
 

回复
举报

65

帖子

0

TA的资源

一粒金砂(初级)

沙发
 

不错!

                                  
此帖出自stm32/stm8论坛
 
 

回复

86

帖子

0

TA的资源

一粒金砂(初级)

板凳
 

哈哈~~~McuIsp辛苦了,不过要考虑硬件成本,软件可以胡搞~~~

主流都是软件人瞎搞的~~~
相关链接:http://www.hotpower.org/HotPower_CRC.html
此帖出自stm32/stm8论坛
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

4
 

辛苦了楼上的两位

                                 一个“非主流CRC”PC端验证,整出一堆夜猫子。
此帖出自stm32/stm8论坛
 
 
 

回复

84

帖子

0

TA的资源

一粒金砂(初级)

5
 

现在流行非主流啊,哈哈

                                  
此帖出自stm32/stm8论坛
 
 
 

回复

59

帖子

0

TA的资源

一粒金砂(初级)

6
 

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

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

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


哈哈,最终证实了我的怀疑——所谓主流化CRC32是个非典应用。
此帖出自stm32/stm8论坛
 
 
 

回复

62

帖子

0

TA的资源

一粒金砂(初级)

7
 

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


如果要非典(主流)就把下面的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 
此帖出自stm32/stm8论坛
 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

8
 

CRC32运算实际根本没如此复杂~~~有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

相关链接:http://www.hotpower.org/HotPower_CRC.html
此帖出自stm32/stm8论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表