18luck网站

18luck网站電子設計 | 18luck网站Rss 2.0 會員中心 會員注冊
搜索: 您現在的位置: 18luck网站 >> 18luck平台 >> 單片機 >> 正文

RS485通信和Modbus協議

作者:佚名    文章來源:本站原創    點擊數:    更新時間:2017-2-12

  在工業(ye) 控製、電力通訊、智能儀(yi) 表等領域,通常情況下是采用串口通信的方式進行數據交換。最初采用的方式是RS232接口,由於(yu) 工業(ye) 現場比較複雜,各種電氣設備會(hui) 在環境中產(chan) 生比較多的電磁幹擾,會(hui) 導致信號傳(chuan) 輸錯誤。除此之外,RS232接口隻能實現點對點通信,不具備聯網功能,最大傳(chuan) 輸距離也隻能達到幾十米,不能滿足遠距離通信要求。而RS485則解決(jue) 了這些問題,數據信號采用差分傳(chuan) 輸方式,可以有效的解決(jue) 共模幹擾問題,最大距離可以到1200米,並且允許多個(ge) 收發設備接到同一條總線上。隨著工業(ye) 應用通信越來越多,1979年施耐德電氣製定了一個(ge) 用於(yu) 工業(ye) 現場的總線協議Modbus協議,現在工業(ye) 中使用RS485通信場合很多都采用Modbus協議,本節課我們(men) 要講解一下RS485通信和Modbus協議。

  單單使用一塊KST-51開發板是不能夠進行RS485實驗的,應很多同學的要求,把這節課作為(wei) 擴展課程講一下,如果要做本課相關(guan) 實驗,需要自行購買(mai) USB轉485通信模塊。

 1、RS485通信

  實際上在RS485之前RS232就已經誕生,但是RS232有幾處不足的地方:

  1、接口的信號電平值較高,達到十幾V,容易損壞接口電路的芯片,而且和TTL電平不兼容,因此和單片機電路接起來的話必須加轉換電路。

  2、傳(chuan) 輸速率有局限,不可以過高,一般到幾十Kb/s就到極限了。

  3、接口使用信號線和GND與(yu) 其他設備形成共地模式的通信,這種共地模式傳(chuan) 輸容易產(chan) 生幹擾,並且抗幹擾性能也比較弱。

  4、傳(chuan) 輸距離有限,最多隻能通信幾十米。

  5、通信的時候隻能兩(liang) 點之間進行通信,不能夠實現多機聯網通信。

  針對RS232接口的不足,就不斷出現了一些新的接口標準,RS485就是其中之一,他具備以下的特點:

  1、我們(men) 在講A/D的時候,講過差分信號輸入的概念,同時也介紹了差分輸入的好處,最大的優(you) 勢是可以抑製共模幹擾。尤其工業(ye) 現場的環境比較複雜,幹擾比較多,所以通信如果采用的是差分方式,就可以有效的抑製共模幹擾。而RS485就是一種差分通信方式,它的通信線路是兩(liang) 根,通常用A和B或者D+和D-來表示。邏輯“1”以兩(liang) 線之間的電壓差為(wei) +(0.2~6)V表示,邏輯“0”以兩(liang) 線間的電壓差為(wei) -(0.2~6)V來表示,是一種典型的差分通信。

  2、RS485通信速度快,最大傳(chuan) 輸速度可以達到10Mb/s以上。

  3、RS485內(nei) 部的物理結構,采用的是平衡驅動器和差分接收器的組合,抗幹擾能力也大大增加。

  4、傳(chuan) 輸距離最遠可以達到1200米左右,但是他的傳(chuan) 輸速率和傳(chuan) 輸距離是成反比的,隻有在100Kb/s以下的傳(chuan) 輸速度,才能達到最大的通信距離,如果需要傳(chuan) 輸更遠距離可以使用中繼。

  5、可以在總線上進行聯網實現多機通信,總線上允許掛多個(ge) 收發器,從(cong) 現有的RS485芯片來看,有可以掛32、64、128、256等不同個(ge) 設備的驅動器。

  RS485的接口非常簡單,和RS232所使用的MAX232是類似的,隻需要一個(ge) RS485轉換器,就可以直接和我們(men) 單片機的UART串行接口連接起來,並且完全使用的是和UART一致的異步串行通信協議。但是由於(yu) RS485是差分通信,因此接收數據和發送數據是不能同時進行的,也就是說它是一種半雙工通信。那我們(men) 如何判斷什麽(me) 時候發送,什麽(me) 時候接收呢?

  RS485類的芯片很多,這節課我們(men) 以MAX485為(wei) 例講解RS485通信,如圖1所示。

圖18-1 MAX485硬件接口

圖1 MAX485硬件接口

  MAX485是美信(Maxim)推出的一款常用RS485轉換器。其中5腳和8腳是電源引腳,6腳和7腳就是485通信中的A和B兩(liang) 個(ge) 引腳,而1腳和4腳分別接到我們(men) 單片機的RXD和TXD引腳上,直接使用單片機UART進行數據接收和發送。而2腳和3腳就是方向引腳了,其中2腳是低電平使能接收器,3腳是高電平使能輸出驅動器。我們(men) 把這兩(liang) 個(ge) 引腳連到一起,平時不發送數據的時候,保持這兩(liang) 個(ge) 引腳是低電平,讓MAX485處於(yu) 接收狀態,當需要發送數據的時候,把這個(ge) 引腳拉高,發送數據,發送完畢後再拉低這個(ge) 引腳就可以了。為(wei) 了提高RS485的抗幹擾性能,需要在靠近MAX485的A和B引腳之間並接一個(ge) 電阻,這個(ge) 電阻阻值從(cong) 100歐到1K都可以。

  在這裏我們(men) 還要介紹一下如何使用KST-51單片機開發板進行外圍擴展實驗。我們(men) 的開發板隻能把基本的功能給同學們(men) 做出來提供實驗練習(xi) ,但是同學們(men) 學習(xi) 的腳步不應該停留在這個(ge) 實驗板上。如果想進行更多的實驗,就可以通過單片機開發板的擴展接口進行擴展實驗。大家可以看到藍綠色的單片機座周圍有32個(ge) 插針,這32個(ge) 插針就是把單片機的32個(ge) IO引腳全部都引出來了。在原理圖上體(ti) 現出來的就是我們(men) 的J4、J5、J6、J7這4個(ge) 器件,如圖2所示。

 圖18-2 單片機擴展接口

圖2 單片機擴展接口

  這32個(ge) IO口不是所有的IO口都可以用來對外擴展,其中既作為(wei) 數據輸出,又可以作為(wei) 數據輸入的引腳是不可以用的,比如P3.2、P3.4、P3.6引腳,這三個(ge) 引腳是不可用的。比如P3.2這個(ge) 引腳,如果我們(men) 用來擴展,發送的信號如果和DS18B20的時序吻合,會(hui) 導致DS18B20拉低引腳,影響通信。除這3個(ge) IO口以外的其他29個(ge) IO口,都可以使用杜邦線接上插針,擴展出來使用。當然了,如果把當前的IO口應用於(yu) 擴展功能了,板子上的相應的功能就實現不了了,也就是說需要擴展功能和板載功能二選一。

  在進行RS485實驗中,我們(men) 通信用的引腳必須是P3.0和P3.1,此外還有一個(ge) 方向控製引腳,我們(men) 使用杜邦線將其連接到P1.7上去。RS485的另外一端,大家可以使用一個(ge) USB轉485模塊,用雙絞線把開發板和模塊上的A和B分別對應連起來,USB那頭插入電腦,然後就可以進行通信了。

  學習(xi) 了第13章的實用串口通信的方法和程序後,做這種串口通信的方法就很簡單了,基本是一致的。我們(men) 使用實用串口通信的思路,做了一個(ge) 簡單的程序,通過串口調試助手下發任意個(ge) 字符,單片機接收到後在末尾添加“回車+換行”符後再送回,在調試助手上重新顯示出來,先把程序貼出來。

  程序中需要注意的一點是:因為(wei) 平常都是將485設置為(wei) 接收狀態,隻有在發送數據的時候才將485改為(wei) 發送狀態,所以在UartWrite()函數開頭將485方向引腳拉高,函數退出前再拉低。但是這裏有一個(ge) 細節,就是單片機的發送和接收中斷產(chan) 生的時刻都是在停止位的一半上,也就是說每當停止位傳(chuan) 送了一半的時候,RI或TI就已經置位並且馬上進入中斷(如果中斷使能的話)函數了,接收的時候自然不會(hui) 存在問題,但發送的時候就不一樣了:當緊接這向SBUF寫(xie) 入一個(ge) 字節數據時,UART硬件會(hui) 在完成上一個(ge) 停止位的發送後,再開始新字節的發送,但如果此時不是繼續發送下一個(ge) 字節,而是已經發送完畢了,要停止發送並將485方向引腳拉低以使485重新處於(yu) 接收狀態時就有問題了,因為(wei) 這時候最後的這個(ge) 停止位實際隻發送了一半,還沒有完全完成,所以就有了UartWrite()函數內(nei) DelayX10us(5)這個(ge) 操作,這是人為(wei) 的增加了延時50us,這50us的時間正好讓剩下的一半停止位完成,那麽(me) 這個(ge) 時間自然就是由通信波特率決(jue) 定的了,為(wei) 波特率周期的一半。

/***********************RS485.c文件程序源代碼*************************/

#include <reg52.h>

#include <intrins.h>

 

sbit RS485_DIR = P1^7;  //RS485方向選擇引腳

 

bit flagOnceTxd = 0;  //單次發送完成標誌,即發送完一個(ge) 字節

bit cmdArrived = 0;   //命令到達標誌,即接收到上位機下發的命令

unsigned char cntRxd = 0;

unsigned char pdata bufRxd[40]; //串口接收緩衝(chong) 區

 

void ConfigUART(unsigned int baud)  //串口配置函數,baud為(wei) 波特率

{

    RS485_DIR = 0; //RS485設置為(wei) 接收方向

    SCON = 0x50;   //配置串口為(wei) 模式1

    TMOD &= 0x0F;  //清零T1的控製位

    TMOD |= 0x20;  //配置T1為(wei) 模式2

    TH1 = 256 - (11059200/12/32) / baud;  //計算T1重載值

    TL1 = TH1;     //初值等於(yu) 重載值

    ET1 = 0;       //禁止T1中斷

    ES  = 1;       //使能串口中斷

    TR1 = 1;       //啟動T1

}

unsigned char UartRead(unsigned char *buf, unsigned char len) //串口數據讀取函數,數據接收指針buf,讀取數據長度len,返回值為(wei) 實際讀取到的數據長度

{

    unsigned char i;

    

    if (len > cntRxd) //讀取長度大於(yu) 接收到的數據長度時,

    {

        len = cntRxd; //讀取長度設置為(wei) 實際接收到的數據長度

    }

    for (i=0; i<len; i++) //拷貝接收到的數據

    {

        *buf = bufRxd[i];

        buf++;

    }

    cntRxd = 0;  //清零接收計數器

    

    return len;  //返回實際讀取長度

}

void DelayX10us(unsigned char t)  //軟件延時函數,延時時間(t*10)us

{

    do {

        _nop_();

        _nop_();

        _nop_();

        _nop_();

        _nop_();

        _nop_();

        _nop_();

        _nop_();

        } while (--t);

}

void UartWrite(unsigned char *buf, unsigned char len) //串口數據寫(xie) 入函數,即串口發送函數,待發送數據指針buf,數據長度len

{

    RS485_DIR = 1;  //RS485設置為(wei) 發送

    while (len--)   //發送數據

    {

        flagOnceTxd = 0;

        SBUF = *buf;

        buf++;

        while (!flagOnceTxd);

    }

    DelayX10us(5);  //等待最後的停止位完成,延時時間由波特率決(jue) 定

    RS485_DIR = 0;  //RS485設置為(wei) 接收

}

 

void UartDriver() //串口驅動函數,檢測接收到的命令並執行相應動作

{

    unsigned char len;

    unsigned char buf[30];

 

    if (cmdArrived) //有命令到達時,讀取處理該命令

    {

        cmdArrived = 0;

        len = UartRead(buf, sizeof(buf)-2); //將接收到的命令讀取到緩衝(chong) 區中

        buf[len++] = '\r';   //在接收到的數據幀後添加換車換行符後發回

        buf[len++] = '\n';

        UartWrite(buf, len);

    }

}

 

void UartRxMonitor(unsigned char ms)  //串口接收監控函數

{

    static unsigned char cntbkp = 0;

&nbsnbsp;   static unsigned char idletmr = 0;

 

    if (cntRxd > 0)  //接收計數器大於(yu) 零時,監控總線空閑時間

    {

        if (cntbkp != cntRxd)  //接收計數器改變,即剛接收到數據時,清零空閑計時

        {

            cntbkp = cntRxd;

            idletmr = 0;

        }

        else

        {

            if (idletmr < 30)  //接收計數器未改變,即總線空閑時,累積空閑時間

            {

                idletmr += ms;

                if (idletmr >= 30)  //空閑時間超過30ms即認為(wei) 一幀命令接收完畢

                {

                    cmdArrived = 1; //設置命令到達標誌

                }

            }

        }

    }

    else

    {

        cntbkp = 0;

    }

}

void InterruptUART() interrupt 4  //UART中斷服務函數

{

     if (RI)  //接收到字節

    {

        RI = 0;   //手動清零接收中斷標誌位

        if (cntRxd < sizeof(bufRxd)) //接收緩衝(chong) 區尚未用完時,

        {

            bufRxd[cntRxd++] = SBUF; //保存接收字節,並遞增計數器

        }

     }

     if (TI)  //字節發送完畢

    {

         TI = 0;   //手動清零發送中斷標誌位

        flagOnceTxd = 1;  //設置單次發送完成標誌

     }

}

/***********************main.c文件程序源代碼*************************/

#include <reg52.h>

 

unsigned char T0RH = 0;  //T0重載值的高字節

unsigned char T0RL = 0;  //T0重載值的低字節

 

void ConfigTimer0(unsigned int ms);

extern void ConfigUART(unsigned int baud);

extern void UartRxMonitor(unsigned char ms);

extern void UartDriver();

 

void main ()

{

    EA = 1;           //開總中斷

    ConfigTimer0(1);  //配置T0定時1ms

    ConfigUART(9600); //配置波特率為(wei) 9600

    

    while(1)

    {

        UartDriver();

    }

}

 

void ConfigTimer0(unsigned int ms)  //T0配置函數

{

    unsigned long tmp;

    

    tmp = 11059200 / 12;      //定時器計數頻率

    tmp = (tmp * ms) / 1000;  //計算所需的計數值

    tmp = 65536 - tmp;        //計算定時器重載值

    tmp = tmp + 34;           //修正中斷響應延時造成的誤差

    

    T0RH = (unsigned char)(tmp >> 8);  //定時器重載值拆分為(wei) 高低字節

    T0RL = (unsigned char)tmp;

    TMOD &= 0xF0;   //清零T0的控製位

    TMOD |= 0x01;   //配置T0為(wei) 模式1

    TH0 = T0RH;     //加載T0重載值

    TL0 = T0RL;

    ET0 = 1;        //使能T0中斷

    TR0 = 1;        //啟動T0

}

void InterruptTimer0() interrupt 1  //T0中斷服務函數

{

    TH0 = T0RH;  //定時器重新加載重載值

    TL0 = T0RL;

    UartRxMonitor(1);  //串口接收監控

}

   現在看這種串口程序,是不是感覺很簡單了呢?串口通信程序我們(men) 反反複複的使用,加上隨著我們(men) 學習(xi) 的模塊越來越多,實踐的越來越多,原先感覺很複雜的東(dong) 西,現在就會(hui) 感到簡單了。我們(men) 的下載程序模塊用的是COM4,而USB轉485虛擬的是COM5,通信的時候我們(men) 用的是COM5口,如圖3所示。

RS485串行通信

圖3 RS485串行通信

  2、Modbus通信協議介紹

   我們(men) 前邊學習(xi) UART、I2C、SPI這些通信協議,都是最底層的協議,是“位”級別的協議。而我們(men) 在學習(xi) 13章實用串口通信程序的時候,我們(men) 通過串口發給單片機三條指令,讓單片機做了三件不同的事情,分別是"buzz on"、"buzz off"、和"showstr"。隨著我們(men) 係統複雜性的增加,我們(men) 希望可以實現更多的指令。而指令越來越多,帶來的後果就是非常雜亂(luan) 無章,尤其是這個(ge) 人喜歡寫(xie) 成"buzz on"、"buzz off",而另外一個(ge) 人喜歡寫(xie) 成"on buzz"、"off buzz"。導致不同開發人員寫(xie) 出來的代碼指令不兼容,不同廠家的產(chan) 品不能掛到一條總線上通信。

  隨著這種矛盾的日益嚴(yan) 重,就會(hui) 有聰明人提出更合理的解決(jue) 方案,提出一些標準來,今後我們(men) 的編程必須按照這個(ge) 標準來,這種標準也是一種通信協議,但是和UART、I2C、SPI通信協議不同的是,這種通信協議是字節級別的,叫做應用層通信協議。在1979年由Modicon(現為(wei) 施耐德電氣公司的一個(ge) 品牌)提出了全球第一個(ge) 真正用於(yu) 工業(ye) 現場總線的協議,就是Modbus協議。

  2.1 Modbus協議特點

  Modbus協議是應用於(yu) 電子控製器上的一種通用語言。通過此協議,控製器相互之間、控製器經由網絡(例如以太網)和其他設備之間可以通信,已經成為(wei) 一種工業(ye) 標準。有了它,不同廠商生產(chan) 的控製設備可以連成工業(ye) 網絡,進行集中監控。這種協議定義(yi) 了一種控製器能夠認識使用的數據結構,而不管它們(men) 是經過何種網絡進行通信的。它描述了控製器請求訪問其他設備的過程,如何回應來自其他設備的請求,以及怎樣偵(zhen) 測錯誤記錄,它製定了通信數據的格局和內(nei) 容的公共格式。

  在進行多機通信的時候,Modbus協議規定每個(ge) 控製器必須要知道他們(men) 的設備地址,識別按照地址發送過來的數據,決(jue) 定是否要產(chan) 生動作,產(chan) 生何種動作,如果要回應,控製器將生成的反饋信息用Modbus協議發出。

  Modbus協議允許在各種網絡體(ti) 係結構內(nei) 進行簡單通信,每種設備(plc、人機界麵、控製麵板、驅動程序、輸入輸出設備)都能使用Modbus協議來啟動遠程操作,一些網關(guan) 允許在幾種使用Modbus協議的總線或網絡之間的通信,如圖4所示。

圖18-4 Modbus網絡體(ti) 係結構實例

圖4 Modbus網絡體(ti) 係結構實例

  Modbus協議的整體(ti) 架構和格式比較複雜和龐大,在我們(men) 的課程裏,我們(men) 重點介紹數據幀結構和數據通信控製方式,作為(wei) 一個(ge) 入門級別的了解。如果大家要詳細了解,或者使用Modbus開發相關(guan) 設備,可以查閱相關(guan) 的國標文件再進行深入學習(xi) 。

  2.2 RTU協議幀數據

  Modbus有兩(liang) 種通信傳(chuan) 輸方式,一種是ASCII模式,一種是RTU模式。由於(yu) ASCII模式的數據字節是7bit數據位,51單片機無法實現,而且應用也相對較少,所以這裏我們(men) 隻用RTU模式。兩(liang) 種模式相似,會(hui) 用一種另外一種也就會(hui) 了。一條典型的RTU數據幀如圖5所示。

 RTU數據幀

圖5 RTU數據幀

  和我們(men) 實用串口通信程序類似,我們(men) 一次發送的數據幀必須是作為(wei) 一個(ge) 連續的數據流進行傳(chuan) 輸。我們(men) 在實用串口通信程序中采用的方法是定義(yi) 30ms,如果接收到的數據超過了30ms還沒有接收到下一個(ge) 字節,我們(men) 就認為(wei) 這次的數據結束。而Modbus的RTU模式規定不同數據幀之間的間隔是3.5個(ge) 字節通信時間以上。如果在一幀數據完成之前有超過3.5個(ge) 字節時間的停頓,接收設備將刷新當前的消息並假定下一個(ge) 字節是一個(ge) 新的數據幀的開始。(https://www.diangon.com/版權所有)同樣的,如果一個(ge) 新消息在小於(yu) 3.5個(ge) 字節時間內(nei) 接著前邊一個(ge) 數據開始的,接收的設備將會(hui) 認為(wei) 它是前一幀數據的延續。這將會(hui) 導致一個(ge) 錯誤,因此大家看RTU數據幀最後還有16bit的CRC校驗。

  起始位和結束符:圖18-5上代表的是一個(ge) 數據幀,前後都至少有3.5個(ge) 字節的時間間隔,起始位和結束符實際上沒有任何數據,T1-T2-T3-T4代表的是時間間隔3.5個(ge) 字節以上的時間,而真正有意義(yi) 的第一個(ge) 字節是設備地址。

  設備地址:很多同學不理解,在多機通信的時候,數據那麽(me) 多,我們(men) 依靠什麽(me) 判斷這個(ge) 數據幀是哪個(ge) 設備的呢?沒錯,就是依靠這個(ge) 設備地址字節。每個(ge) 設備都有一個(ge) 自己的地址,當設備接收到一幀數據後,程序首先對設備地址字節進行判斷比較,如果與(yu) 自己的地址不同,則對這幀數據直接不予理會(hui) ,如果如果與(yu) 自己的地址相同,就要對這幀數據進行解析,按照之後的功能碼執行相應的功能。如果地址是0x00,則認為(wei) 是一個(ge) 廣播命令,就是所有的從(cong) 機設備都要執行的指令。

  功能代碼:在第二個(ge) 字節功能代碼字節中,Modbus規定了部分功能代碼,此外也保留了一部分功能代碼作為(wei) 備用或者用戶自定義(yi) ,這些功能碼大家不需要去記憶,甚至都不用去看,直到你有用到的那天再過來查這個(ge) 表格即可,如表1所示。

  表1 Modbus功能碼

功能碼

名稱

作用

01

讀取線圈狀態

取得一組邏輯線圈的當前狀態(ON/OFF)

02

讀取輸入狀態

取得一組開關(guan) 輸入的當前狀態(ON/OFF)

03

讀取保持寄存器 

在一個(ge) 或多個(ge) 保持寄存器中取得當前的二進製值

04

讀取輸入寄存器

在一個(ge) 或多個(ge) 輸入寄存器中取得當前的二進製值

05

強置單線圈

強置一個(ge) 邏輯線圈的通斷狀態

06

預置單寄存器

把具體(ti) 二進值裝入一個(ge) 保持寄存器 

07

讀取異常狀態

取得8 個(ge) 內(nei) 部線圈的通斷狀態,這 8 個(ge) 線圈的地址由控製器決(jue) 定,用戶邏輯可以將這些線圈定義(yi) ,以說明從(cong) 機狀態,短報文適宜於(yu) 迅速讀取狀態 

08

回送診斷校驗

把診斷校驗報文送從(cong) 機,以對通信處理進行評鑒

09

編程(隻用於(yu) 484)

使主機模擬編程器作用,修改PC從(cong) 機邏輯

10

控詢(隻用於(yu) 484)

可使主機與(yu) 一台正在執行長程序任務從(cong) 機通信,探詢該從(cong) 機是否已完成其操作任務,僅(jin) 在含有功能碼 9 的報文發送後,本功能碼才發送 

11

讀取事件計數

可使主機發出單詢問,並隨即判定操作是否成功,尤其是該命令或其他應答產(chan) 生通信錯誤時 

12

讀取通信事件記錄

可是主機檢索每台從(cong) 機的ModBus事務處理通信事件記錄。如果某項事務處理完成,記錄會(hui) 給出有關(guan) 錯誤

13

編程(184/384 484 584 )

可使主機模擬編程器功能修改PC從(cong) 機邏輯 

14

探詢(184/384 484 584)

可使主機與(yu) 正在執行任務的從(cong) 機通信,定期控詢該從(cong) 機是否已完成其程序操作,僅(jin) 在含有功能13的報文發送後,本功能碼才得發送

15

強置多線圈

強置一串連續邏輯線圈的通斷

16

預置多寄存器

把具體(ti) 的二進製值裝入一串連續的保持寄存器

17

報告從(cong) 機標識

可使主機判斷編址從(cong) 機的類型及該從(cong) 機運行指示燈的狀態

18

884 和MICRO 84

可使主機模擬編程功能,修改PC狀態邏輯

19

重置通信鏈路

發生非可修改錯誤後,是從(cong) 機複位於(yu) 已知狀態,可重置順序字節 

20

讀取通用參數(584L)

顯示擴展存儲(chu) 器文件中的數據信息

    21

寫(xie) 入通用參數(584L)

把通用參數寫(xie) 入擴展存儲(chu) 文件,或修改

22~64

保留作擴展功能備用

 

65~72

保留以備用戶功能所用

留作用戶功能的擴展編碼 

73~119

非法功能

 

120~127

保留 

留作內(nei) 部作用

128~255

保留

用於(yu) 異常應答

  我們(men) 程序對功能碼的處理,就是程序來檢測這個(ge) 字節的數值,然後根據其數值來做相應的功能處理。

  數據:跟在功能代碼後邊的是n個(ge) 8bit的數據。這個(ge) n值的到底是多少,是功能代碼來確定的,不同的功能代碼後邊跟的數據數量不同。舉(ju) 個(ge) 例子,如果功能碼是0x03,也就是讀保持寄存器,那麽(me) 主機發送數據n的組成部分就是:2個(ge) 字節的寄存器起始地址,加2個(ge) 字節的寄存器數量N*。從(cong) 機數據n的組成部分是:1個(ge) 字節的字節數,因為(wei) 我們(men) 回複的寄存器的值是2個(ge) 字節,所以這個(ge) 字節數也就是2N*個(ge) ,再加上2N*個(ge) 寄存器的值,如圖6所示。

讀保持寄存器數據結構

圖6 讀保持寄存器數據結構

  CRC校驗:CRC校驗是一種數據算法,是用來校驗數據對錯的。CRC校驗函數把一幀數據除最後兩(liang) 個(ge) 字節外,前邊所有的字節進行特定的算法計算,計算完後生成了一個(ge) 16bit的數據,作為(wei) CRC校驗碼,添加在一幀數據的最後。接收方接收到數據後,同樣會(hui) 把前邊的字節進行CRC計算,計算完了再和發過來的CRC的16bit的數據進行比較,如果相同則認為(wei) 數據正常,沒有出錯,如果比較不相同,則說明數據在傳(chuan) 輸中發生了錯誤,這幀數據將被丟(diu) 棄,就像沒收到一樣,而發送方會(hui) 在得不到回應後做相應的處理錯誤處理。

  RTU模式的每個(ge) 字節的位是這樣分布的:1個(ge) 起始位、8個(ge) 數據位,最小有效位先發送、1個(ge) 奇偶校驗位(如果無校驗則沒有這一位)、1位停止位(有校驗位時)或者2個(ge) 停止位(無校驗位時)。

Tags:RS485通信和Modbus協議,RS485通信,Modbus協議  
責任編輯:admin
相關文章列表
沒有相關文章
請文明參與討論,禁止漫罵攻擊,不要惡意評論、違禁詞語。 昵稱:
1分 2分 3分 4分 5分

還可以輸入 200 個字
[ 查看全部 ] 網友評論
關於我們 - 聯係我們 - 廣告服務 - 友情鏈接 - 網站地圖 - 版權聲明 - 在線幫助 - 文章列表
返回頂部
刷新頁麵
下到頁底
晶體管查詢