ios android 小程序 蓝牙 CRC16_MODBUS
安卓 MODBUS
public static int CRC16_MODBUS(byte[] source, int offset, int length) {int wCRCin = 0xFFFF;// Integer.reverse(0x8005) >>> 16int wCPoly = 0xA001;for (int i = offset, cnt = offset + length; i < cnt; i++) {wCRCin ^= ((int) source[i] & 0x00FF);for (int j = 0; j < 8; j++) {if ((wCRCin & 0x0001) != 0) {wCRCin >>= 1;wCRCin ^= wCPoly;} else {wCRCin >>= 1;}}}return wCRCin ^= 0x0000;}
调用:
int crc16 = CRC16_MODBUS(data,0,data.length-3);
参数 1. 数组 2.数组的第几个开始参与MODBUS 3 .数组的第几个到第几个参与MODBUS
苹果 MODBUS
//const uint8_t *data 是结构体地址。
uint16_t CRC16ModbusByteCalc(const uint8_t *data, uint8_t length) {uint16_t tmp = 0xFFFF;uint16_t ret1;for (int n = 0; n < length; n++) {tmp = data[n] ^ tmp;for (int i = 0; i < 8; i++) {if (tmp & 0x01) {tmp = tmp >> 1;tmp = tmp ^ 0xA001;} else {tmp = tmp >> 1;}}}/* CRC校验后的值 */printf("CRC校验结果为: %X \n",tmp);/* 如需要:将CRC校验小端输出 */ret1 = tmp >> 8;ret1 = ret1 | (tmp << 8);printf("CRC校验结果小端: %X \n",ret1);return (tmp);
}//求 CRC 数组的和
unsigned short CRC16(unsigned char *puchMsg,unsigned short usDataLen )
{
unsigned char uchCRCHi = 0xFF ; /* 高CRC字节初始化 */
unsigned char uchCRCLo = 0xFF ; /* 低CRC 字节初始化 */
unsigned uIndex ; /* CRC循环中的索引 */
uIndex = 0x01 ^ 0x02;
while (usDataLen--) /* 传输消息缓冲区 */
{uIndex = uchCRCHi ^ (*puchMsg++); /* 计算CRC *///(*puchMsg)++;uchCRCHi = uchCRCLo ^ (auchCRCHi[uIndex]);uchCRCLo = auchCRCLo[uIndex];
}
// 左移前uchCRCHi先转换为unsigned short,否则就变成0了。return (uchCRCHi << 8 | uchCRCLo) ;
// return (unsigned short)((unsigned short)uchCRCHi << 8 | uchCRCLo) ;
}short a= CRC16(&struct,17);
调用
int16_t reValue1 = CRC16ModbusByteCalc(&struct, 14);
安卓其它CRC加密 比如 USB CRC16_MAXIM
package com.sbas.utils;public class CrcUtils {public static class CRC8 {public static int CRC8(byte[] source, int offset, int length) {int wCRCin = 0x00;int wCPoly = 0x07;for (int i = offset, cnt = offset + length; i < cnt; i++) {for (int j = 0; j < 8; j++) {boolean bit = ((source[i] >> (7 - j) & 1) == 1);boolean c07 = ((wCRCin >> 7 & 1) == 1);wCRCin <<= 1;if (c07 ^ bit)wCRCin ^= wCPoly;}}wCRCin &= 0xFF;return wCRCin ^= 0x00;}public static int CRC8_DARC(byte[] source, int offset, int length) {int wCRCin = 0x00;// Integer.reverse(0x39) >>> 24int wCPoly = 0x9C;for (int i = offset, cnt = offset + length; i < cnt; i++) {wCRCin ^= ((long) source[i] & 0xFF);for (int j = 0; j < 8; j++) {if ((wCRCin & 0x01) != 0) {wCRCin >>= 1;wCRCin ^= wCPoly;} else {wCRCin >>= 1;}}}return wCRCin ^= 0x00;}public static int CRC8_ITU(byte[] source, int offset, int length) {int wCRCin = 0x00;int wCPoly = 0x07;for (int i = offset, cnt = offset + length; i < cnt; i++) {for (int j = 0; j < 8; j++) {boolean bit = ((source[i] >> (7 - j) & 1) == 1);boolean c07 = ((wCRCin >> 7 & 1) == 1);wCRCin <<= 1;if (c07 ^ bit)wCRCin ^= wCPoly;}}wCRCin &= 0xFF;return wCRCin ^= 0x55;}public static int CRC8_MAXIM(byte[] source, int offset, int length) {int wCRCin = 0x00;// Integer.reverse(0x31) >>> 24int wCPoly = 0x8C;for (int i = offset, cnt = offset + length; i < cnt; i++) {wCRCin ^= ((long) source[i] & 0xFF);for (int j = 0; j < 8; j++) {if ((wCRCin & 0x01) != 0) {wCRCin >>= 1;wCRCin ^= wCPoly;} else {wCRCin >>= 1;}}}return wCRCin ^= 0x00;}public static int CRC8_ROHC(byte[] source, int offset, int length) {int wCRCin = 0xFF;// Integer.reverse(0x07) >>> 24int wCPoly = 0xE0;for (int i = offset, cnt = offset + length; i < cnt; i++) {wCRCin ^= ((long) source[i] & 0xFF);for (int j = 0; j < 8; j++) {if ((wCRCin & 0x01) != 0) {wCRCin >>= 1;wCRCin ^= wCPoly;} else {wCRCin >>= 1;}}}return wCRCin ^= 0x00;}}public static class CRC16 {public static int CRC16_IBM(byte[] source, int offset, int length) {int wCRCin = 0x0000;// Integer.reverse(0x8005) >>> 16int wCPoly = 0xA001;for (int i = offset, cnt = offset + length; i < cnt; i++) {wCRCin ^= ((int) source[i] & 0x00FF);for (int j = 0; j < 8; j++) {if ((wCRCin & 0x0001) != 0) {wCRCin >>= 1;wCRCin ^= wCPoly;} else {wCRCin >>= 1;}}}return wCRCin ^= 0x0000;}public static int CRC16_CCITT(byte[] source, int offset, int length) {int wCRCin = 0x0000;// Integer.reverse(0x1021) >>> 16int wCPoly = 0x8408;for (int i = offset, cnt = offset + length; i < cnt; i++) {wCRCin ^= ((int) source[i] & 0x00FF);for (int j = 0; j < 8; j++) {if ((wCRCin & 0x0001) != 0) {wCRCin >>= 1;wCRCin ^= wCPoly;} else {wCRCin >>= 1;}}}return wCRCin ^= 0x0000;}public static int CRC16_CCITT_FALSE(byte[] source, int offset, int length) {int wCRCin = 0xFFFF;int wCPoly = 0x1021;for (int i = offset, cnt = offset + length; i < cnt; i++) {for (int j = 0; j < 8; j++) {boolean bit = ((source[i] >> (7 - j) & 1) == 1);boolean c15 = ((wCRCin >> 15 & 1) == 1);wCRCin <<= 1;if (c15 ^ bit)wCRCin ^= wCPoly;}}wCRCin &= 0xFFFF;return wCRCin ^= 0x0000;}public static int CRC16_DECT_R(byte[] source, int offset, int length) {int wCRCin = 0x0000;int wCPoly = 0x0589;for (int i = offset, cnt = offset + length; i < cnt; i++) {for (int j = 0; j < 8; j++) {boolean bit = ((source[i] >> (7 - j) & 1) == 1);boolean c15 = ((wCRCin >> 15 & 1) == 1);wCRCin <<= 1;if (c15 ^ bit)wCRCin ^= wCPoly;}}wCRCin &= 0xFFFF;return wCRCin ^= 0x0001;}public static int CRC16_DECT_X(byte[] source, int offset, int length) {int wCRCin = 0x0000;int wCPoly = 0x0589;for (int i = offset, cnt = offset + length; i < cnt; i++) {for (int j = 0; j < 8; j++) {boolean bit = ((source[i] >> (7 - j) & 1) == 1);boolean c15 = ((wCRCin >> 15 & 1) == 1);wCRCin <<= 1;if (c15 ^ bit)wCRCin ^= wCPoly;}}wCRCin &= 0xFFFF;return wCRCin ^= 0x0000;}public static int CRC16_DNP(byte[] source, int offset, int length) {int wCRCin = 0x0000;// Integer.reverse(0x3D65) >>> 16int wCPoly = 0xA6BC;for (int i = offset, cnt = offset + length; i < cnt; i++) {wCRCin ^= ((int) source[i] & 0x00FF);for (int j = 0; j < 8; j++) {if ((wCRCin & 0x0001) != 0) {wCRCin >>= 1;wCRCin ^= wCPoly;} else {wCRCin >>= 1;}}}return wCRCin ^= 0xFFFF;}public static int CRC16_GENIBUS(byte[] source, int offset, int length) {int wCRCin = 0xFFFF;int wCPoly = 0x1021;for (int i = offset, cnt = offset + length; i < cnt; i++) {for (int j = 0; j < 8; j++) {boolean bit = ((source[i] >> (7 - j) & 1) == 1);boolean c15 = ((wCRCin >> 15 & 1) == 1);wCRCin <<= 1;if (c15 ^ bit)wCRCin ^= wCPoly;}}wCRCin &= 0xFFFF;return wCRCin ^= 0xFFFF;}public static int CRC16_MAXIM(byte[] source, int offset, int length) {int wCRCin = 0x0000;// Integer.reverse(0x8005) >>> 16int wCPoly = 0xA001;for (int i = offset, cnt = offset + length; i < cnt; i++) {wCRCin ^= ((int) source[i] & 0x00FF);for (int j = 0; j < 8; j++) {if ((wCRCin & 0x0001) != 0) {wCRCin >>= 1;wCRCin ^= wCPoly;} else {wCRCin >>= 1;}}}return wCRCin ^= 0xFFFF;}public static int CRC16_MODBUS(byte[] source, int offset, int length) {int wCRCin = 0xFFFF;// Integer.reverse(0x8005) >>> 16int wCPoly = 0xA001;for (int i = offset, cnt = offset + length; i < cnt; i++) {wCRCin ^= ((int) source[i] & 0x00FF);for (int j = 0; j < 8; j++) {if ((wCRCin & 0x0001) != 0) {wCRCin >>= 1;wCRCin ^= wCPoly;} else {wCRCin >>= 1;}}}return wCRCin ^= 0x0000;}public static int CRC16_USB(byte[] source, int offset, int length) {int wCRCin = 0xFFFF;// Integer.reverse(0x8005) >>> 16int wCPoly = 0xA001;for (int i = offset, cnt = offset + length; i < cnt; i++) {wCRCin ^= ((int) source[i] & 0x00FF);for (int j = 0; j < 8; j++) {if ((wCRCin & 0x0001) != 0) {wCRCin >>= 1;wCRCin ^= wCPoly;} else {wCRCin >>= 1;}}}return wCRCin ^= 0xFFFF;}public static int CRC16_X25(byte[] source, int offset, int length) {int wCRCin = 0xFFFF;// Integer.reverse(0x1021) >>> 16int wCPoly = 0x8408;for (int i = offset, cnt = offset + length; i < cnt; i++) {wCRCin ^= ((int) source[i] & 0x00FF);for (int j = 0; j < 8; j++) {if ((wCRCin & 0x0001) != 0) {wCRCin >>= 1;wCRCin ^= wCPoly;} else {wCRCin >>= 1;}}}return wCRCin ^= 0xFFFF;}public static int CRC16_XMODEM(byte[] source, int offset, int length) {int wCRCin = 0x0000;int wCPoly = 0x1021;for (int i = offset, cnt = offset + length; i < cnt; i++) {for (int j = 0; j < 8; j++) {boolean bit = ((source[i] >> (7 - j) & 1) == 1);boolean c15 = ((wCRCin >> 15 & 1) == 1);wCRCin <<= 1;if (c15 ^ bit)wCRCin ^= wCPoly;}}wCRCin &= 0xFFFF;return wCRCin ^= 0x0000;}}public static class CRC32 {public static long CRC32(byte[] source, int offset, int length) {long wCRCin = 0xFFFFFFFFL;// Long.reverse(0x04C11DB7L) >>> 32long wCPoly = 0xEDB88320L;for (int i = offset, cnt = offset + length; i < cnt; i++) {wCRCin ^= ((long) source[i] & 0x000000FFL);for (int j = 0; j < 8; j++) {if ((wCRCin & 0x00000001L) != 0) {wCRCin >>= 1;wCRCin ^= wCPoly;} else {wCRCin >>= 1;}}}return wCRCin ^= 0xFFFFFFFFL;}public static long CRC32_B(byte[] source, int offset, int length) {long wCRCin = 0xFFFFFFFFL;long wCPoly = 0x04C11DB7L;for (int i = offset, cnt = offset + length; i < cnt; i++) {for (int j = 0; j < 8; j++) {boolean bit = ((source[i] >> (7 - j) & 1) == 1);boolean c31 = ((wCRCin >> 31 & 1) == 1);wCRCin <<= 1;if (c31 ^ bit) {wCRCin ^= wCPoly;}}}wCRCin &= 0xFFFFFFFFL;return wCRCin ^= 0xFFFFFFFFL;}public static long CRC32_C(byte[] source, int offset, int length) {long wCRCin = 0xFFFFFFFFL;// Long.reverse(0x1EDC6F41L) >>> 32long wCPoly = 0x82F63B78L;for (int i = offset, cnt = offset + length; i < cnt; i++) {wCRCin ^= ((long) source[i] & 0x000000FFL);for (int j = 0; j < 8; j++) {if ((wCRCin & 0x00000001L) != 0) {wCRCin >>= 1;wCRCin ^= wCPoly;} else {wCRCin >>= 1;}}}return wCRCin ^= 0xFFFFFFFFL;}public static long CRC32_D(byte[] source, int offset, int length) {long wCRCin = 0xFFFFFFFFL;// Long.reverse(0xA833982BL) >>> 32long wCPoly = 0xD419CC15L;for (int i = offset, cnt = offset + length; i < cnt; i++) {wCRCin ^= ((long) source[i] & 0x000000FFL);for (int j = 0; j < 8; j++) {if ((wCRCin & 0x00000001L) != 0) {wCRCin >>= 1;wCRCin ^= wCPoly;} else {wCRCin >>= 1;}}}return wCRCin ^= 0xFFFFFFFFL;}public static long CRC32_MPEG_2(byte[] source, int offset, int length) {long wCRCin = 0xFFFFFFFFL;long wCPoly = 0x04C11DB7L;for (int i = offset, cnt = offset + length; i < cnt; i++) {for (int j = 0; j < 8; j++) {boolean bit = ((source[i] >> (7 - j) & 1) == 1);boolean c31 = ((wCRCin >> 31 & 1) == 1);wCRCin <<= 1;if (c31 ^ bit) {wCRCin ^= wCPoly;}}}wCRCin &= 0xFFFFFFFFL;return wCRCin ^= 0x00000000L;}public static long CRC32_POSIX(byte[] source, int offset, int length) {long wCRCin = 0x00000000L;long wCPoly = 0x04C11DB7L;for (int i = offset, cnt = offset + length; i < cnt; i++) {for (int j = 0; j < 8; j++) {boolean bit = ((source[i] >> (7 - j) & 1) == 1);boolean c31 = ((wCRCin >> 31 & 1) == 1);wCRCin <<= 1;if (c31 ^ bit) {wCRCin ^= wCPoly;}}}wCRCin &= 0xFFFFFFFFL;return wCRCin ^= 0xFFFFFFFFL;}}
}
冗余位是循环冗余校验(CRC)中用于检测数据传输错误的附加校验位,其核心原理是通过生成多项式对数据块进行编码,生成可被多项式整除的二进制序列并附加冗余位,接收端通过相同多项式验证余数以判断传输正确性 [1]。该技术利用模2除法运算,发送端在数据末尾补零后除以生成多项式,所得余数作为校验码附加发送;接收端重复运算,余数非零则判定存在差错并触发重传 [2]。
循环冗余码的生成多项式决定校验位长度和错误检测能力,如CRC-32、CRC-16等标准差异在于多项式选择及校验位长度 [1-2]。CRC可检测所有奇数位错、双比特错及小于校验位长度的突发错误,适用于以太网、蓝牙、存储设备等场景。其实现基于异或运算简化模2除法流程,硬件复杂度低且漏检率优于传统校验方案