蔡淼
摘 要:Modbus協(xié)議是智能控制器上一種免費、開放的通用協(xié)議,廣泛應(yīng)用于自動化智能控制器和智能測控儀表,已成為我國工業(yè)自動化網(wǎng)絡(luò)協(xié)議規(guī)范的國家標(biāo)準(zhǔn)之一。CRC-16校驗是Modbus RTU通信協(xié)議中確保數(shù)據(jù)可靠性的重要措施之一,本文詳細(xì)討論了遵循Modbus RTU協(xié)議的傳輸數(shù)據(jù)的字節(jié)型CRC-16算法驗證實現(xiàn)。
關(guān)鍵詞:Modbus RTU;循環(huán)冗余碼(CRC);字節(jié)型CRC-16算法;表驅(qū)動
中圖分類號:TP391 文獻(xiàn)標(biāo)識碼:A 文章編號:2095-1302(2015)03-00-02
0 引 言
隨著物聯(lián)網(wǎng)信息化的不斷深入發(fā)展,智能設(shè)備被大量部署[1]。Modbus協(xié)議以其良好的開放特性,廣泛應(yīng)用于各種智能設(shè)備,因此對于數(shù)據(jù)傳輸?shù)目煽啃燥@的尤為重要。為了保證數(shù)據(jù)在傳送的過程中的正確無誤,不僅需要高可靠的硬件電路,同時還需差錯檢查機制,對數(shù)據(jù)信息進行校驗以檢測數(shù)據(jù)傳輸是否錯誤。通常的做法就是使用校驗碼,而CRC(循環(huán)冗余校驗碼,Cyclic Redundancy Check )就是其中最常用的一種校驗碼。為此本文對Modbus RTU及CRC原理進行了分析,詳細(xì)介紹了CRC-16字節(jié)型算法的實現(xiàn)過程,并給出了項目實踐中應(yīng)用的關(guān)鍵代1 Modbus RTU協(xié)議
1.1 Modbus協(xié)議簡介
Modbus協(xié)議是一種工業(yè)自動化系統(tǒng)常采用的通用標(biāo)準(zhǔn)協(xié)議,最初于1979年由Modicon公司提出。以其開放、標(biāo)準(zhǔn)、免收許可費等特點,被大量應(yīng)用于自動化控制器和測控儀表,已成為我國工業(yè)自動化網(wǎng)絡(luò)協(xié)議規(guī)范的國家標(biāo)準(zhǔn)之一。Modbus協(xié)議支持多種結(jié)構(gòu)的網(wǎng)絡(luò)系統(tǒng)之間的數(shù)據(jù)通信,通過此協(xié)議,智能控制器相互之間、智能控制器通過網(wǎng)絡(luò)和其它設(shè)備之間可以通信。不同廠商生產(chǎn)的智能控制設(shè)備可以藉此連接成工業(yè)網(wǎng)絡(luò),更好的進行集中監(jiān)控。
Modbus協(xié)議有兩種傳輸模式:①ASCII模式,此模式下,一個信息幀中的每八位的字節(jié)作為兩個ASCII字符傳輸;②RTU模式,此模式將信息幀中的八位數(shù)據(jù)作為兩個4位16進制字符傳輸。相對于ASCII模式,RTU模式表示相同的信息時需要的位數(shù)較少,并且在相同通信速率下可以傳輸更大的數(shù)據(jù)流量。因此,智能控制器大多采用Modbus RTU規(guī)約[2]。
1.2 Modbus RTU傳輸過程
Modbus RTU信息幀的傳輸采用異步方式,以字節(jié)為單位。在主站和從站之間傳遞的典型通訊報文的信息幀格式如圖1所示。
圖1 Modbus RTU信息幀格式
Modbus RTU采用主-從方式的通訊方式[3],通信過程由主機首先發(fā)起,從機在正確接收數(shù)據(jù)之后將處理報文返回主機,主機可以通過廣播模式與從機進行數(shù)據(jù)傳輸,也可以利用不同功能碼修改從機內(nèi)存,實現(xiàn)數(shù)據(jù)雙向讀寫的功能。其查詢響應(yīng)流程如圖2所示。
圖2 Modbus RTU查詢響應(yīng)流程
2 循環(huán)冗余碼
CRC是數(shù)據(jù)通信領(lǐng)域中最常用的一種差錯校驗碼,其信息字段和校驗字段的長度可以任意選定,通過對數(shù)據(jù)進行多項式計算,并將得到的結(jié)果附在信息幀的后面,接收設(shè)備也執(zhí)行類似的算法,以保證數(shù)據(jù)傳輸?shù)恼_性和完整性。
生成多項式(Ploy):是發(fā)送方與接收方的一個約定;在發(fā)送方,利用生成多項式對信息多項式做模2除法生成校驗碼。在接收方利用生成多項式對收到的編碼多項式做模2除法檢測和確定錯誤位置。在編碼理論中,多項式用碼組來表示,多項式的系數(shù)即為碼組的碼元。例如碼組 1000 0000 0000 0101表示的多項式為1·x15+0·x14+0·x13+0·x12+0·x11+0·x10+0·x9+0·x8+0·x7+0·x6+0·x5+0·x4+0·x3+1·x2+0·x1+1·x0,即 x16+x15+x2+1。
假設(shè)原始信息幀多項式為O(x);發(fā)送方和接收方約定的生成多項式為G(x),G(x)最高次冪加為m;O(x)與G(x)做模2除法得到CRC碼記為R(x);發(fā)送方發(fā)送數(shù)據(jù)的多項式(拼接了CRC碼的信息幀)為M(x)。發(fā)送方信息幀編碼規(guī)則為:將原始信息幀多項式O(x)乘以xm(即對應(yīng)的二進制碼序列左移m位),再除以生成多項式G(x),所得余式即為R(x)。用公式表示為M(x)= xmO(x)+R(x)。接收方校驗規(guī)則為:將接收到的信息幀多項式M(x)除以生成多項式G(x),得到一個余數(shù),如果這個余數(shù)為0,則說明傳輸過程中無錯誤發(fā)生;如果不為0,則說明傳輸過程中發(fā)生錯誤。
特別指出,在計算CRC過程中除法采用的是計算機模二除法,即除數(shù)和被除數(shù)做異或運算。進行異或運算時除數(shù)和被除數(shù)最高位對齊,按位異或[4]。
根據(jù)CRC生成原理,可以得到直接算法(按位計算CRC)。以CRC-16為例,其流程如下:
(1)預(yù)置一個16位寄存器(用register表示)全為0(16代表生成的CRC碼的位數(shù));
(2)將待測數(shù)據(jù)左移16位,用0補位(左移16位確保待測數(shù)據(jù)每一位都能被除到);
(3)將register中的值左移1位,并讀入待測數(shù)據(jù)的1位存入register左移后空出的位置;
(4)判斷步驟(3)中register左移1位操作中移出的是否是1:若移出的是1,則生成多項式(CRC-16:Ploy=x16+x15+x2+1,簡記為0x8005)和寄存器進行除法運算(即按位異或),結(jié)果放入register中;若移出的是0,則返回執(zhí)行步驟(3);
(5)重復(fù)步驟(3)和(4),直至待測數(shù)據(jù)的每一位均與register進行了除法運算,這樣register中的數(shù)值即為所要的CRC-16校驗碼。
3 字節(jié)型CRC-16算法的原理與實現(xiàn)
3.1 字節(jié)型CRC-16原理分析
數(shù)據(jù)通信中對實時性要求較高,若按位求CRC則耗時較多,不能滿足通信控制要求。相比,按字節(jié)計算CRC,一次計算8位數(shù)據(jù),耗時則大大減少。另外在數(shù)字通信系統(tǒng)中一般是對一幀數(shù)據(jù)進行CRC校驗,而字節(jié)是幀的基本單位,采用按字節(jié)算法(也叫表驅(qū)動算法)將提高運算效率,從而確保通信的實時性。
字節(jié)型CRC-16算法的思路是先離線構(gòu)造一個單字節(jié)信息的余式編碼表,根據(jù)此余式編碼表進行查表及異或運算即可求得多字節(jié)信息的余式。由于單字節(jié)信息共8個二進制碼元,則總共28即256種不同的組合。在Modbus RTU中CRC-16生成多項式為G(x)= x16+x15+x2+1(簡記為0x8005),每種組合經(jīng)生成多項式G(x)除,就產(chǎn)生16位即兩個字節(jié)的CRC校驗碼表共占512個字節(jié)[5]。
字節(jié)型CRC算法在實際應(yīng)用中有2個問題需要考慮:
(1)由于待測數(shù)據(jù)的內(nèi)容和長度是隨機的,若register初始值為0,則待測字節(jié)是單字節(jié)0x00和待測字節(jié)是N字節(jié)的0x00計算出來的CRC-16值都是0,如此則字節(jié)型CRC值無意義。將register的初始值設(shè)為0xFFFF,則可以避免這個問題;
(2)硬件數(shù)據(jù)通信時,每個字節(jié)在發(fā)送時是先發(fā)送最低位(LSB)的。這樣在計算單字節(jié)CRC時需要對單字節(jié)內(nèi)部的比特(bit)進行顛倒處理(字節(jié)順序不用顛倒)。
然而,在對單字節(jié)處理前還需先進行顛倒處理,顯然消耗時間較多。
結(jié)合本文前述,單字節(jié)處理由最高位(MSB)到最低位(LSB)依次左移與生成多項式相除,那么當(dāng)單字節(jié)內(nèi)容為最低位(LSB)到最高位(MSB)時,則只需將生成多項式顛倒,由原來0x8005(1000 0000 0000 0101)逆序為0xA001(1010 0000 0000 0001),處理順序由左移改為右移。最后將所得CRC-16碼高字節(jié)與低字節(jié)交換得到的即為正確的CRC-16校驗碼。
3.2 字節(jié)型CRC-16實現(xiàn)
3.2.1 CRC-16查詢表的生成算法
算法流程如下:
(1)預(yù)設(shè)一個16位寄存器,所有數(shù)位均為1(即值為0xFFFF);待測數(shù)據(jù)組合0x00~0xFF;
(2)該16位寄存器與待測數(shù)據(jù)進行“異或”運算,運算結(jié)果仍存該16位寄存器中;
(3)將該16位寄存器右移一位,用0填補最高位;
(4)檢測移出位是1還是0。若是1,則生成多項式0xA001和該寄存器進行“異或”運算。若是0,則返回步驟(3);
(5)重復(fù)步驟(3)和(4),直到右移8次,這樣待測數(shù)據(jù)的8位數(shù)據(jù)全部進行了處理;
(6)將得到的16位寄存器的高、低字節(jié)進行交換,得到的16位寄存器內(nèi)容即為CRC-16校驗碼;
(7)將待測數(shù)據(jù)依次設(shè)置為0x00~0xFF(256種),按照步驟(2)~(5)各計算一遍,得到的256個CRC-16校驗碼組合在一起即為CRC-16查詢表。
根據(jù)上述流程,編寫程序生成表(記為byteCRC16Table [256])如圖3所示。
3.2.2 依據(jù)查詢表實現(xiàn)CRC-16
算法流程如下:
(1)將寄存器右移8位;
(2)將步驟(1)中移出的一個字節(jié)內(nèi)容和待測數(shù)據(jù)中的一個字節(jié)內(nèi)容做“異或”運算,得到一個查詢表的索引值。
(3)將步驟(2)中索引值所指向的表值和寄存器做“異或”運算。
(4)重復(fù)步驟(1)~(3),直至待測數(shù)據(jù)所有字節(jié)都處理完成。
最后寄存器中的內(nèi)容即為所求的CRC-16校驗碼。
圖3 程序生成表
關(guān)鍵代碼如下:
DWORD reg16=0xFFFF;
//reg16為寄存器,初始值為0xFFFF
for (i=0;i //byteLength為待測數(shù)據(jù)的字節(jié)長度 tableIndex=(reg16^(*(ptrByteMeg+i)))&0xFF; //tableIndex為表索引值 //ptrByteMeg是指向待測數(shù)據(jù)的指針 reg16=byteCRC16Table[tableIndex]^(reg16>>8); } //byteCRC16Table是查詢表名 4 結(jié) 語 本文通過對Modbus RTU協(xié)議及CRC原理的分析,給出了Modbus RTU協(xié)議中CRC-16按字節(jié)快速計算的算法及源代碼。該方法已在某智慧能源管理系統(tǒng)的終端數(shù)據(jù)采集中運用,取得了理想的應(yīng)用效果,確保了數(shù)據(jù)采集的可靠性。同時本文也為初次進行Modbus RTU通信設(shè)計人員快速了解及運用CRC校驗提供了參考。 參考文獻(xiàn) [1]劉海濤,馬建,熊永平.物聯(lián)網(wǎng)技術(shù)應(yīng)用[M].北京:機械工業(yè)出版社,2011. [2]呂國芳,唐海龍,李進.基于Modbus RTU的串口調(diào)試軟件的實現(xiàn)[J].計算機技術(shù)與發(fā)展,2009(9):236-239. [3]何建忠.基于Modbus協(xié)議的工業(yè)網(wǎng)關(guān)設(shè)計與實現(xiàn)[D].內(nèi)蒙古:內(nèi)蒙古大學(xué),2013. [4]馬吉明,程立輝,張素智.字節(jié)型CRC算法分析與實現(xiàn)[J].微計算機信息2006,22(9):234-236. [5]馬寶甫.CRC校驗快速查表算法及其應(yīng)用[J].計算機工程與應(yīng)用1997(7):28-31.