Modbus RTU協議實現

Modbus協議簡介

Modbus串行鏈路系統可以使用不同的物理接口(RS 485,RS 232),最常用的是RS 485兩線制接口。爲了提高通信模塊在工業應用中的抗干擾性和穩定性,接口芯片和FPGA核心模塊之間應加入高速光耦進行隔離,總線兩端處放置線路終端電阻,採用屏蔽雙絞線作爲通信線等。
在串行鏈路上,Modbus RTU(Remote Terminal Unit)模式報文中每8個位字節含有兩個4位十六進制字符,這種模式的主要優點是較高的數據密度,在相同的波特率下比ASCII模式有更高的吞吐率。RTU模式每個字節(11位)的格式如圖1所示,支持奇、偶和無校驗,使用無校驗時要求2個停止位。Modbus RTU幀最大爲256B,由發送設備將Modbus報文構造爲帶有已知起始和結束標記的幀,報文幀由時長至少爲3.5個字符時間的空閒間隔區分,整個報文幀必須以連續的字符流發送,如果兩個字符之間的空閒間隔大於1.5個字符時間,則報文幀被認爲不完整被接收節點丟棄,如圖所示。
在這裏插入圖片描述
在應用層上,Modbus是一個請求/應答協議,並且提供功能碼規定的服務。有三類Modbus功能碼:公共碼、用戶定義碼和保留碼,大多數情況下只用公共碼,其主要包括比特(線圈)訪問、16 b(寄存器)訪問、文件記錄訪問、診斷和其他信息訪問。

CRC校驗

  1. 循環校驗碼(CRC碼)
    數據通信領域中最常用的一種差錯校驗碼,其特徵是信息字段和校驗字段的長度可以任意選定。這個校驗方式的根本思想是在發送數據的後面拼接上一些額外的數據位,使得這個拼接之後的數據可以被一個固定的數模2整除(這裏的模2整除是一種區別於普通的除法的運算方法,也不難理解),之後將數據發送……接收端同樣將整個拼接後的數據與之前確定的固定的數據做模2除法,若能整除,則說明傳輸過程沒有出錯,若不能整除,則可以根據餘數判斷是哪一位發生了錯誤。
  2. 生成CRC碼的基本原理
    任意一個由二進制位串組成的代碼都可以和一個係數僅爲‘0’和‘1’取值的多項式一一對應。例如:代碼1010111對應的多項式爲x6+x4+x2+x+1,而多項式爲x5+x3+x2+x+1對應的代碼101111。標準CRC生成多項式如下表:
    在這裏插入圖片描述CRC校驗是前面幾段數據內容的校驗值,爲一個16位數據,發送時,低8位在前,高8位在末使用相同的計算方法計算出信息字段的校驗碼,對比接收到的實際校驗碼,如果相等及信息正確,不相等則信息錯誤;或者將接受到的所有信息除多項式,如果能夠除盡,則信息正確。
  3. CRC-16校驗碼的計算方法
    計算法
    (1).預置1個16位的寄存器爲十六進制FFFF(即全爲1),稱此寄存器爲CRC寄存器;
    (2).把第一個8位二進制數據(既通訊信息幀的第一個字節)與16位的CRC寄存器的低8位相異或,把結果放於CRC寄存器,高八位數據不變;
    (3).把CRC寄存器的內容右移一位(朝低位)用0填補最高位,並檢查右移後的移出位;
    (4).如果移出位爲0:重複第3步(再次右移一位);如果移出位爲1,CRC寄存器與多項式A001【 (CRC-16)8005按位顛倒後的結果】(1010 0000 0000 0001)進行異或;
    (5).重複步驟3和4,直移8次,這樣整個8位數據全部進行了處理;
    (6).重複步驟2到步驟5,進行通訊信息幀下一個字節的處理;
    (7).將該通訊信息幀所有字節按上述步驟計算完成後,得到的16位CRC寄存器的高、低字節進行交換;
    (8).最後得到的CRC寄存器內容即爲:CRC碼。
    //表示計算一個字節的校驗值,實際收到多少個字節數,就循環調用該計算程序多少次
    reg [7:0] cnt_reg,cnt_data,x;
    reg signal_CRC_start;
    reg [15:0] CRC;
    always@(posedge clk100m or negedge rst_n)
    begin
    if( !rst_n ) begin
        CRC <= 16'hFFFF;
    end
    else begin
        if(rx_done )  begin                 //表收到一個完整的字節
            CRC[7:0] = CRC[7:0] ^ rx_byte;
            signal_CRC_start <= 1;         //該字節校驗值計算開始標誌
            cnt_data <= cnt_data + 1;      //收到字節數+1
        end
        else begin
            if(cnt_reg == 8)  begin      	//該字節的8位校驗值全部計算完
                signal_CRC_start <= 0;
                cnt_reg <= 0;
            end
            else
                if(signal_CRC_start == 1)begin //對8位依次計算
                    cnt_reg = cnt_reg +1;
                    if(CRC[0] == 0)
                        CRC = CRC>>1;
                    else
                        CRC = (CRC>>1)^ 16'hA001;
                end
        	end
    	end
    end
    
    查表法
    查表法是將移位異或的計算結果做成了一個表,就是將0~256放入一個長度爲16位的寄存器中的低八位,高八位填充0,然後將該寄存器與多項式0XA001按照上述3、4步驟,直到八位全部移出,最後寄存器中的值就是表格中的數據,高八位、低八位分別單獨一個表。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章