[英]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。 有誰知道如何解決這個問題?
首先,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.