首页 CRC算法

CRC算法

举报
开通vip

CRC算法CRC算法 //************************************ CRC32代码开始 ************************************ //对于51一类的8位单片机以及低端ARM,可以把这个表定位到code区…… unsigned long code CRC32Table[256] = { 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 0x076DC419L, 0x706AF48FL, 0xE963A...

CRC算法
CRC算法 //************************************ CRC32代码开始 ************************************ //对于51一类的8位单片机以及低端ARM,可以把这个表定位到code区…… unsigned long code CRC32Table[256] = { 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL }; /******************************************************************************** 函数 excel方差函数excelsd函数已知函数     2 f x m x mx m      2 1 4 2拉格朗日函数pdf函数公式下载 名称: unsigned long Calculate_CRC32(unsigned long CRC32,unsigned char *buff,unsigned lon g Len) 函数功能:计算一个数组的CRC32校验值。 输 入:ulong CRC32——当前的CRC32校验值 uchar *buff——待校验的缓冲区 ulong Len——待校验的缓冲区长度(以字节为单位) 输 出:ulong CRC32——计算结果 创 建:莫汉伟 Amo73@126.com 修 改: 备 注:参考了网络上的代码,但是和一般的算法不同,这个是可以分次计算的~ 例如:char *s1="HB_V1.0",*s2="2007-9-22"; ulong CRC32=Calculate_CRC32(0,s1,strlen(s1)); CRC32=Calculate_CRC32(CRC32,s2,strlen(s2)); …… 用在嵌入式系统中打包、解包非常合适 *********************************************************************************/ unsigned long Calculate_CRC32(unsigned long CRC32,unsigned char *buff,unsigned lon g Len) { CRC32 = ~CRC32; while(Len--) { CRC32 = CRC32Table[(CRC32 ^ *buff++) & 0xFFL] ^ (CRC32 >> 8); } return(CRC32 ^ (~0L)); } //************************************ CRC32代码结束 ************************************ CRC16程序 blove 发表于 2005-12-6 12:13:00 1 推荐 //CRC16校验在通讯中应用广泛,这里不对其理论进行讨论,只对常见的3种 //实现方法进行测试。方法1选用了一种常见的查表方法,类似的还有512字 //节、256字等查找表的,至于查找表的生成,这里也略过。 // ---------------- POPULAR POLYNOMIALS ---------------- // CCITT: x^16 + x^12 + x^5 + x^0 (0x1021) // CRC-16: x^16 + x^15 + x^2 + x^0 (0x8005) #define CRC_16_POLYNOMIALS 0x8005 // -------------------------------------------------------------- // CRC16计算方法1:使用2个256长度的校验表 // -------------------------------------------------------------- const BYTE chCRCHTalbe[] = // CRC 高位字节值表 { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 }; const BYTE chCRCLTalbe[] = // CRC 低位字节值表 { 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1 C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 }; WORD CRC16_1(BYTE* pchMsg, WORD wDataLen) { BYTE chCRCHi = 0xFF; // 高CRC字节初始化 BYTE chCRCLo = 0xFF; // 低CRC字节初始化 WORD wIndex; // CRC循环中的索引 while (wDataLen--) { // 计算CRC wIndex = chCRCLo ^ *pchMsg++ ; chCRCLo = chCRCHi ^ chCRCHTalbe[wIndex]; chCRCHi = chCRCLTalbe[wIndex] ; } return ((chCRCHi << 8) | chCRCLo) ; } // -------------------------------------------------------------- // CRC16计算方法2:使用简单的校验表 // -------------------------------------------------------------- const WORD wCRCTalbeAbs[] = { 0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400, }; WORD CRC16_2(BYTE* pchMsg, WORD wDataLen) { WORD wCRC = 0xFFFF; WORD i; BYTE chChar; for (i = 0; i < wDataLen; i++) { chChar = *pchMsg++; wCRC = wCRCTalbeAbs[(chChar ^ wCRC) & 15] ^ (wCRC >> 4); wCRC = wCRCTalbeAbs[((chChar >> 4) ^ wCRC) & 15] ^ (wCRC >> 4); } return wCRC; } // ----------------------------------------------------------------- // CRC16计算方法3:使用直接结算的方法 // ----------------------------------------------------------------- WORD CRC16_3(BYTE* pchMsg, WORD wDataLen) { BYTE i, chChar; WORD wCRC = 0xFFFF; while (wDataLen--) { chChar = *pchMsg++; chChar = ByteInvert(chChar); wCRC ^= (((WORD) chChar) << 8); for (i = 0; i < 8; i++) { if (wCRC & 0x8000) wCRC = (wCRC << 1) ^ CRC_16_POLYNOMI ALS; else wCRC <<= 1; } } wCRC = WordInvert(wCRC); return wCRC; } //试验数据: // 采用Metrowerks CodeWarrior在DSP56F80x平台上,对这3种方法 //进行了性能测试。 // ---------------------------------------------------------------- // 代码大小(字) 额外存储空间(字) 执行时间(周期数) // ---------------------------------------------------------------- // 方法1 32 512 540 // 方法2 57 16 11 20 // 方法3 142* 0 4598 // //说明:方法3的代码大小还包括字反转、字节反转程序(这里没有给出源码) // //结论:通常在存储空间没有限制的情况下,采用方法1是最好的,毕竟在 //通讯中,保障通讯速度是至关重要的。而方法2也不失为一种很好的方法, //占用空间很少。而与方法2相比,方法3似乎不占有什么优势。 /*******************结束************************/ 三种常用的CRC16校验算法的C51程序的优化 技术知识 2009-10-10 09:34:17 阅读404 评论0 字号:大中小 CRC校验又称为循环冗余校验,是数据通讯中常用的一种校验算法。它可以有效的判别出数据在传输过程中是否发生了错误,从而保障了传输的数据可靠性。 CRC校验有多种方式,如:CRC8、CRC16、CRC32等等。在实际使用中,我们经常使用CRC16校验。CRC16校验也有多种,如:1005多项式、1021多项式(CRC-ITU)等。在这里我们不讨论CRC算法是怎样产生的,而是重点落在几种算法的C51程序的优化上。 计算CRC校验时,最常用的计算方式有三种:查表、计算、查表,计算。一般来说,查表法最快,但是需要较大的空间存放表格;计算法最慢,但是代码最简洁、占用空间最小;而在既要求速度,空间又比较紧张时常用查表,计算法。 下面我们分别就这三种方法进行讨论和比较。这里以使用广泛的51单片机为例,分别用查表、计算、查表,计算三种方法计算 1021多项式(CRC-ITU)校验。原始程序都是在网上或杂志上经常能见到的,相信大家也比较熟悉了,甚至就是正在使用或已经使用过的程序。 编译平台采用 Keil C51 7.0,使用小内存模式,编译器默认的优化方式。 常用的查表法程序如下,这是网上经常能够看到的程序范例。因为篇幅关系,省略了大部分表格的 内容 财务内部控制制度的内容财务内部控制制度的内容人员招聘与配置的内容项目成本控制的内容消防安全演练内容 。 code unsigned int Crc1021Table[256] = { 0x0000, 0x1021, 0x2042, 0x3063,... 0x1ef0 }; unsigned int crc0(unsigned char *pData, unsigned char nLength) { unsigned int CRC16 = 0; while(nLength>0) { CRC16 = (CRC16 << 8 ) ^ Crc1021Table[((CRC16>>8) ^ *pData) & 0xFF]; nLength--; pData++; } return CRC16; } 编译后,函数crc0的代码为68字节,加上表格占用的512字节,一共使用了580个字节的代码空 间。 下面是常见的计算法的程序: unsigned int crc2(unsigned char *ptr,unsigned char count) { unsigned int crc =0; unsigned char i; while(count-- >0) { crc = ( crc^(((unsigned int)*ptr)<<8)); for(i=0;i<8;i++) { if(crc&0x8000) crc= ((crc<<1)^0x1021); else crc <<= 1; } ptr++; } return crc; } 下面是常见的一种查表,计算的方法: unsigned int crc4(unsigned char *ptr, unsigned char len) { unsigned int crc; unsigned char da; code unsigned int crc_ta[16]={ /* CRC余式表 */ 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7, 0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef, }; crc=0; while(len-->0) { da = ((crc/256))/16; /* 暂存CRC的高四位 */ crc <<=4; /* CRC右移4位,相当于取CRC的低12位)*/ crc ^= crc_ta[da^(*ptr/16)]; /* CRC的高4位和本字节的前半字节相加后查表*/ /*计算CRC,然后加上上一次CRC的余数 */ da = ((crc/256))/16; /* 暂存CRC的高4位 */ crc <<=4; /* CRC右移4位, 相当于CRC的低12位) */ crc ^= crc_ta[da^(*ptr&0x0f)];/* CRC的高4位和本字节的后半字节相加后查表*/ /*计算CRC,然后再加上上一次CRC的余数 */ ptr++; } return crc; } 程序优化策略:上面程序都只是给出了通用算法,并没有考虑到51单片机的特点。我们知道,51单片机是8位单片机,使用的变量类型也是8位的。如果在程序中使用8位的变量速度是最快的,比使用16位的变量代码短、效率高。在上面的程序中都使用了大量整型数类型(16位)的表格和整型数类型的变量,特别是关键的变量。如果我们不使用整型类型的表格和变量,而使用字节类型的表格和变量,就能够使程序的性能得到优化。基于这种思路,我们将原来整型的表格拆分为两个字节型(8位)的表格,即将原来表格的高低字节分别拆开,每个表格还是256个单元,这样表格的大小和顺序都没有变;原来使用16位变量计算的地方,改用8位变量计算。 修改后的查表程序如下(省略了表格的内容): code unsigned char crctableh[256]={ 0x00,0x10,0x20,0x30,... 0x0E,0x1E, }; code unsigned char crctablel[256]={ 0x00,0x21,0x42,0x63,... 0xD1,0xF0, }; unsigned int crc1(unsigned char *buf,unsigned char n) { unsigned char t; union{ unsigned char c[2]; unsigned int x; }data crc; crc.x = 0; while(n !=0) { t = crc.c[0]^*buf; crc.c[0] = crc.c[1]^crctableh[t]; crc.c[1] = crctablel[t]; n--; buf++; } return ( crc.x ); } 表面上看起来,函数crc1比crc0的源代码还长一些。但是编译后,函数crc1的目标代码实际为44 个字节,加上表格占用的512个字节,一共使用了556个字节,比函数crc0反而节约了24个字节。这两 个函数的运行对比情况见表一。 我们采用和上面相同的优化方法来优化计算法的程序,优化后的计算法程序为: unsigned int crc3(unsigned char *ptr,unsigned char count) { data unsigned char i; union{ unsigned char c[2]; unsigned int x; }data crc; crc.x=0; while(count!=0) { crc.c[0] ^= *ptr; for(i=8;i>0;i--) { if(crc.c[0]&0x70)crc.x=(crc.x<<1)&0x1021; else crc.x=crc.x<<1; } ptr++; count--; } return crc.x; } 编译后函数crc2的代码长度为76,函数crc3的代码长度为68,变化不是太大,但是执行效率是很 不一样的,具体差别见后面的表一。 优化后的查表,计算法的程序为: unsigned int crc5(unsigned char *ptr,unsigned char len) { code unsigned char crch[16]={ /* CRC余式表 */ 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70, 0x81,0x91,0xa1,0xb1,0xc1,0xd1,0xe1,0xf1, }; code unsigned char crcl[16]={ /* CRC余式表 */ 0x00,0x21,0x42,0x63,0x84,0xa5,0xc6,0xe7, 0x08,0x29,0x4a,0x6b,0x8c,0xad,0xce,0xef, }; union{ unsigned char c[2]; unsigned int x; }data crc; unsigned char t; crc.x =0; while(len!=0) { t = (crc.c[0]>>4) ^ (*ptr >>4); crc.x <<=4; crc.c[0] ^=crch[t]; crc.c[1] ^=crcl[t]; t = (crc.c[0]>>4) ^ (*ptr & 0x0F); crc.x <<=4; crc.c[0] ^=crch[t]; crc.c[1] ^=crcl[t]; ptr++; len--; } return crc.x; } 优化前后的代码长度分别为175字节和146字节(包括了32字节的表格空间)。 代码测试:仅代码长度变短是不够的,衡量优化后的程序一个重要的 标准 excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载 是看优化前后两个函数执行相同的计算量使用的时间,或者说执行的效率是否提高了。如果优化后的函数需要时间少,就说明我们优化后的函数确实提高了效率,否则就是反而降低了程序的效率,优化失败。我在 Keil C51 下编写了一个测试程序,在程序中调用了上面的六个函数,共同计算一个长度为200字节的CRC校验,并 记录 混凝土 养护记录下载土方回填监理旁站记录免费下载集备记录下载集备记录下载集备记录下载 下每个函数使用的时间。测试方法为:使用 Keil C51 的软件仿真功能(采用带计时功能的硬件仿真器也可以),在每个函数上加上断点,记录下执行到每个断点的时间,然后前后相减就得出每个函数的执行时间。仿真时使用的单片机型号为AT89C51,晶体频率为12MHz。 测试文件的源代码为: xdata unsigned char buf[200]; unsigned char i; unsigned int crc; extern unsigned int crc0(unsigned char *,unsigned char); extern unsigned int crc1(unsigned char *,unsigned char); extern unsigned int crc2(unsigned char *,unsigned char); extern unsigned int crc3(unsigned char *,unsigned char); extern unsigned int crc4(unsigned char *,unsigned char); extern unsigned int crc5(unsigned char *,unsigned char); void main(void) { for(i=0;i<200;i++) buf[i]=i+1; crc=crc0(buf,200); crc=crc1(buf,200); crc=crc2(buf,200); crc=crc3(buf,200); crc=crc4(buf,200); crc=crc5(buf,200); i=0; } 测试结果见表一: 函代码长度(字节) 执行时间(微秒) 提高效率 数 Crc68+512=580 10626 28% 查表法 0 Crc44+512=556 7622 1 Crc76 30309 13.6% 计算法 2 Crc68 26186 3 Crc175 24229 18.2% 查表,计 4 算 Crc146 19822 5 表一:三种CRC16校验算法及其优化的比较 从表中可以看出,优化后的函数执行速度都有了明显的提高,这说明我们的优化是很有效的。其实优化前后的函数区别并不大,算法都是完全一样的,只是个别地方的写法调整了一下,但是取得的效果是非常明显的。现在很多人写单片机的程序,都带有写VC或C,,的习惯,而没有考虑到51单片机的特点,从而造成了一些资源的浪费。 这三种计算方法之间的对比也很清楚,查表法使用的时间最短,查表,计算次之,计算法最长,它们的执行效率比为1:3.4:2.6,代码效率比为8.1:1:2.1(优化后的函数)。从代码长度看,查表法因 为使用了一个相对较大的表格,所以代码最长,适合于代码空间比较充足的情况;计算法没有使用任何表格,所以代码长度最小,适合于ROM空间比较小的情况。而查表,计算法从执行速度和代码长度都是处于中流,是一种很好的折衷 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 。 下面是我总结的一些C51编程优化的几个小技巧和方法: 1. 尽量使用无符号的变量; 2. 尽量使用data与idata寄存器变量;它们之间的效率顺序为data>idata>xdata ; 3. 使用最小的变量类型,能使用整型时就不要使用长整型,能使用字符型时就不要使用整型; 4. 多使用局部变量,少使用全局变量、静态变量,这样可以充分利用Keil提供的变量覆盖技术。同时局部变量也要尽量使用寄存器变量; 5. 少使用浮点数。使用浮点数需要连接浮点库,会增加大约1K的代码;而且浮点运算的速度是很慢的,没有特殊情况尽量使用定点数代替浮点数; 6. 没有必要就不要使用printf等标准输入输出函数,它会增加大约3K的代码。 7. 函数带有的参数不要太多,多了会影响效率; 8. 注意C51的特点,按照C51的特点编写程序; 9. 多用几种方法优化,比较后找出最佳方法; 10. 注意软件的写法,有时一个写法上很小的变化就会有意想不到的效果。因为Keil的优化是与上下文的程序相关的,对于不同的情况产生不同的优化。如果对比一下产生的汇编代码,就能够更加容易的找出不合理的代码,从而有针对性的优化了; 11. 不要过于依赖C51提供的优化功能,能够自己优化的地方就自己手工优化了,程序不可能完成所有的事情; 12. 不同版本的C51(特别是6.0和7.0的版本与低于6.0的版本相比)产生的优化效果可能会不同,产生的代码会不完全一样,需要特别注意; 13. 在循环中比较条件尽量与0作比较(这与51单片机的特点有关,对比一下编译产生的汇编代码就明白了),这样可以减少代码,加快速度。如: 将while( n > 10 )修改为 while( n != 0 ); 14. 在循环中比较中不要直接使用 n-- 或 n++ ,而要分开写,这样产生的代码较小。 如:while( n-- != 0)修改为 while(n != 0) { n--; ...//其他代码 } 15. 尽量不要使用太复杂的表达式,虽然这样程序简洁,但是对程序的调试不方便。 只要能充分考虑到所使用的单片机的特点,在加上一些经验和技巧,就一定可以编写出高性能的 程序来。 本文作者:邵子扬 2003年9月22日
本文档为【CRC算法】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_105949
暂无简介~
格式:doc
大小:56KB
软件:Word
页数:0
分类:互联网
上传时间:2018-02-22
浏览量:32