CRCHelper.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  1. using System;
  2. namespace Ropin.Environmentally.LoRaService
  3. {
  4. public class CRCHelper
  5. {
  6. /// **********************************************************************
  7. /// Name: CRC-4/ITU x4+x+1
  8. /// Poly: 0x03
  9. /// Init: 0x00
  10. /// Refin: true
  11. /// Refout: true
  12. /// Xorout: 0x00
  13. ///*************************************************************************
  14. public static byte[] Crc1(byte[] buffer, int start = 0, int len = 0)
  15. {
  16. if (buffer == null || buffer.Length == 0) return null;
  17. if (start < 0) return null;
  18. if (len == 0) len = buffer.Length - start;
  19. int length = start + len;
  20. if (length > buffer.Length) return null;
  21. byte crc = 0;// Initial value
  22. for (int i = start; i < length; i++)
  23. {
  24. crc ^= buffer[i];
  25. for (int j = 0; j < 8; j++)
  26. {
  27. if ((crc & 1) > 0)
  28. crc = (byte)((crc >> 1) ^ 0x0C);//0x0C = (reverse 0x03)>>(8-4)
  29. else
  30. crc = (byte)(crc >> 1);
  31. }
  32. }
  33. return new byte[] { crc };
  34. }
  35. /// **********************************************************************
  36. /// Name: CRC-5/EPC x5+x3+1
  37. /// Poly: 0x09
  38. /// Init: 0x09
  39. /// Refin: false
  40. /// Refout: false
  41. /// Xorout: 0x00
  42. ///*************************************************************************
  43. public static byte[] Crc2(byte[] buffer, int start = 0, int len = 0)
  44. {
  45. if (buffer == null || buffer.Length == 0) return null;
  46. if (start < 0) return null;
  47. if (len == 0) len = buffer.Length - start;
  48. int length = start + len;
  49. if (length > buffer.Length) return null;
  50. byte crc = 0x48;// Initial value: 0x48 = 0x09<<(8-5)
  51. for (int i = start; i < length; i++)
  52. {
  53. crc ^= buffer[i];
  54. for (int j = 0; j < 8; j++)
  55. {
  56. if ((crc & 0x80) > 0)
  57. crc = (byte)((crc << 1) ^ 0x48);// 0x48 = 0x09<<(8-5)
  58. else
  59. crc = (byte)(crc << 1);
  60. }
  61. }
  62. return new byte[] { (byte)(crc >> 3) };
  63. }
  64. /// **********************************************************************
  65. /// Name: CRC-5/ITU x5+x4+x2+1
  66. /// Poly: 0x15
  67. /// Init: 0x00
  68. /// Refin: true
  69. /// Refout: true
  70. /// Xorout: 0x00
  71. ///*************************************************************************
  72. public static byte[] Crc3(byte[] buffer, int start = 0, int len = 0)
  73. {
  74. if (buffer == null || buffer.Length == 0) return null;
  75. if (start < 0) return null;
  76. if (len == 0) len = buffer.Length - start;
  77. int length = start + len;
  78. if (length > buffer.Length) return null;
  79. byte crc = 0;// Initial value
  80. for (int i = start; i < length; i++)
  81. {
  82. crc ^= buffer[i];
  83. for (int j = 0; j < 8; j++)
  84. {
  85. if ((crc & 1) > 0)
  86. crc = (byte)((crc >> 1) ^ 0x15);// 0x15 = (reverse 0x15)>>(8-5)
  87. else
  88. crc = (byte)(crc >> 1);
  89. }
  90. }
  91. return new byte[] { crc };
  92. }
  93. /// **********************************************************************
  94. /// Name: CRC-5/USB x5+x2+1
  95. /// Poly: 0x05
  96. /// Init: 0x1F
  97. /// Refin: true
  98. /// Refout: true
  99. /// Xorout: 0x1F
  100. ///*************************************************************************
  101. public static byte[] Crc4(byte[] buffer, int start = 0, int len = 0)
  102. {
  103. if (buffer == null || buffer.Length == 0) return null;
  104. if (start < 0) return null;
  105. if (len == 0) len = buffer.Length - start;
  106. int length = start + len;
  107. if (length > buffer.Length) return null;
  108. byte crc = 0x1F;// Initial value
  109. for (int i = start; i < length; i++)
  110. {
  111. crc ^= buffer[i];
  112. for (int j = 0; j < 8; j++)
  113. {
  114. if ((crc & 1) > 0)
  115. crc = (byte)((crc >> 1) ^ 0x14);// 0x14 = (reverse 0x05)>>(8-5)
  116. else
  117. crc = (byte)(crc >> 1);
  118. }
  119. }
  120. return new byte[] { (byte)(crc ^ 0x1F) };
  121. }
  122. /// **********************************************************************
  123. /// Name: CRC-6/ITU x6+x+1
  124. /// Poly: 0x03
  125. /// Init: 0x00
  126. /// Refin: true
  127. /// Refout: true
  128. /// Xorout: 0x00
  129. ///*************************************************************************
  130. public static byte[] Crc5(byte[] buffer, int start = 0, int len = 0)
  131. {
  132. if (buffer == null || buffer.Length == 0) return null;
  133. if (start < 0) return null;
  134. if (len == 0) len = buffer.Length - start;
  135. int length = start + len;
  136. if (length > buffer.Length) return null;
  137. byte crc = 0;// Initial value
  138. for (int i = start; i < length; i++)
  139. {
  140. crc ^= buffer[i];
  141. for (int j = 0; j < 8; j++)
  142. {
  143. if ((crc & 1) > 0)
  144. crc = (byte)((crc >> 1) ^ 0x30);// 0x30 = (reverse 0x03)>>(8-6)
  145. else
  146. crc = (byte)(crc >> 1);
  147. }
  148. }
  149. return new byte[] { crc };
  150. }
  151. /// **********************************************************************
  152. /// Name: CRC-7/MMC x7+x3+1
  153. /// Poly: 0x09
  154. /// Init: 0x00
  155. /// Refin: false
  156. /// Refout: false
  157. /// Xorout: 0x00
  158. ///*************************************************************************
  159. public static byte[] Crc6(byte[] buffer, int start = 0, int len = 0)
  160. {
  161. if (buffer == null || buffer.Length == 0) return null;
  162. if (start < 0) return null;
  163. if (len == 0) len = buffer.Length - start;
  164. int length = start + len;
  165. if (length > buffer.Length) return null;
  166. byte crc = 0;// Initial value
  167. for (int i = start; i < length; i++)
  168. {
  169. crc ^= buffer[i];
  170. for (int j = 0; j < 8; j++)
  171. {
  172. if ((crc & 0x80) > 0)
  173. crc = (byte)((crc << 1) ^ 0x12);// 0x12 = 0x09<<(8-7)
  174. else
  175. crc = (byte)(crc << 1);
  176. }
  177. }
  178. return new byte[] { (byte)(crc >> 1) };
  179. }
  180. /// **********************************************************************
  181. /// Name: CRC8 x8+x2+x+1
  182. /// Poly: 0x07
  183. /// Init: 0x00
  184. /// Refin: false
  185. /// Refout: false
  186. /// Xorout: 0x00
  187. ///*************************************************************************
  188. public static byte[] Crc7(byte[] buffer, int start = 0, int len = 0)
  189. {
  190. if (buffer == null || buffer.Length == 0) return null;
  191. if (start < 0) return null;
  192. if (len == 0) len = buffer.Length - start;
  193. int length = start + len;
  194. if (length > buffer.Length) return null;
  195. byte crc = 0;// Initial value
  196. for (int i = start; i < length; i++)
  197. {
  198. crc ^= buffer[i];
  199. for (int j = 0; j < 8; j++)
  200. {
  201. if ((crc & 0x80) > 0)
  202. crc = (byte)((crc << 1) ^ 0x07);
  203. else
  204. crc = (byte)(crc << 1);
  205. }
  206. }
  207. return new byte[] { crc };
  208. }
  209. /// **********************************************************************
  210. /// Name: CRC-8/ITU x8+x2+x+1
  211. /// Poly: 0x07
  212. /// Init: 0x00
  213. /// Refin: false
  214. /// Refout: false
  215. /// Xorout: 0x55
  216. ///*************************************************************************
  217. public static byte[] Crc8(byte[] buffer, int start = 0, int len = 0)
  218. {
  219. if (buffer == null || buffer.Length == 0) return null;
  220. if (start < 0) return null;
  221. if (len == 0) len = buffer.Length - start;
  222. int length = start + len;
  223. if (length > buffer.Length) return null;
  224. byte crc = 0;// Initial value
  225. for (int i = start; i < length; i++)
  226. {
  227. crc ^= buffer[i];
  228. for (int j = 0; j < 8; j++)
  229. {
  230. if ((crc & 0x80) > 0)
  231. crc = (byte)((crc << 1) ^ 0x07);
  232. else
  233. crc = (byte)(crc << 1);
  234. }
  235. }
  236. return new byte[] { (byte)(crc ^ 0x55) };
  237. }
  238. /// **********************************************************************
  239. /// Name: CRC-8/MAXIM x8+x5+x4+1
  240. /// Poly: 0x31
  241. /// Init: 0x00
  242. /// Refin: true
  243. /// Refout: true
  244. /// Xorout: 0x00
  245. ///*************************************************************************
  246. public static byte[] Crc9(byte[] buffer, int start = 0, int len = 0)
  247. {
  248. if (buffer == null || buffer.Length == 0) return null;
  249. if (start < 0) return null;
  250. if (len == 0) len = buffer.Length - start;
  251. int length = start + len;
  252. if (length > buffer.Length) return null;
  253. byte crc = 0;// Initial value
  254. for (int i = start; i < length; i++)
  255. {
  256. crc ^= buffer[i];
  257. for (int j = 0; j < 8; j++)
  258. {
  259. if ((crc & 1) > 0)
  260. crc = (byte)((crc >> 1) ^ 0x8C);// 0x8C = reverse 0x31
  261. else
  262. crc = (byte)(crc >> 1);
  263. }
  264. }
  265. return new byte[] { crc };
  266. }
  267. /// **********************************************************************
  268. /// Name: CRC-8/ROHC x8+x2+x+1
  269. /// Poly: 0x07
  270. /// Init: 0xFF
  271. /// Refin: true
  272. /// Refout: true
  273. /// Xorout: 0x00
  274. ///*************************************************************************
  275. public static byte[] Crc10(byte[] buffer, int start = 0, int len = 0)
  276. {
  277. if (buffer == null || buffer.Length == 0) return null;
  278. if (start < 0) return null;
  279. if (len == 0) len = buffer.Length - start;
  280. int length = start + len;
  281. if (length > buffer.Length) return null;
  282. byte crc = 0xFF;// Initial value
  283. for (int i = start; i < length; i++)
  284. {
  285. crc ^= buffer[i];
  286. for (int j = 0; j < 8; j++)
  287. {
  288. if ((crc & 1) > 0)
  289. crc = (byte)((crc >> 1) ^ 0xE0);// 0xE0 = reverse 0x07
  290. else
  291. crc = (byte)(crc >> 1);
  292. }
  293. }
  294. return new byte[] { crc };
  295. }
  296. /// Z1协议校验码计算
  297. static byte[] table = { 0x00, 0x1C, 0x38, 0x24, 0x70, 0x6C, 0x48, 0x54, 0xE0, 0xFC,
  298. 0xD8, 0xC4, 0x90, 0x8C, 0xA8, 0xB4, 0xDC, 0xC0, 0xE4, 0xF8,
  299. 0xAC, 0xB0, 0x94, 0x88, 0x3C, 0x20, 0x04, 0x18, 0x4C, 0x50,
  300. 0x74, 0x68, 0xA4, 0xB8, 0x9C, 0x80, 0xD4, 0xC8, 0xEC, 0xF0,
  301. 0x44, 0x58, 0x7C, 0x60, 0x34, 0x28, 0x0C, 0x10, 0x78, 0x64,
  302. 0x40, 0x5C, 0x08, 0x14, 0x30, 0x2C, 0x98, 0x84, 0xA0, 0xBC,
  303. 0xE8, 0xF4, 0xD0, 0xCC, 0x54, 0x48, 0x6C, 0x70, 0x24, 0x38,
  304. 0x1C, 0x00, 0xB4, 0xA8, 0x8C, 0x90, 0xC4, 0xD8, 0xFC, 0xE0,
  305. 0x88, 0x94, 0xB0, 0xAC, 0xF8, 0xE4, 0xC0, 0xDC, 0x68, 0x74,
  306. 0x50, 0x4C, 0x18, 0x04, 0x20, 0x3C, 0xF0, 0xEC, 0xC8, 0xD4,
  307. 0x80, 0x9C, 0xB8, 0xA4, 0x10, 0x0C, 0x28, 0x34, 0x60, 0x7C,
  308. 0x58, 0x44, 0x2C, 0x30, 0x14, 0x08, 0x5C, 0x40, 0x64, 0x78,
  309. 0xCC, 0xD0, 0xF4, 0xE8, 0xBC, 0xA0, 0x84, 0x98, 0xA8, 0xB4,
  310. 0x90, 0x8C, 0xD8, 0xC4, 0xE0, 0xFC, 0x48, 0x54, 0x70, 0x6C,
  311. 0x38, 0x24, 0x00, 0x1C, 0x74, 0x68, 0x4C, 0x50, 0x04, 0x18,
  312. 0x3C, 0x20, 0x94, 0x88, 0xAC, 0xB0, 0xE4, 0xF8, 0xDC, 0xC0,
  313. 0x0C, 0x10, 0x34, 0x28, 0x7C, 0x60, 0x44, 0x58, 0xEC, 0xF0,
  314. 0xD4, 0xC8, 0x9C, 0x80, 0xA4, 0xB8, 0xD0, 0xCC, 0xE8, 0xF4,
  315. 0xA0, 0xBC, 0x98, 0x84, 0x30, 0x2C, 0x08, 0x14, 0x40, 0x5C,
  316. 0x78, 0x64, 0xFC, 0xE0, 0xC4, 0xD8, 0x8C, 0x90, 0xB4, 0xA8,
  317. 0x1C, 0x00, 0x24, 0x38, 0x6C, 0x70, 0x54, 0x48, 0x20, 0x3C,
  318. 0x18, 0x04, 0x50, 0x4C, 0x68, 0x74, 0xC0, 0xDC, 0xF8, 0xE4,
  319. 0xB0, 0xAC, 0x88, 0x94, 0x58, 0x44, 0x60, 0x7C, 0x28, 0x34,
  320. 0x10, 0x0C, 0xB8, 0xA4, 0x80, 0x9C, 0xC8, 0xD4, 0xF0, 0xEC,
  321. 0x84, 0x98, 0xBC, 0xA0, 0xF4, 0xE8, 0xCC, 0xD0, 0x64, 0x78,
  322. 0x5C, 0x40, 0x14, 0x08, 0x2C, 0x30
  323. };
  324. public static byte[] Crc11(byte[] buffer, int start = 0, int len = 0)
  325. {
  326. if (buffer == null || buffer.Length == 0) return null;
  327. if (start < 0) return null;
  328. if (len == 0) len = buffer.Length - start;
  329. int length = start + len;
  330. if (length > buffer.Length) return null;
  331. int i;
  332. byte crc = 0x00;
  333. int tableIndex;
  334. for (i = start; i < length; i++)
  335. {
  336. tableIndex = crc ^ (buffer[i] & 0xFF);
  337. crc = table[tableIndex];
  338. }
  339. return new byte[] { crc };
  340. }
  341. /// **********************************************************************
  342. /// Name: CRC-12 x16+x12+x5+1
  343. /// Poly: 0x80
  344. /// Init: 0x0000
  345. /// Refin: true
  346. /// Refout: true
  347. /// Xorout: 0x0000
  348. ///*************************************************************************
  349. public static byte[] Crc12(byte[] buffer, int start = 0, int len = 0)
  350. {
  351. if (buffer == null || buffer.Length == 0) return null;
  352. if (start < 0) return null;
  353. if (len == 0) len = buffer.Length - start;
  354. int length = start + len;
  355. if (length > buffer.Length) return null;
  356. ushort crc = 0;// Initial value
  357. short iQ = 0, iR = 0;
  358. for (int i = start; i < length; i++)
  359. {
  360. // 多项式除法
  361. // 如果该位为1
  362. if ((buffer[i] & (0x80 >> iR)) > 0)
  363. {
  364. // 则在余数尾部添1否则添0
  365. crc |= 0x01;
  366. }
  367. // 如果12位除数中的最高位为1,则够除
  368. if (crc >= 0x1000)
  369. {
  370. crc ^= 0x180D;
  371. }
  372. crc <<= 1;
  373. iR++;
  374. if (8 == iR)
  375. {
  376. iR = 0;
  377. iQ++;
  378. }
  379. }
  380. // 对后面添加的12个0做处理
  381. for (int i = 0; i < 12; i++)
  382. {
  383. if (crc >= 0x1000)
  384. {
  385. crc ^= 0x180D;
  386. }
  387. crc <<= 1;
  388. }
  389. crc >>= 1;
  390. byte[] ret = BitConverter.GetBytes(crc);
  391. Array.Reverse(ret);
  392. return ret;
  393. }
  394. /// **********************************************************************
  395. /// Name: CRC-16/CCITT x16+x12+x5+1
  396. /// Poly: 0x1021
  397. /// Init: 0x0000
  398. /// Refin: true
  399. /// Refout: true
  400. /// Xorout: 0x0000
  401. ///*************************************************************************
  402. public static byte[] Crc13(byte[] buffer, int start = 0, int len = 0)
  403. {
  404. if (buffer == null || buffer.Length == 0) return null;
  405. if (start < 0) return null;
  406. if (len == 0) len = buffer.Length - start;
  407. int length = start + len;
  408. if (length > buffer.Length) return null;
  409. ushort crc = 0;// Initial value
  410. for (int i = start; i < length; i++)
  411. {
  412. crc ^= buffer[i];
  413. for (int j = 0; j < 8; j++)
  414. {
  415. if ((crc & 1) > 0)
  416. crc = (ushort)((crc >> 1) ^ 0x8408);// 0x8408 = reverse 0x1021
  417. else
  418. crc = (ushort)(crc >> 1);
  419. }
  420. }
  421. byte[] ret = BitConverter.GetBytes(crc);
  422. Array.Reverse(ret);
  423. return ret;
  424. }
  425. /// **********************************************************************
  426. /// Name: CRC-16/CCITT FALSE x16+x12+x5+1
  427. /// Poly: 0x1021
  428. /// Init: 0xFFFF
  429. /// Refin: false
  430. /// Refout: false
  431. /// Xorout: 0x0000
  432. ///*************************************************************************
  433. public static byte[] Crc14(byte[] buffer, int start = 0, int len = 0)
  434. {
  435. if (buffer == null || buffer.Length == 0) return null;
  436. if (start < 0) return null;
  437. if (len == 0) len = buffer.Length - start;
  438. int length = start + len;
  439. if (length > buffer.Length) return null;
  440. ushort crc = 0xFFFF;// Initial value
  441. for (int i = start; i < length; i++)
  442. {
  443. crc ^= (ushort)(buffer[i] << 8);
  444. for (int j = 0; j < 8; j++)
  445. {
  446. if ((crc & 0x8000) > 0)
  447. crc = (ushort)((crc << 1) ^ 0x1021);
  448. else
  449. crc = (ushort)(crc << 1);
  450. }
  451. }
  452. byte[] ret = BitConverter.GetBytes(crc);
  453. Array.Reverse(ret);
  454. return ret;
  455. }
  456. /// **********************************************************************
  457. /// Name: CRC-16/DNP x16+x13+x12+x11+x10+x8+x6+x5+x2+1
  458. /// Poly: 0x3D65
  459. /// Init: 0x0000
  460. /// Refin: true
  461. /// Refout: true
  462. /// Xorout: 0xFFFF
  463. ///*************************************************************************
  464. public static byte[] Crc15(byte[] buffer, int start = 0, int len = 0)
  465. {
  466. if (buffer == null || buffer.Length == 0) return null;
  467. if (start < 0) return null;
  468. if (len == 0) len = buffer.Length - start;
  469. int length = start + len;
  470. if (length > buffer.Length) return null;
  471. ushort crc = 0;// Initial value
  472. for (int i = start; i < length; i++)
  473. {
  474. crc ^= buffer[i];
  475. for (int j = 0; j < 8; j++)
  476. {
  477. if ((crc & 1) > 0)
  478. crc = (ushort)((crc >> 1) ^ 0xA6BC);// 0xA6BC = reverse 0x3D65
  479. else
  480. crc = (ushort)(crc >> 1);
  481. }
  482. }
  483. byte[] ret = BitConverter.GetBytes((ushort)~crc);
  484. Array.Reverse(ret);
  485. return ret;
  486. }
  487. /// **********************************************************************
  488. /// Name: CRC-16/IBM x16+x15+x2+1
  489. /// Poly: 0x8005
  490. /// Init: 0x0000
  491. /// Refin: true
  492. /// Refout: true
  493. /// Xorout: 0x0000
  494. ///*************************************************************************
  495. public static byte[] Crc16(byte[] buffer, int start = 0, int len = 0)
  496. {
  497. if (buffer == null || buffer.Length == 0) return null;
  498. if (start < 0) return null;
  499. if (len == 0) len = buffer.Length - start;
  500. int length = start + len;
  501. if (length > buffer.Length) return null;
  502. ushort crc = 0;// Initial value
  503. for (int i = start; i < length; i++)
  504. {
  505. crc ^= buffer[i];
  506. for (int j = 0; j < 8; j++)
  507. {
  508. if ((crc & 1) > 0)
  509. crc = (ushort)((crc >> 1) ^ 0xA001);// 0xA001 = reverse 0x8005
  510. else
  511. crc = (ushort)(crc >> 1);
  512. }
  513. }
  514. byte[] ret = BitConverter.GetBytes(crc);
  515. Array.Reverse(ret);
  516. return ret;
  517. }
  518. /// **********************************************************************
  519. /// Name: CRC-16/MAXIM x16+x15+x2+1
  520. /// Poly: 0x8005
  521. /// Init: 0x0000
  522. /// Refin: true
  523. /// Refout: true
  524. /// Xorout: 0xFFFF
  525. ///*************************************************************************
  526. public static byte[] Crc17(byte[] buffer, int start = 0, int len = 0)
  527. {
  528. if (buffer == null || buffer.Length == 0) return null;
  529. if (start < 0) return null;
  530. if (len == 0) len = buffer.Length - start;
  531. int length = start + len;
  532. if (length > buffer.Length) return null;
  533. ushort crc = 0;// Initial value
  534. for (int i = start; i < length; i++)
  535. {
  536. crc ^= buffer[i];
  537. for (int j = 0; j < 8; j++)
  538. {
  539. if ((crc & 1) > 0)
  540. crc = (ushort)((crc >> 1) ^ 0xA001);// 0xA001 = reverse 0x8005
  541. else
  542. crc = (ushort)(crc >> 1);
  543. }
  544. }
  545. byte[] ret = BitConverter.GetBytes((ushort)~crc);
  546. Array.Reverse(ret);
  547. return ret;
  548. }
  549. /// **********************************************************************
  550. /// Name: CRC-16/MODBUS x16+x15+x2+1
  551. /// Poly: 0x8005
  552. /// Init: 0xFFFF
  553. /// Refin: true
  554. /// Refout: true
  555. /// Xorout: 0x0000
  556. ///*************************************************************************
  557. public static byte[] Crc16Modbus(byte[] buffer, int start = 0, int len = 0)
  558. {
  559. if (buffer == null || buffer.Length == 0) return null;
  560. if (start < 0) return null;
  561. if (len == 0) len = buffer.Length - start;
  562. int length = start + len;
  563. if (length > buffer.Length) return null;
  564. ushort crc = 0xFFFF;// Initial value
  565. for (int i = start; i < length; i++)
  566. {
  567. crc ^= buffer[i];
  568. for (int j = 0; j < 8; j++)
  569. {
  570. if ((crc & 1) > 0)
  571. crc = (ushort)((crc >> 1) ^ 0xA001);// 0xA001 = reverse 0x8005
  572. else
  573. crc = (ushort)(crc >> 1);
  574. }
  575. }
  576. byte[] ret = BitConverter.GetBytes(crc);
  577. Array.Reverse(ret);
  578. return ret;
  579. }
  580. /// **********************************************************************
  581. /// Name: CRC-16/USB x16+x15+x2+1
  582. /// Poly: 0x8005
  583. /// Init: 0xFFFF
  584. /// Refin: true
  585. /// Refout: true
  586. /// Xorout: 0xFFFF
  587. ///*************************************************************************
  588. public static byte[] Crc19(byte[] buffer, int start = 0, int len = 0)
  589. {
  590. if (buffer == null || buffer.Length == 0) return null;
  591. if (start < 0) return null;
  592. if (len == 0) len = buffer.Length - start;
  593. int length = start + len;
  594. if (length > buffer.Length) return null;
  595. ushort crc = 0xFFFF;// Initial value
  596. for (int i = start; i < length; i++)
  597. {
  598. crc ^= buffer[i];
  599. for (int j = 0; j < 8; j++)
  600. {
  601. if ((crc & 1) > 0)
  602. crc = (ushort)((crc >> 1) ^ 0xA001);// 0xA001 = reverse 0x8005
  603. else
  604. crc = (ushort)(crc >> 1);
  605. }
  606. }
  607. byte[] ret = BitConverter.GetBytes((ushort)~crc);
  608. Array.Reverse(ret);
  609. return ret;
  610. }
  611. /// **********************************************************************
  612. /// Name: CRC-16/X25 x16+x12+x5+1
  613. /// Poly: 0x1021
  614. /// Init: 0xFFFF
  615. /// Refin: true
  616. /// Refout: true
  617. /// Xorout: 0xFFFF
  618. ///*************************************************************************
  619. public static byte[] Crc20(byte[] buffer, int start = 0, int len = 0)
  620. {
  621. if (buffer == null || buffer.Length == 0) return null;
  622. if (start < 0) return null;
  623. if (len == 0) len = buffer.Length - start;
  624. int length = start + len;
  625. if (length > buffer.Length) return null;
  626. ushort crc = 0xFFFF;// Initial value
  627. for (int i = start; i < length; i++)
  628. {
  629. crc ^= buffer[i];
  630. for (int j = 0; j < 8; j++)
  631. {
  632. if ((crc & 1) > 0)
  633. crc = (ushort)((crc >> 1) ^ 0x8408);// 0x8408 = reverse 0x1021
  634. else
  635. crc = (ushort)(crc >> 1);
  636. }
  637. }
  638. byte[] ret = BitConverter.GetBytes((ushort)~crc);
  639. Array.Reverse(ret);
  640. return ret;
  641. }
  642. /// **********************************************************************
  643. /// Name: CRC-16/XMODEM x16+x12+x5+1
  644. /// Poly: 0x1021
  645. /// Init: 0x0000
  646. /// Refin: false
  647. /// Refout: false
  648. /// Xorout: 0x0000
  649. ///*************************************************************************
  650. public static byte[] Crc21(byte[] buffer, int start = 0, int len = 0)
  651. {
  652. if (buffer == null || buffer.Length == 0) return null;
  653. if (start < 0) return null;
  654. if (len == 0) len = buffer.Length - start;
  655. int length = start + len;
  656. if (length > buffer.Length) return null;
  657. ushort crc = 0;// Initial value
  658. for (int i = start; i < length; i++)
  659. {
  660. crc ^= (ushort)(buffer[i] << 8);
  661. for (int j = 0; j < 8; j++)
  662. {
  663. if ((crc & 0x8000) > 0)
  664. crc = (ushort)((crc << 1) ^ 0x1021);
  665. else
  666. crc = (ushort)(crc << 1);
  667. }
  668. }
  669. byte[] ret = BitConverter.GetBytes(crc);
  670. Array.Reverse(ret);
  671. return ret;
  672. }
  673. /// **********************************************************************
  674. /// Name: CRC32 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
  675. /// Poly: 0x04C11DB7
  676. /// Init: 0xFFFFFFFF
  677. /// Refin: true
  678. /// Refout: true
  679. /// Xorout: 0xFFFFFFFF
  680. ///*************************************************************************
  681. public static byte[] Crc22(byte[] buffer, int start = 0, int len = 0)
  682. {
  683. if (buffer == null || buffer.Length == 0) return null;
  684. if (start < 0) return null;
  685. if (len == 0) len = buffer.Length - start;
  686. int length = start + len;
  687. if (length > buffer.Length) return null;
  688. uint crc = 0xFFFFFFFF;// Initial value
  689. for (int i = start; i < length; i++)
  690. {
  691. crc ^= buffer[i];
  692. for (int j = 0; j < 8; j++)
  693. {
  694. if ((crc & 1) > 0)
  695. crc = (crc >> 1) ^ 0xEDB88320;// 0xEDB88320= reverse 0x04C11DB7
  696. else
  697. crc = crc >> 1;
  698. }
  699. }
  700. byte[] ret = BitConverter.GetBytes(~crc);
  701. Array.Reverse(ret);
  702. return ret;
  703. }
  704. /// **********************************************************************
  705. /// Name: CRC32/MPEG-2 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
  706. /// Poly: 0x04C11DB7
  707. /// Init: 0xFFFFFFFF
  708. /// Refin: false
  709. /// Refout: false
  710. /// Xorout: 0x00000000
  711. ///*************************************************************************
  712. public static byte[] Crc23(byte[] buffer, int start = 0, int len = 0)
  713. {
  714. if (buffer == null || buffer.Length == 0) return null;
  715. if (start < 0) return null;
  716. if (len == 0) len = buffer.Length - start;
  717. int length = start + len;
  718. if (length > buffer.Length) return null;
  719. uint crc = 0xFFFFFFFF;// Initial value
  720. for (int i = start; i < length; i++)
  721. {
  722. crc ^= (uint)(buffer[i] << 24);
  723. for (int j = 0; j < 8; j++)
  724. {
  725. if ((crc & 0x80000000) > 0)
  726. crc = (crc << 1) ^ 0x04C11DB7;
  727. else
  728. crc = crc << 1;
  729. }
  730. }
  731. byte[] ret = BitConverter.GetBytes(crc);
  732. Array.Reverse(ret);
  733. return ret;
  734. }
  735. /// <summary>
  736. /// CRC高位校验码checkCRCHigh
  737. /// </summary>
  738. static byte[] ArrayCRCHigh =
  739. {
  740. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  741. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  742. 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  743. 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  744. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  745. 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  746. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  747. 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  748. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  749. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
  750. 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  751. 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  752. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  753. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
  754. 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  755. 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  756. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  757. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  758. 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  759. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  760. 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  761. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
  762. 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  763. 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  764. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  765. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  766. };
  767. /// <summary>
  768. /// CRC地位校验码checkCRCLow
  769. /// </summary>
  770. static byte[] checkCRCLow =
  771. {
  772. 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
  773. 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
  774. 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
  775. 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
  776. 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
  777. 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
  778. 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
  779. 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
  780. 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
  781. 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
  782. 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
  783. 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
  784. 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
  785. 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
  786. 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
  787. 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
  788. 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
  789. 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
  790. 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
  791. 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
  792. 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
  793. 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
  794. 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
  795. 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
  796. 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
  797. 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
  798. };
  799. /// <summary>
  800. /// CRC校验
  801. /// </summary>
  802. /// <param name="data">校验的字节数组</param>
  803. /// <param name="length">校验的数组长度</param>
  804. /// <returns>该字节数组的奇偶校验字节</returns>
  805. public static string CRC16(byte[] data, int arrayLength)
  806. {
  807. byte CRCHigh = 0xFF;
  808. byte CRCLow = 0xFF;
  809. byte index;
  810. int i = 0;
  811. while (arrayLength-- > 0)
  812. {
  813. index = (System.Byte)(CRCHigh ^ data[i++]);
  814. CRCHigh = (System.Byte)(CRCLow ^ ArrayCRCHigh[index]);
  815. CRCLow = checkCRCLow[index];
  816. }
  817. return (CRCHigh << 8 | CRCLow).ToString("X2");
  818. }
  819. }
  820. }