目前共有6篇帖子。
![]() |
/* CRC(循環冗餘校驗)在線計算: http://www.ip33.com/crc.html */
// 初始值INIT=0, 結果異或值XOROUT=0, 輸入數據不反轉, 輸出數據不反轉 #include <stdint.h> #include <stdio.h> #include <string.h> #define POLYNOMIAL_CRC7 0x89ul #define POLYNOMIAL_CRC8 0x107ul #define POLYNOMIAL_CRC16 0x11021ul #define POLYNOMIAL_CRC32 0x104c11db7ull /* 計算CRC7校驗碼 */ uint8_t calc_crc7(const void *data, int len) { const uint8_t *p = data; int i, j; uint16_t temp = 0; if (len != 0) temp = p[0] << 8; for (i = 1; i <= len; i++) { if (i != len) temp |= p[i]; for (j = 0; j < 8; j++) { if (temp & 0x8000) temp ^= POLYNOMIAL_CRC7 << 8; temp <<= 1; } } return temp >> 9; } /* 計算CRC8校驗碼 */ uint8_t calc_crc8(const void *data, int len) { const uint8_t *p = data; int i, j; uint16_t temp = 0; if (len != 0) temp = p[0] << 8; for (i = 1; i <= len; i++) { if (i != len) temp |= p[i]; for (j = 0; j < 8; j++) { if (temp & 0x8000) temp ^= POLYNOMIAL_CRC8 << 7; temp <<= 1; } } return temp >> 8; } /* 計算CRC16校驗碼 */ uint16_t calc_crc16(const void *data, int len) { const uint8_t *p = data; int i, j; uint32_t temp = 0; if (len & 1) { printf("%s: data size %d is odd!\n", __FUNCTION__, len); len--; // 不允許出現奇數長度 } if (len != 0) temp = (p[0] << 24) | (p[1] << 16); // 填充前二分之一 if (len > 2) temp |= p[2] << 8; // 填充到四分之三 for (i = 3; i <= len + 2; i++) { if (i < len) temp |= p[i]; // 每次都填充最後四分之一的空間 // 從左數第0~7位計算到左數第16~23位 // 當j=0時是從左數第0位計算到第16位, 共計17位 // 當j=1時是從左數第1位計算到第17位, 共計17位 // ... // 當j=7時是從左數第7位計算到第23位, 共計17位 for (j = 0; j < 8; j++) { if (temp & 0x80000000) temp ^= POLYNOMIAL_CRC16 << 15; temp <<= 1; } } return temp >> 16; } /* 計算CRC32校驗碼 */ uint32_t calc_crc32(const void *data, int len) { const uint8_t *p = data; int i, j; uint64_t temp = 0; if (len & 3) { printf("%s: data size %d is not a multiple of 4\n", __FUNCTION__, len); len -= (len & 3); } if (len != 0) temp = ((uint64_t)p[0] << 56) | ((uint64_t)p[1] << 48) | ((uint64_t)p[2] << 40) | ((uint64_t)p[3] << 32); // 填充前二分之一 if (len > 6) temp |= ((uint64_t)p[4] << 24) | ((uint64_t)p[5] << 16) | ((uint64_t)p[6] << 8); // 填充到八分之七 for (i = 7; i <= len + 6; i++) { if (i < len) temp |= p[i]; // 每次都填充最後八分之一的空間 // 從左數第0~7位計算到左數第32~39位 // 當j=0時是從左數第0位計算到第32位, 共計33位 // 當j=1時是從左數第1位計算到第33位, 共計33位 // ... // 當j=7時是從左數第7位計算到第39位, 共計33位 for (j = 0; j < 8; j++) { if (temp & 0x8000000000000000) temp ^= POLYNOMIAL_CRC32 << 31; temp <<= 1; } } return temp >> 32; } void main() { char *str = "https://zh.purasbar.com/"; int i, n; n = strlen(str); for (i = 0; i <= n; i += 4) printf("len=%d, crc7=0x%02x, crc8=0x%02x, crc16=0x%04x, crc32=0x%08x\n", i, calc_crc7(str, i), calc_crc8(str, i), calc_crc16(str, i), calc_crc32(str, i)); } |
![]() |
程序運行結果:
len=0, crc7=0x00, crc8=0x00, crc16=0x0000, crc32=0x00000000 len=4, crc7=0x49, crc8=0x88, crc16=0x62d3, crc32=0x41e278d5 len=8, crc7=0x35, crc8=0x4f, crc16=0x90e6, crc32=0xe83f2f79 len=12, crc7=0x50, crc8=0x5c, crc16=0x9764, crc32=0x7392a791 len=16, crc7=0x7b, crc8=0x67, crc16=0xeeae, crc32=0x8bb08019 len=20, crc7=0x21, crc8=0xa2, crc16=0x335b, crc32=0xa70b55c8 len=24, crc7=0x3d, crc8=0xef, crc16=0xc4a5, crc32=0x20087a6a ———————————————— 版權聲明:本文為CSDN博主「巨大八爪魚」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本聲明。 原文連結:https://blog.csdn.net/ZLK1214/article/details/157174177 |
![]() |
四個計算函數長得非常像,就只是裡面的數字不一樣。
|
![]() |
#include <stdint.h>
#include <stdio.h> #include <string.h> #define INIT_CRC32 0xffffffffull #define POLYNOMIAL_CRC32 0x104c11db7ull uint8_t invert(uint8_t data) { int i; uint8_t result = 0; for (i = 0; i < 8; i++) { result <<= 1; if (data & 1) result |= 1; data >>= 1; } return result; } uint32_t invert32(uint32_t data) { uint32_t result; result = invert((data >> 24) & 0xff); result |= invert((data >> 16) & 0xff) << 8; result |= invert((data >> 8) & 0xff) << 16; result |= invert(data & 0xff) << 24; return result; } /* 計算CRC32校驗碼(初始值0xffffffff、結果異或值0xffffffff、輸入數據反轉、輸出數據反轉) */ uint32_t calc_crc32_inv(const void *data, int len) { const uint8_t *p = data; int i, j; uint64_t temp = INIT_CRC32 << 32; if (len & 3) { printf("%s: data size %d is not a multiple of 4\n", __FUNCTION__, len); len -= (len & 3); } if (len != 0) temp ^= ((uint64_t)invert(p[0]) << 56) | ((uint64_t)invert(p[1]) << 48) | ((uint64_t)invert(p[2]) << 40) | ((uint64_t)invert(p[3]) << 32); // 填充前二分之一 if (len > 6) temp |= ((uint64_t)invert(p[4]) << 24) | ((uint64_t)invert(p[5]) << 16) | ((uint64_t)invert(p[6]) << 8); // 填充到八分之七 for (i = 7; i <= len + 6; i++) { if (i < len) temp |= invert(p[i]); // 每次都填充最後八分之一的空間 // 從左數第0~7位計算到左數第32~39位 // 當j=0時是從左數第0位計算到第32位, 共計33位 // 當j=1時是從左數第1位計算到第33位, 共計33位 // ... // 當j=7時是從左數第7位計算到第39位, 共計33位 for (j = 0; j < 8; j++) { if (temp & 0x8000000000000000) temp ^= POLYNOMIAL_CRC32 << 31; temp <<= 1; } } return invert32(temp >> 32) ^ 0xffffffff; } void main() { char *str = "https://zh.purasbar.com/"; int i, n; n = strlen(str); for (i = 0; i <= n; i += 4) printf("len=%d, crc32_inv=0x%08x\n", i, calc_crc32_inv(str, i)); } 程序運行結果: |
![]() |
有的單片機不支持uint64_t類型,無法運行calc_crc32函數和calc_crc32_inv函數。
注意到 if (temp & 0x8000000000000000) temp ^= POLYNOMIAL_CRC32 << 31; temp <<= 1; 也就是 if (temp & 0x8000000000000000) { temp ^= POLYNOMIAL_CRC32 << 31; temp <<= 1; } else temp <<= 1; 相當於 if (temp & 0x8000000000000000) { temp <<= 1; temp ^= POLYNOMIAL_CRC32 << 32; } else temp <<= 1; 這樣的話,我們就可以把一個uint64_t temp變量拆成兩個uint32_t變量,使calc_crc32函數和calc_crc32_inv函數可以在不支持uint64_t類型的平台上運行。 ———————————————— 版權聲明:本文為CSDN博主「巨大八爪魚」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本聲明。 原文連結:https://blog.csdn.net/ZLK1214/article/details/157174177 |
![]() |
#include <stdint.h>
#include <stdio.h> #include <string.h> #define POLYNOMIAL_CRC32 0x4c11db7 /* 計算CRC32校驗碼 */ uint32_t calc_crc32(const void *data, int len) { const uint8_t *p = data; int i, j; uint32_t temp = 0; uint32_t temp2 = 0; uint32_t msb; // 填充前二分之一 if (len > 0) temp |= p[0] << 24; if (len > 1) temp |= p[1] << 16; if (len > 2) temp |= p[2] << 8; if (len > 3) temp |= p[3]; // 填充到八分之七 if (len > 4) temp2 |= p[4] << 24; if (len > 5) temp2 |= p[5] << 16; if (len > 6) temp2 |= p[6] << 8; for (i = 7; i <= len + 6; i++) { if (i < len) temp2 |= p[i]; // 每次都填充最後八分之一的空間 // 從左數第0~7位計算到左數第32~39位 // 當j=0時是從左數第0位計算到第32位, 共計33位 // 當j=1時是從左數第1位計算到第33位, 共計33位 // ... // 當j=7時是從左數第7位計算到第39位, 共計33位 for (j = 0; j < 8; j++) { msb = (temp & 0x80000000); temp <<= 1; if (temp2 & 0x80000000) temp |= 1; temp2 <<= 1; if (msb) temp ^= POLYNOMIAL_CRC32; } } return temp; } uint8_t invert(uint8_t data) { int i; uint8_t result = 0; for (i = 0; i < 8; i++) { result <<= 1; if (data & 1) result |= 1; data >>= 1; } return result; } uint32_t invert32(uint32_t data) { uint32_t result; result = invert((data >> 24) & 0xff); result |= invert((data >> 16) & 0xff) << 8; result |= invert((data >> 8) & 0xff) << 16; result |= invert(data & 0xff) << 24; return result; } /* 計算CRC32校驗碼(初始值0xffffffff、結果異或值0xffffffff、輸入數據反轉、輸出數據反轉) */ uint32_t calc_crc32_inv(const void *data, int len) { const uint8_t *p = data; int i, j; uint32_t temp = 0xffffffff; uint32_t temp2 = 0; uint32_t msb; // 填充前二分之一 if (len > 0) temp ^= invert(p[0]) << 24; if (len > 1) temp ^= invert(p[1]) << 16; if (len > 2) temp ^= invert(p[2]) << 8; if (len > 3) temp ^= invert(p[3]); // 填充到八分之七 if (len > 4) temp2 |= invert(p[4]) << 24; if (len > 5) temp2 |= invert(p[5]) << 16; if (len > 6) temp2 |= invert(p[6]) << 8; for (i = 7; i <= len + 6; i++) { if (i < len) temp2 |= invert(p[i]); // 每次都填充最後八分之一的空間 // 從左數第0~7位計算到左數第32~39位 // 當j=0時是從左數第0位計算到第32位, 共計33位 // 當j=1時是從左數第1位計算到第33位, 共計33位 // ... // 當j=7時是從左數第7位計算到第39位, 共計33位 for (j = 0; j < 8; j++) { msb = (temp & 0x80000000); temp <<= 1; if (temp2 & 0x80000000) temp |= 1; temp2 <<= 1; if (msb) temp ^= POLYNOMIAL_CRC32; } } return invert32(temp) ^ 0xffffffff; } void main() { char *str = "https://zh.purasbar.com/"; int i, n; n = strlen(str); for (i = 0; i <= n; i++) printf("len=%d, crc32=0x%08x, crc32_inv=0x%08x\n", i, calc_crc32(str, i), calc_crc32_inv(str, i)); } 程序運行結果: |