簡體   English   中英

帶有 Vanilla JS 的 CRC-16 校驗和計算器

[英]CRC-16 Checksum calculator with Vanilla JS

我正在尋找用 JavaScript 編寫並在普通瀏覽器中運行的 CRC-16 CRC 算法。 我知道在各種編程語言中都有大量用於 CRC-16 實現的代碼示例。 但我仍然無法解決我的問題。 以下示例顯示了 NodeJ 的 CRC-16 校驗和檢查。

https://github.com/donvercety/node-crc16/blob/master/crc16.js

為了讓 NodeJS 代碼在普通瀏覽器中運行,我對其進行了如下調整。

 const crctab16 = new Uint16Array([ 0X0000, 0X1189, 0X2312, 0X329B, 0X4624, 0X57AD, 0X6536, 0X74BF, 0X8C48, 0X9DC1, 0XAF5A, 0XBED3, 0XCA6C, 0XDBE5, 0XE97E, 0XF8F7, 0X1081, 0X0108, 0X3393, 0X221A, 0X56A5, 0X472C, 0X75B7, 0X643E, 0X9CC9, 0X8D40, 0XBFDB, 0XAE52, 0XDAED, 0XCB64, 0XF9FF, 0XE876, 0X2102, 0X308B, 0X0210, 0X1399, 0X6726, 0X76AF, 0X4434, 0X55BD, 0XAD4A, 0XBCC3, 0X8E58, 0X9FD1, 0XEB6E, 0XFAE7, 0XC87C, 0XD9F5, 0X3183, 0X200A, 0X1291, 0X0318, 0X77A7, 0X662E, 0X54B5, 0X453C, 0XBDCB, 0XAC42, 0X9ED9, 0X8F50, 0XFBEF, 0XEA66, 0XD8FD, 0XC974, 0X4204, 0X538D, 0X6116, 0X709F, 0X0420, 0X15A9, 0X2732, 0X36BB, 0XCE4C, 0XDFC5, 0XED5E, 0XFCD7, 0X8868, 0X99E1, 0XAB7A, 0XBAF3, 0X5285, 0X430C, 0X7197, 0X601E, 0X14A1, 0X0528, 0X37B3, 0X263A, 0XDECD, 0XCF44, 0XFDDF, 0XEC56, 0X98E9, 0X8960, 0XBBFB, 0XAA72, 0X6306, 0X728F, 0X4014, 0X519D, 0X2522, 0X34AB, 0X0630, 0X17B9, 0XEF4E, 0XFEC7, 0XCC5C, 0XDDD5, 0XA96A, 0XB8E3, 0X8A78, 0X9BF1, 0X7387, 0X620E, 0X5095, 0X411C, 0X35A3, 0X242A, 0X16B1, 0X0738, 0XFFCF, 0XEE46, 0XDCDD, 0XCD54, 0XB9EB, 0XA862, 0X9AF9, 0X8B70, 0X8408, 0X9581, 0XA71A, 0XB693, 0XC22C, 0XD3A5, 0XE13E, 0XF0B7, 0X0840, 0X19C9, 0X2B52, 0X3ADB, 0X4E64, 0X5FED, 0X6D76, 0X7CFF, 0X9489, 0X8500, 0XB79B, 0XA612, 0XD2AD, 0XC324, 0XF1BF, 0XE036, 0X18C1, 0X0948, 0X3BD3, 0X2A5A, 0X5EE5, 0X4F6C, 0X7DF7, 0X6C7E, 0XA50A, 0XB483, 0X8618, 0X9791, 0XE32E, 0XF2A7, 0XC03C, 0XD1B5, 0X2942, 0X38CB, 0X0A50, 0X1BD9, 0X6F66, 0X7EEF, 0X4C74, 0X5DFD, 0XB58B, 0XA402, 0X9699, 0X8710, 0XF3AF, 0XE226, 0XD0BD, 0XC134, 0X39C3, 0X284A, 0X1AD1, 0X0B58, 0X7FE7, 0X6E6E, 0X5CF5, 0X4D7C, 0XC60C, 0XD785, 0XE51E, 0XF497, 0X8028, 0X91A1, 0XA33A, 0XB2B3, 0X4A44, 0X5BCD, 0X6956, 0X78DF, 0X0C60, 0X1DE9, 0X2F72, 0X3EFB, 0XD68D, 0XC704, 0XF59F, 0XE416, 0X90A9, 0X8120, 0XB3BB, 0XA232, 0X5AC5, 0X4B4C, 0X79D7, 0X685E, 0X1CE1, 0X0D68, 0X3FF3, 0X2E7A, 0XE70E, 0XF687, 0XC41C, 0XD595, 0XA12A, 0XB0A3, 0X8238, 0X93B1, 0X6B46, 0X7ACF, 0X4854, 0X59DD, 0X2D62, 0X3CEB, 0X0E70, 0X1FF9, 0XF78F, 0XE606, 0XD49D, 0XC514, 0XB1AB, 0XA022, 0X92B9, 0X8330, 0X7BC7, 0X6A4E, 0X58D5, 0X495C, 0X3DE3, 0X2C6A, 0X1EF1, 0X0F78, ]); function crc16(data) { var res = 0x0ffff; for (let b of data) { res = ((res >> 8) & 0x0ff) ^ crctab16[(res ^ b) & 0xff]; } return (~res) & 0x0ffff; } alert(crc16("010400030002"))

如果我用 01 04 0003 0002 測試它,我得到 13428。但我正在尋找的是 81 CB。 有誰知道如何解決這個問題?

在線工具中CRC計算截圖

鏈接到在線 CRC 計算工具

首先,Javascript 字符串存儲為 UTF-16,每個字符兩個字節。 您可以使用b.charCodeAt(0)將每個字符轉換為 integer,但僅當b是 0..127 中的 ASCII 字符時才有效。 由於 Javascript 的轉換規則,您實際計算的 CRC 是字節00 01 00 04 00 00 00 03 00 00 00 02

你沒有給 CRC 你認為你給它的數據。 您應該將Uint8Array用於一系列字節。

其次,您想要的 CRC 到底是什么? 你從哪里得到81 CB 你說你用“01 04 0003 0002”測試它,但實際上你(試圖)用“010400030002”(沒有空格)測試它。 它是哪一個? 還是您真的是指字節01 04 00 03 00 02 或者因為你對它們進行了奇怪的分組,也許后兩個是需要小端序的 16 位字? 那么字節將是01 04 03 00 02 00 它是其中之一嗎?

您需要准確了解他們在您的示例中使用了什么來達到81 CB的 CRC。 您還需要知道 CRC 本身是小端還是大端。 CRC 81cb還是cb81

“我正在尋找一種 CRC-16 CRC 算法”——那將是一個錯誤。 查看有關“循環冗余校驗”的 Wikipedia 頁面,您會注意到它列出了 11 種 CRC-16 算法(將為相同的輸入提供不同的結果)。 當你看到這個支持 23 種不同算法的在線計算器時,情況會變得更糟!

我不確定您找到的代碼使用的是哪種算法,但它不是生成您期望的值的算法。

看起來您想要計算MODBUS over Serial Line Specification and Implementation Guide附錄 B 中指定的 CRC 值(基於 modbus 標簽的使用和消息內容)。 值得看一下規范中提出的算法,因為它很容易遵循(您可能自己將其轉換為 Javascript)。

一個好的起點是現有的 Javascript Modbus 實現,所以讓我們從node-modbus-serial (ISC 許可證)中的代碼開始,並將其與您的測試數據一起使用(也解決了 Mark Adler 指出的問題):

 /** * Calculates the buffers CRC16. * * @param {Buffer} buffer the data buffer. * @return {number} the calculated CRC16. * * Source: github.com/yaacov/node-modbus-serial */ function crc16(buffer) { var crc = 0xFFFF; var odd; for (var i = 0; i < buffer.length; i++) { crc = crc ^ buffer[i]; for (var j = 0; j < 8; j++) { odd = crc & 0x0001; crc = crc >> 1; if (odd) { crc = crc ^ 0xA001; } } } return crc; }; console.log(crc16(Uint8Array.from([01,04,00,03,00,02])).toString(16))

這將輸出結果CB81 MODBUS 使用“big-Endian”表示,因此這將被編碼為81CB ,並使用modbus 解析器檢查01 04 00 03 00 02 81 CB確認這是一個有效的 MODBUS RTU 請求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM