2015年7月10日 星期五

[Linux C] C語言上Modbus RTU CRC16計算教學與實作


一、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:


STEP 3~4: 





上述這過程要連續做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));

}



沒有留言:

張貼留言