一、Modbus CRC-16
Modbus CRC-16是屬於邏輯運算的一種,假設現在有一個串資料是0x01, 0x25,想要運算,其算法如下:
- 步驟一:先將一個16bit(在C中可以使用unsigned short)暫存器設為0xFFFF,這邊先命名該暫存器為crc。
- 步驟二:將crc與資料的1個byte做XOR運算,這邊的舉例第一次就是與0x01做XOR,第二次就是0x25
- 步驟三:接下來,將crc向右位移1個bit,並且最高有效位元(MSB)填0。
- 步驟四:在位移前的crc,若其最低有效位元(LSB)是1,則將位移後的CRC對0xA001做運算。
- 接下來繼續重複步驟3~4,直到做滿8次。
- 步驟五:接下來將Data的下一個byte拿來做步驟二到四,直到全部資料皆運算完為止。
我們來看個圖例吧!下圖是將1個byte的資料:0x01拿來運算的過程。
STEP 1:
STEP 2:
上述這過程要連續做8次。
這樣就完成一個byte的資料CRC運算了,如果要運算的資料大於1個byte,就繼續做步驟2~4吧。
二、程式簡介
本篇重點是稍微分享一下修改過的Modbus RTU CRC16計算程式。計算function是從網路上找到的,來源:modbus RTUのCRC計算方法(C言語)
不過由於公司使用的Modbus其封包格式CRC是低位元在前,高位元在後,所以下方的程式範例我將運算出來的CRC做高低位元交換,如此一來送出才是正確的哦。
假設現在要送出485的指令是『01 05 01 00 00 00』,我們使用南樺電機有限公司‧計算 Modbus RTU 線上計算結果如下
將下列程式執行出來後結果圖如下
變更一下長度試試看..!!
程式執行結果
三、程式碼
程式碼如下:
unsigned short calc_crc(unsigned char *buf, int length) { unsigned short crc = 0xFFFF; int i,j; unsigned char LSB; for (i = 0; i < length; i++) { crc ^= buf[i]; for (j = 0; j < 8; j++) { LSB= crc & 1; crc = crc >> 1; if (LSB) { crc ^= 0xA001; } } } return ((crc & 0xFF00) >> 8)|((crc & 0x0FF) << 8 ); } int main(void) { char tmp[] = {1,5,1,0,0,0}; printf("%x\n", calc_crc(tmp, 6)); }
沒有留言:
張貼留言