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