Modbus通信協(xié)議的FPGA實(shí)現(xiàn)
掃描二維碼
隨時(shí)隨地手機(jī)看文章
現(xiàn)場總線是一種應(yīng)用于生產(chǎn)現(xiàn)場,在現(xiàn)場設(shè)備之間,現(xiàn)場設(shè)備與控制裝置之間實(shí)現(xiàn)雙向、串行、多節(jié)點(diǎn)數(shù)字通信的技術(shù)。Modbus協(xié)議其節(jié)點(diǎn)安裝數(shù)量非常多,安裝的地區(qū)遍及世界各地。
今天的FPGA可包含內(nèi)嵌乘法器、專用計(jì)算例程和片上RAM等,加上FPGA的并行性,其結(jié)果比最快的DSP芯片還要快上500倍乃至更多。隨著FPGA價(jià)格不斷下降,甚至最小的器件都足以實(shí)現(xiàn)一個(gè)集成可選定制I/O功能的軟處理器核。可見,F(xiàn)PGA對(duì)嵌入控制應(yīng)用越來越具有吸引力。
目前Modbus協(xié)議實(shí)現(xiàn)方式多為單片機(jī)和PLC,隨著FPGA的廣泛應(yīng)用,研究Modbus現(xiàn)場總線的FPGA解決方案有很大的實(shí)用價(jià)值。
1 Modbus協(xié)議簡介
Modbus串行鏈路系統(tǒng)可以使用不同的物理接口(RS 485,RS 232),最常用的是RS 485兩線制接口。為了提高通信模塊在工業(yè)應(yīng)用中的抗干擾性和穩(wěn)定性,接口芯片和FPGA核心模塊之間應(yīng)加入高速光耦進(jìn)行隔離,總線兩端處放置線路終端電阻,采用屏蔽雙絞線作為通信線等。
在串行鏈路上,Modbus RTU(Remote Terminal Unit)模式報(bào)文中每8個(gè)位字節(jié)含有兩個(gè)4位十六進(jìn)制字符,這種模式的主要優(yōu)點(diǎn)是較高的數(shù)據(jù)密度,在相同的波特率下比ASCII模式有更高的吞吐率。RTU模式每個(gè)字節(jié)(11位)的格式如圖1所示,支持奇、偶和無校驗(yàn),使用無校驗(yàn)時(shí)要求2個(gè)停止位。Modbus RTU幀最大為256B,由發(fā)送設(shè)備將Modbus報(bào)文構(gòu)造為帶有已知起始和結(jié)束標(biāo)記的幀,報(bào)文幀由時(shí)長至少為3.5個(gè)字符時(shí)間的空閑間隔區(qū)分,整個(gè)報(bào)文幀必須以連續(xù)的字符流發(fā)送,如果兩個(gè)字符之間的空閑間隔大于1.5個(gè)字符時(shí)間,則報(bào)文幀被認(rèn)為不完整被接收節(jié)點(diǎn)丟棄,如圖1所示。
在應(yīng)用層上,Modbus是一個(gè)請(qǐng)求/應(yīng)答協(xié)議,并且提供功能碼規(guī)定的服務(wù)。有三類Modbus功能碼:公共碼、用戶定義碼和保留碼,大多數(shù)情況下只用公共碼,其主要包括比特(線圈)訪問、16 b(寄存器)訪問、文件記錄訪問、診斷和其他信息訪問。
2 Modbus RTU通信協(xié)議接口設(shè)計(jì)
2.1 接口功能及模塊劃分
Modbus RTU接口框圖及輸入、輸出引腳示意圖如圖2所示。
在某一確定的主時(shí)鐘頻率、通信波特率和奇偶校驗(yàn)方式下,通過設(shè)置CE_Modbus和R_Tn的狀態(tài),可以控制該接口模塊處于接收Modbus協(xié)議幀模式、發(fā)送Modbus協(xié)議幀模式或輸入/輸出寄存器操作模式,如表1所示。
典型的波特率和奇偶校驗(yàn)位設(shè)置如表2、表3所示。這兩組控制信號(hào)可以從端口引出接到撥碼開關(guān),然后可以通過調(diào)節(jié)撥碼開關(guān)來靈活控制該設(shè)備奇偶性與波特率,也可以通過寄存器配置方式控制。
2.2 接收過程
(1)系統(tǒng)處于接收Modbus協(xié)議幀模式下之后,清零標(biāo)志位和定時(shí)器,然后啟動(dòng)定時(shí)器,如果檢測(cè)到有串口輸入數(shù)據(jù),則清零定時(shí)器,如果沒有檢測(cè)到串口輸入數(shù)據(jù)且定時(shí)器第一次計(jì)時(shí)到3.5個(gè)字符時(shí)間,置幀起始標(biāo)志;
(2)把接收到的第一個(gè)字符放入接收緩沖寄存器的0x00地址(協(xié)議幀最長為256 B,故接收緩沖大小為256 B,地址為8 b),置已開始接收標(biāo)志;
(3)將接收到的正確字符依次放入接收緩沖寄存器中,即地址每次加1,每接收完一個(gè)字符之后清零定時(shí)器;如果在接收字符時(shí)檢查到起始錯(cuò)誤(起始位沒有持續(xù)波特率所對(duì)應(yīng)bit時(shí)間的一半),奇偶校驗(yàn)錯(cuò)誤,或者幀錯(cuò)誤(停止位為O),則丟棄該字符,重新同步起始位;[!--empirenews.page--]
(4)如果檢測(cè)到兩個(gè)字符時(shí)間間隔大于1.5個(gè)字符時(shí)間,則重置幀起始標(biāo)志,把下一個(gè)接收到的字符放入接收緩沖寄存器的0x00地址,再繼續(xù)步驟(3);
(5)當(dāng)檢測(cè)到?jīng)]有字符輸入且定時(shí)器第二次檢測(cè)到3.5個(gè)字符時(shí)間,置協(xié)議幀接收完全標(biāo)志;
(6)把接收緩沖區(qū)接收的數(shù)據(jù)作CRC校驗(yàn),如果校驗(yàn)不正確,置幀起始標(biāo)志,轉(zhuǎn)到步驟(3),繼續(xù)等待接收;如果是基于該接口的主Modbus協(xié)議設(shè)備,一般應(yīng)設(shè)置超時(shí)時(shí)間,以避免無限等待;如果校驗(yàn)正確,則Re_finish發(fā)出一個(gè)脈沖,認(rèn)為接收了一個(gè)在數(shù)據(jù)鏈路層上正確的Mod-bus協(xié)議幀。
對(duì)于幀錯(cuò)誤(停止位為0)標(biāo)志FE,奇偶校驗(yàn)錯(cuò)誤標(biāo)志PE,最后一個(gè)接收到的數(shù)據(jù)所在接收緩沖區(qū)中的位置Rebuf_end[7..O],對(duì)外并不必須,可以留出這些端口備用,所以用虛線表示。
2.3 輸入/輸出寄存器操作
接收緩沖數(shù)據(jù)寄存器和發(fā)送緩沖數(shù)據(jù)寄存器都采用雙口RAM實(shí)現(xiàn),這比寄存器實(shí)現(xiàn)要節(jié)省很多資源。為了保證對(duì)它們的操作是原子的,即為了避免同時(shí)對(duì)相同地址執(zhí)行寫操作,故要求當(dāng)CE_Modbus置低時(shí),外部才可以對(duì)輸入輸出寄存器執(zhí)行寫操作,此時(shí)接口內(nèi)部不會(huì)對(duì)接收/輸出寄存器執(zhí)行任何讀寫操作。
2.4 發(fā)送過程
(1)在發(fā)送模式使能之前,應(yīng)先處于輸入/輸出寄存器模式,通過Trbuf_data[7..0],Trbuf_add[7..0],Trbuf_wren把待發(fā)送的不包括兩位CRC校驗(yàn)的Modbus協(xié)議幀從地址0x00依次寫入發(fā)送緩沖寄存器中,然后使能Ld_TbNCE信號(hào)(一個(gè)時(shí)鐘周期),同時(shí)存入發(fā)送緩存寄存器所裝最后一個(gè)數(shù)據(jù)的地址,然后把該接口置于發(fā)送Modbus協(xié)議幀模式。
(2)發(fā)送模塊先對(duì)發(fā)送數(shù)據(jù)緩沖寄存器中的所有數(shù)做CRC-16校驗(yàn),然后把計(jì)算所得結(jié)果按低位在前高位在后的順序依次放到用Ld_TbNCE信號(hào)鎖存的地址的下兩個(gè)地址位置處。
(3)發(fā)送模塊從發(fā)送數(shù)據(jù)緩沖寄存器Ox00開始,依次讀出數(shù)據(jù)并按所給的波特率發(fā)送出去,如果要求奇偶校驗(yàn),則發(fā)送完數(shù)據(jù)之后加上計(jì)算所得的奇偶校驗(yàn)位發(fā)送出去。
(4)當(dāng)發(fā)送完最后一個(gè)數(shù)據(jù)即CRC-16的高8位數(shù)據(jù)之后,Tr_finish發(fā)出一個(gè)脈沖表示發(fā)送完畢。
3 接口模塊實(shí)現(xiàn)
3.1 波特率發(fā)生器
波特率發(fā)生器就是一個(gè)分頻器,根據(jù)系統(tǒng)時(shí)鐘分別發(fā)出位時(shí)鐘(Tx_clk)和1/16位時(shí)鐘(RX_clkl6)。由于系統(tǒng)的時(shí)鐘周期可能不同,為了模塊的通用性,該模塊用一個(gè)類屬(Generic)語句產(chǎn)生各種分頻系數(shù)。為了保證同步設(shè)計(jì),產(chǎn)生的位時(shí)鐘和1/16位時(shí)鐘作為控制信號(hào)在主時(shí)鐘的驅(qū)動(dòng)下控制其他模塊。
3.2 接收模塊
接收模塊組包括同步濾波模塊、接收機(jī)模塊、接收控制模塊、接收狀態(tài)寄存器模塊、時(shí)間標(biāo)志產(chǎn)生模塊等。
Modbus網(wǎng)絡(luò)中設(shè)備是運(yùn)行在不相關(guān)時(shí)鐘上的,為了避免亞穩(wěn)態(tài)現(xiàn)象,要求通信信號(hào)進(jìn)入FPGA時(shí)通過兩個(gè)級(jí)聯(lián)的寄存器。異步輸入信號(hào)必須在足夠的時(shí)間內(nèi)保持?jǐn)?shù)據(jù)有效,從而保證被目標(biāo)時(shí)鐘域檢測(cè)到,在接收端則認(rèn)為最少是大于幾個(gè)脈沖寬度的信號(hào)才是應(yīng)該被檢測(cè)到的信號(hào),于是在接收端加入濾波模塊,具體算法如下:連續(xù)3次檢測(cè)到為高(或低)電平時(shí),才往接收寄存器寫入高(或低)電平,否則保持原來檢測(cè)到的電平,不到3個(gè)脈沖寬度的信號(hào)被過濾。顯然,同步濾波模塊引入了5個(gè)時(shí)鐘的延遲,但這樣的延時(shí)對(duì)于Modbus協(xié)議來說可以忽略。
接收機(jī)模塊是一個(gè)改進(jìn)的UART接收模塊,其工作流程如下:
(1)當(dāng)檢測(cè)到起始位時(shí),繼續(xù)讀取其他位并通過移位把它們移人接收移位寄存器RSR中;
(2)當(dāng)所有的數(shù)據(jù)位和停止位都接收完畢后,置RDR寄存器滿標(biāo)志RDRF位為1;
(3)檢測(cè)停止位和奇偶校驗(yàn)位,如果發(fā)現(xiàn)錯(cuò)誤置相關(guān)錯(cuò)誤標(biāo)志位;
(4)如果所接收數(shù)據(jù)正確,RSR中數(shù)據(jù)載入到接收數(shù)據(jù)寄存器RDR中,清除錯(cuò)誤標(biāo)志。
從Rxd_syn上進(jìn)入的比特流與本地的位時(shí)鐘不是同步的,為了避免可能在錯(cuò)誤的時(shí)間讀取一些位,在每個(gè)比特時(shí)間采樣16次,在時(shí)鐘Rx_-clkl6的每個(gè)上升沿采樣,為了保證最大可行度,在理想情況下將在每比特時(shí)間中間進(jìn)行采樣。首先判斷起始位,當(dāng)檢測(cè)Rxd_syn至少連續(xù)半個(gè)位時(shí)鐘為低電平時(shí),即從第一次檢測(cè)到低電平之后,再連續(xù)9次檢測(cè),如果Rxd_syn為低電平的次數(shù)大于等于8次,則認(rèn)為起始位到來,此時(shí)應(yīng)該在起始位中間后兩個(gè)Rx_clkl6處。之后每隔16個(gè)Rx_clkl6時(shí)鐘周期在14,15,16個(gè)上升沿到來時(shí)分別采樣,然后對(duì)3次采樣結(jié)果取至少兩次相等的數(shù)據(jù)作為所接收到的值,以保證接收數(shù)據(jù)的準(zhǔn)確性。8個(gè)數(shù)據(jù)位采集完畢之后,根據(jù)Sel_parity[1..O]信號(hào)判斷是否奇偶校驗(yàn),如果有校驗(yàn)需求,則對(duì)第9個(gè)數(shù)據(jù)位的數(shù)據(jù)同樣做3次采樣取兩次相同值作為接收到的奇偶校驗(yàn)位,同時(shí)計(jì)算奇偶校驗(yàn)結(jié)果。在停止位(不包括起始位,無校驗(yàn)時(shí)為第9位,有校驗(yàn)時(shí)為第10位)到來時(shí),同樣經(jīng)過3次采樣,但是只要檢測(cè)到1位為高就認(rèn)為停止位正確,為了減少狀態(tài)機(jī)數(shù)量,可以在停止位到來時(shí)比較計(jì)算所得奇偶校驗(yàn)位和接收到的奇偶校驗(yàn)位從而判定接收數(shù)據(jù)是否奇偶校驗(yàn)錯(cuò)誤。由于接收控制器一定會(huì)讀取前一個(gè)數(shù)據(jù)字節(jié)并清零RDRF,所以常見的UART里的超限(overrun)錯(cuò)誤這里并沒有出現(xiàn)。圖3為用QuartusⅡ軟件自帶仿真器仿真結(jié)果。[!--empirenews.page--]
3.3 發(fā)送模塊
發(fā)送模塊包括發(fā)送控制模塊,發(fā)送機(jī)模塊,發(fā)送狀態(tài)寄存器模塊等。
發(fā)送機(jī)模塊是基于普通UART發(fā)送原理設(shè)計(jì),其發(fā)送過程如下:
(1)等待TDRE=‘1’,即等待發(fā)送數(shù)據(jù)寄存器(TDR)為空,隨后TDR中載入一個(gè)字節(jié)數(shù)據(jù),并把TDRE清零。
(2)根據(jù)波特率設(shè)置Sel_baud[1..0]對(duì)TDR里的數(shù)據(jù)進(jìn)行奇偶校驗(yàn)計(jì)算。
(3)把TDR里的數(shù)據(jù)放入發(fā)送移位寄存器TSR的1~8位,TSR第O位放起始位(‘O’),TSR第9位放入奇偶校驗(yàn)位或者停止位(‘1’)。
(4)通過對(duì)TSR右移,一位一位地發(fā)送出9位數(shù)據(jù)比特,最后發(fā)送停止位(‘1’)。
3.4 CRC模塊
CRC模塊包括接收CRC控制模塊,發(fā)送CRC控制模塊,CRC產(chǎn)生模塊三部分。
生成CRC的過程為:
(1)將一個(gè)16位寄存器裝入十六進(jìn)制FFFF(全1),將之稱作CRC寄存器。
(2)將報(bào)文的第一個(gè)8位字節(jié)與16位CRC寄存器的低字節(jié)異或,結(jié)果置于CRC寄存器。
(3)將CRC寄存器右移1位(向LSB方向),MSB充零,提取并檢測(cè)LSB。
(4)如果LSB為0:重復(fù)步驟(3)(另一次移位);如果LSB為1:對(duì)CRC寄存器異或多項(xiàng)式值0xA00l(1010000000000001)。
(5)重復(fù)步驟(3)和(4),直到完成8次移位。當(dāng)做完此操作后,將完成對(duì)8位字節(jié)的完整操作。
(6)對(duì)報(bào)文中的下一個(gè)字節(jié)重復(fù)步驟(2)~(5),繼續(xù)此操作直至所有報(bào)文被處理完畢。
(7)CRC寄存器中的最終內(nèi)容為CRC值。
這種方式計(jì)算CRC值的時(shí)間比其他方式計(jì)算CRC(比如查表法等)的時(shí)間稍微要長,但是它節(jié)省了資源,比如查表法計(jì)算CRC需要一個(gè)數(shù)組來存放所有可能的CRC結(jié)果值。圖5為對(duì)數(shù)據(jù)串“010300000001”(十六進(jìn)制)CRC-16運(yùn)算的仿真時(shí)序圖,時(shí)鐘周期為50 MHz,由圖可見,整個(gè)計(jì)算時(shí)間在2.5 μs內(nèi),估算一個(gè)含有240個(gè)字符的消息,CRC校驗(yàn)總時(shí)間約為2.5μs×(240/6)=100μs,這樣長的校驗(yàn)計(jì)算時(shí)間對(duì)于Modbus協(xié)議來說是完全可以接受的。
4 基于該接口的MODBUS從站協(xié)處理器實(shí)現(xiàn)
協(xié)處理器框圖如圖6所示。
從站協(xié)處理器控制模塊程序控制過程如下:
(1)置CE_Modbus為‘1’,把MAX485芯片信號(hào)輸出置低,即控制RS 485接口芯片處于接收狀態(tài)。
(2)等待一段延遲時(shí)間(RS 485接口芯片穩(wěn)定時(shí)間),使能Modbus協(xié)議接口模塊即置CE_Modbus為‘1’,并置接收Modbus協(xié)議幀模式。
(3)如果接收到一個(gè)完整的幀(消息),則轉(zhuǎn)到步驟(4),如果沒接收到一個(gè)完整的消息,一直處于等待狀態(tài)。
(4)先置CE_Modbus為‘O’,再解釋接收緩沖寄存器里消息,等待消息處理完畢,如果消息不是發(fā)往該從站或者為廣播消息,則轉(zhuǎn)到步驟(2);否則把信號(hào)輸出置高,轉(zhuǎn)到步驟(5)。
(5)等待一段延遲時(shí)間,使能Modbus協(xié)議接口模塊即置CE_Modbus為‘1’,并置發(fā)送Modbus協(xié)議幀模式。[!--empirenews.page--]
(6)等待發(fā)送完成,轉(zhuǎn)到步驟(1)。
解釋模塊主要由解釋控制模塊、分析模塊、各功能碼解釋模塊、錯(cuò)誤功能碼處理模塊組成。分析模塊首先分析接收消息起始兩個(gè)字節(jié),即地址碼和功能碼。如果地址為廣播消息地址(地址為0)或者地址碼和本從站地址不相等,則不處理本消息,解釋控制模塊發(fā)出解釋完畢并置不響應(yīng)信號(hào)為“1”,頂層控制模塊繼續(xù)處于等待接收消息狀態(tài)。如果功能碼為非支持功能碼,則選擇錯(cuò)誤功能代碼處理模塊;如果為某一支持的功能碼,則選擇相應(yīng)的功能模塊解釋接收消息,按照功能碼要求解碼(例如讀/寫某一指定寄存器或者線圈)。處理完之后把相應(yīng)的異常碼響應(yīng)消息或者正常響應(yīng)消息寫入Modbus協(xié)議接口模塊里的發(fā)送緩沖寄存器里,完畢之后通過Ld_TbNCE信號(hào)把發(fā)送緩沖寄存器鎖存消息的末地址(不帶CRC校驗(yàn)位)Trbuf_add[7..O](保證在Ld_TbNCE有效時(shí)它為末地址)存入Modbus協(xié)議接口模塊,發(fā)出解釋完畢信號(hào),不響應(yīng)信號(hào)置“O”,之后由頂層控制模塊控制接口模塊發(fā)送響應(yīng)消息。對(duì)于某些功能碼,比如01碼和02碼,03碼和04碼,由于對(duì)它們的解釋差別很小,可以共用一個(gè)模塊,達(dá)到節(jié)省資源的目的。對(duì)于特定的系統(tǒng),完全可以選擇某一些功能碼甚至某一個(gè)功能碼,而達(dá)到需求,故這里采用這種模塊化方式,可以很容易在不改變其他功能模塊的情況下刪除不需要的功能碼模塊或者增加新需要的功能碼模塊。
該協(xié)處理器與從設(shè)備其他部分接口僅僅為雙口RAM,從設(shè)備完全被映射為寄存器組的抽象,這比啟用寄存器直接實(shí)現(xiàn)要節(jié)省邏輯資源。由于這些雙口RAM是完全透明的,用戶可以根據(jù)整個(gè)Modbus系統(tǒng)需要自定義各個(gè)寄存器的實(shí)際含義。Modbus主設(shè)備可以在任何時(shí)候隨機(jī)地訪問這些寄存器組。Modbus從設(shè)備控制、執(zhí)行模塊對(duì)這些寄存器組的訪問需要尋求一種較好的方式,由于FPGA的高速度及并行機(jī)制,一般情況下可以采取輪詢的機(jī)制即可滿足工業(yè)實(shí)時(shí)性需求。對(duì)于某些特殊情況需要更高優(yōu)先級(jí)的控制方式,也可以采取中斷方式。如圖7所示,可以通過雙口RAM的地址線和寫使能信號(hào)線進(jìn)行中斷檢測(cè)和沖突檢測(cè):當(dāng)從站協(xié)處理模塊對(duì)某些特定寄存器讀/寫完畢之后,產(chǎn)生一個(gè)中斷信號(hào),對(duì)某些可能存在從站協(xié)處理器模塊和從設(shè)備控制執(zhí)行模塊都要對(duì)其進(jìn)行寫操作的寄存器,如果有寫操作同時(shí)發(fā)生,則從設(shè)備控制執(zhí)行模塊應(yīng)該等待從站協(xié)處理器寫完再寫,以保證寫操作是原子的。圖8為03碼應(yīng)答的完整仿真時(shí)序。
圖9為示波器在通信線路上檢測(cè)到的波形,圖9(a)展現(xiàn)了一系列連續(xù)幀通信實(shí)況;圖9(b)展現(xiàn)某一應(yīng)答情況,可以看出主機(jī)和從機(jī)通信電平有差異,但都在RS 485范圍之內(nèi);圖9(c)展現(xiàn)了某一幀的具體情況。
5 結(jié)語
該設(shè)計(jì)基于Altera公司FPGA,首先設(shè)計(jì)了一個(gè)可以通用于Modbus主設(shè)備和從設(shè)備的Modbus協(xié)議接口,然后基于該協(xié)議接口設(shè)計(jì)了一個(gè)通用的Modbus從設(shè)備協(xié)處理器,該接口也可以方便地用于主協(xié)議設(shè)備中。本設(shè)計(jì)通過了多款FPGA芯片的綜合驗(yàn)證,并與WEINVIEW公司觸摸屏MT-506MV和INVT公司CHF1OO-5R5G/7R5P變頻器成功通信。目前該設(shè)計(jì)已在某工業(yè)EPS系統(tǒng)和某沖擊試驗(yàn)臺(tái)中穩(wěn)定運(yùn)行半年,可見其有一定應(yīng)用前景。