03_ACS550變頻器RS485Modbus通訊-CRC校驗
阿新 • • 發佈:2019-02-12
Modbus CRC校驗
Modbus採用的為CRC校驗方式,生成16位的校驗碼,但是不同的協議CRC16採用的校驗方式是有所區別的。
對於CRC16而言,不同的協議之間可能會有如下的不同。
多項式選擇的不同。例如Modbus使用的多項式為0x8005,CCITT使用的多項式為0x1021。
初始值的不同。例如Modbus協議CRC結果暫存器裝載的初始值為0xFFFF,CCITT協議CRC結果暫存器裝載的初始值為0x0000。
結果異或值的不同。例如Modbus協議計算的CRC結果需要異或0x0000,DNP協議結果需要異或0xFFFF。
輸入資料反轉。不同協議要求可能不同,Modbus要求待測資料的每個位元組需要按位反轉,例如位元組01111001需要反轉為10011110,即高低位調換,第0位和第7位進行調換。每一個位元組在進行計算的時候都需要首先進行反轉。
輸出資料反轉。Modbus要求在計算結果之後,異或輸出之前,整個資料是否按位反轉。這個與輸入資料的按位元組進行反轉有所區別,這個是將計算出來的CRC值(16位)高低位調換,即第0位和15位進行調換。 最後再與結果異或值中需要異或的資料進行異或,即為我們需要的校驗碼。
Modbus CRC校驗 C程式碼
CRC校驗的方法具體實現就不進行詳細的介紹了,貼一段Modbus CRC校驗的C程式碼供參考。
#define CRC16 0x8005
//CRC校驗
unsigned int CalculateCRC(char* msg,int length)
{
//定義一個16位的暫存器儲存計算結果
Uint16 CRC16_REGS = 0xFFFF;
int i;
if((msg == 0) || (length == 0))
{
return 0;
}
for(i = 0 ; i < length ; i++)
{
//迴圈冗餘計算
//對輸入的資料按位取反(第0位和第7位對調)
CRC16_REGS = CalculateByte(CRC16_REGS,ReverseBit(msg[i],8));
}
//異或輸出之前,整個資料是否按位反轉
CRC16_REGS = ReverseBit(CRC16_REGS,16 );
//返回計算的結果
CRC16_REGS = CRC16_REGS ^ 0x0000;
return CRC16_REGS;
}
//CRC某一位元組的校驗
unsigned int CalculateByte(Uint16 crc, char b)
{
int i;
//第一次進入相當於將資料拷貝到CRC暫存器中
//之後每次進入進行異或計算相當於將新位元組中的資料與之前的餘數進行關聯
//進行運算的時候每個位元組運算都會進行移位,8次之後剩下的餘數都為與0進行運算的結果
//新資料與該值進行運算,則當前CRC暫存器中的資料即為正確進行運算的結果
crc = crc ^ ((int)b << 8);
for(i = 0 ; i < 8 ; i++ )
{
if(crc & 0x8000)
{
//先移位再計算或者是先計算再移位是不相同的
//先進行移位是因為除數省略了最高位,16位的除數實際為17位,
//當判斷首位是否為1,如果為1,則進行移位,相當於將最高位已經進行了運算,結果為0進行移位
//然後用暫存器中剩餘的15+1位(新移入的0)與除數進行計算
crc = (crc << 1) ^ CRC16;
}
else
{
crc = crc << 1 ; //當首位為0時往後移位
}
}
return crc & 0xFFFF ; //返回該位元組的CRC計算結果
}
//位反轉,num為需要反轉的資料,length為需要反轉的長度8/16/32
unsigned int ReverseBit(unsigned int num,int length){
unsigned int result = 0;
int i;
for(i = 0;i<length;i++){
result = result << 1;
result |= num & 1;
num = num >> 1;
}
return result;
}
使用的時候如下所示:
...
CRC = CalculateCRC((char*)&acs_data, 6);
//計算結果高低位需要置換一次,例如C8 09 傳送的時候應該為09 C8
acs_data.CRCL = CRC >> 8 ;
acs_data.CRCH = CRC & 0x00FF;
...
CRC線上校驗
最後附上一個CRC線上計算的網站:
總結
至此,ACS550變頻器通過RS485 Modbus協議進行通訊的文章完結,由於個人水平有限,不免有理解錯誤或者不到位的地方,忘能夠批評指正。僅希望能夠對初接觸ACS550或者該型別變頻器的朋友能有一些參考作用,避免少走彎路。