RFID超高頻讀寫器CRC16計算方法(.NET、C語言、Java語言、python版本)
一體機(jī)讀寫器/分體式讀寫器AT指令CRC校驗方法,暫時只有C#版本,C語言版本,Java語言版本、python版本
適用型號:
LT-DS302 DS312 DS309 DS310,LT-DS814 DS818 DS8112 DS8116,LT-DS509 DS512,LT-DS322
C#版本CRC:
public class CRC
{
private static int POLYNOMIAL = 0x8408;
private static int PRESET_VALUE = 0xFFFF;
public static int crc16(string hex)
{
byte[] data = HexStringToByteArray(hex);
int current_crc_value = PRESET_VALUE;
for (int i = 0; i < data.Length; i++)
{
current_crc_value ^= data[i] & 0xFF;
for (int j = 0; j < 8; j++)
{
if ((current_crc_value & 1) != 0)
{
current_crc_value = (current_crc_value >> 1) ^ POLYNOMIAL;
}
else
{
current_crc_value = current_crc_value >> 1;
}
}
}
return current_crc_value;
}
//16進(jìn)制數(shù)組字符串轉(zhuǎn)換
private static byte[] HexStringToByteArray(string s)
{
s = s.Replace(" ", "");
byte[] buffer = new byte[s.Length / 2];
for (int i = 0; i < s.Length; i += 2)
buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
return buffer;
}
}
(詢查模式應(yīng)答格式)調(diào)用示例:
string input = "1500010301010C300833B2DDD90140000000002A80BE"//讀寫器AT指令返回值,也可用于指令發(fā)送校驗CRC
int bytes = CRC.crc16(input);
// bytes=0;bytes等于0表示通過,其他值不通過!
(詢查模式應(yīng)答格式)拆分示例:
Len:15
Adr:00
reComd:01
Status:03
ant:01
Num:01
EPC/TID長度:0C
EPC號或TID數(shù)據(jù):300833B2DDD9014000000000
RSSI值:2A
CRC-LSB:80
CRC-MSB:BE
實時模式輸入格式也相似,Statuss是0xee 就是實時模式回傳的數(shù)據(jù)。
C語言版本CRC:
CRC16的C語言算法:
#include #include #include #include #define PRESET_VALUE 0xFFFF
#define POLYNOMIAL 0x8408
typedef unsigned char byte;
typedef union name{
int len;
unsigned char ucx;
} name;
unsigned int uiCrc16Cal(unsigned char const* pucY, unsigned char ucX)
{
unsigned char ucI, ucJ;
unsigned short int uiCrcValue = PRESET_VALUE;
for (ucI = 0; ucI < ucX; ucI++)
{
uiCrcValue = uiCrcValue ^ *(pucY + ucI);
for (ucJ = 0; ucJ < 8; ucJ++)
{
if (uiCrcValue & 0x0001)
{
uiCrcValue = (uiCrcValue >> 1) ^ POLYNOMIAL;
}
else
{
uiCrcValue = (uiCrcValue >> 1);
}
}
}
return uiCrcValue;
}
void hexToBytes(const std::string& hex, byte* bytes){
int bytelen = hex.length()/2;
std::string strByte;
unsigned int n;
for(int i = 0; i < bytelen; i++){
strByte = hex.substr(i*2, 2);
sscanf(strByte.c_str(), "%x", &n);
bytes[i]=n;
}
}
int main()
{
std::string hex="1500010101010ce28011700000020cc282e26d84d652"
int bytelen=hex.length()/2;
byte *ptr=new byte[bytelen];
hexToBytes(hex, ptr);
unsigned int ret = uiCrc16Cal(ptr, bytelen);
std::cout << ret << std::endl;
delete [] ptr;
return 0;
}
說明:
pucY是要計算CRC16的字符數(shù)組的入口(需轉(zhuǎn)換字節(jié)數(shù)組),ucX是字符數(shù)組中字符個數(shù)。
上位機(jī)收到數(shù)據(jù)的時候,只要把收到的數(shù)據(jù)按以上算法進(jìn)行計算CRC16,結(jié)果為0x0000表明數(shù)據(jù)正確。
言版本:
package cn.longhaul.test;
/**
* CRC16的校驗算法工具類
*/
public class Crc16Util {
/**
* 一個字節(jié)包含位的數(shù)量 8
*/
private static final int BITS_OF_BYTE = 8;
/**
* 多項式
*/
private static final int POLYNOMIAL = 0x8408;
/**
* 初始值
*/
private static final int INITIAL_VALUE = 0xFFFF;
/**
* CRC16 編碼
*
* @param bytes 編碼內(nèi)容
* @return 編碼結(jié)果
*/
public static int crc16(int[] bytes) {
int res = INITIAL_VALUE;
for (int data : bytes) {
res = res ^ data;
for (int i = 0; i < BITS_OF_BYTE; i++) {
res = (res & 0x0001) == 1 ? (res >> 1) ^ POLYNOMIAL : res >> 1;
}
}
return revert(res);
}
/**
* 翻轉(zhuǎn)16位的高八位和低八位字節(jié)
*
* @param src 翻轉(zhuǎn)數(shù)字
* @return 翻轉(zhuǎn)結(jié)果
*/
private static int revert(int src) {
int lowByte = (src & 0xFF00) >> 8;
int highByte = (src & 0x00FF) << 8;
return lowByte | highByte;
}
/** 十六進(jìn)制轉(zhuǎn)為IntBytes
* @param s 十六進(jìn)制串
* @return int[] bytes
*/
public static int[] hexString2IntBytes(String s) {
int[] bytes;
bytes = new int[s.length() / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (int) Integer.parseInt(s.substring(2 * i, 2 * i + 2), 16);
}
return bytes;
}
public static void main(String[] args) throws Exception {
int[] data = Crc16Util.hexString2IntBytes("18010206E28011700000020A7D001A0701000600000000");
final int res = Crc16Util.crc16(data);
final String hex = Integer.toHexString(res);
System.out.print(hex);
}
}
python版本:
# -*-coding:utf-8-*-
# 多項式 0x8408
POLYNOMIAL = 0x8408
# 初始值為:0xFFFF
INITIAL_VALUE = 0xFFFF
def crc16(dataarray):
datalength = int(len(dataarray) / 2)
datalist = [None] * datalength
index = 0
try:
for index in range(datalength):
item = dataarray[index * 2:index * 2 + 2]
datalist[index] = int(item, 16)
res = INITIAL_VALUE
for data in datalist:
res = res ^ data
for index in range(8):
if res & 0x0001 == 1:
res >>= 1
res ^= POLYNOMIAL
else:
res >>= 1
lowbyte = (res & 0xFF00) >> 8
highbyte = (res & 0x00FF) << 8
res = lowbyte | highbyte
return res
except ValueError as err:
print(u'第{0}個數(shù)據(jù){1}輸入有誤'.format(index, datalist[index]).encode('utf-8'))
print(err)
if __name__ == '__main__':
data_string = '18FF0206E28011700000020A7D001A0702000800000000' # 16進(jìn)制輸入的數(shù)據(jù)流
print('數(shù)據(jù) :"{0:s}"對應(yīng)的CRC16檢驗碼為:{1:04X}'.format(data_string, crc16(data_string)))
data_string = '18010206E28011700000020A7D001A0701000600000000' # 16進(jìn)制輸入的數(shù)據(jù)流
print('數(shù)據(jù) :"{0:s}"對應(yīng)的CRC16檢驗碼為:{1:04X}'.format(data_string, crc16(data_string)))
data_string = '06FF010400' # 16進(jìn)制輸入的數(shù)據(jù)流
print('數(shù)據(jù) :"{0:s}"對應(yīng)的CRC16檢驗碼為:{1:04X}'.format(data_string, crc16(data_string)))