女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Modbus RTU的設(shè)計(jì)與實(shí)現(xiàn)

CHANBAEK ? 來源:木南創(chuàng)智 ? 作者:尹家軍 ? 2022-12-13 15:27 ? 次閱讀

前面我們已經(jīng)詳細(xì)講解過Modbus協(xié)議棧的開發(fā)過程,并且利用協(xié)議棧封裝了Modbus RTU主站和從站,Modbus TCP服務(wù)器與客戶端,Modbus ASCII主站與從站應(yīng)用。但在使用過程中,我們發(fā)現(xiàn)一些使用不便和受限的地方,所以我們就想要更新一下協(xié)議棧,主要是應(yīng)用站的封裝。

1 、存在的局限性

在原有的協(xié)議棧中,我們所封裝的Modbus RTU主站是一個(gè)特定的主站,即它只是一個(gè)主站。在通常的應(yīng)用中不會(huì)有什么問題,但在有些應(yīng)用場(chǎng)合就會(huì)顯現(xiàn)出它的局限性。

首先,作為一個(gè)特定的主站,帶多個(gè)從站時(shí),寫從站的處理變的非常復(fù)雜,需要分辨不同的從站,不同的變量。當(dāng)有多個(gè)端口時(shí),還需要分辨不同的端口。

其次,作為一個(gè)特定的主站,帶多個(gè)從站時(shí),讀從站的處理,即使是不同的端口也不能分辨相同站地址的從站。因?yàn)橥恢髡镜慕馕龊瘮?shù)是同一個(gè),所以即使在不同端口也很難分辨,除非在解析前傳遞端口信息,這其實(shí)是將多余的信息傳遞到協(xié)議棧。這樣做不但程序不夠明晰也缺乏一般性。

最后,將所有的Modbus從站通訊都作為唯一的一個(gè)特定從站來處理,使得各部分混雜在一起,程序結(jié)構(gòu)很不清晰,對(duì)象也不明確。

2 、更新設(shè)計(jì)

考慮到前述的局限性,我們將主站及其帶訪問的從站定義為通用的對(duì)象,而當(dāng)我們?cè)诰唧w應(yīng)用中使用時(shí),再將其特例化為特定的主站和從站對(duì)象。

首先我們來考慮主站,原則上我們規(guī)劃的每一個(gè)主站對(duì)象對(duì)應(yīng)我們?cè)O(shè)備上的一個(gè)端口,那么在同一端口下,也就是在一個(gè)特定主站下,我們可以定義多個(gè)地址不同的從站,但不同端口下不受影響。如下圖所示:

從上圖中我們可以發(fā)現(xiàn),我們的目的就是讓協(xié)議棧支持,多主站和多從站,并且在不同主站下,從站的地址重復(fù)不受影響。接下來我們還需要考慮從站對(duì)象。主站對(duì)從站的操作無非兩類:讀從站信息和寫從站信息。

對(duì)于讀從站信息來說,主站需要發(fā)送請(qǐng)求命令,等待從站返回響應(yīng)信息,然后主站解析收到的信息并更新對(duì)應(yīng)的參數(shù)值。有兩點(diǎn)需要我們考慮,第一返回的響應(yīng)消息是沒有對(duì)應(yīng)的寄存器地址的,所以要想在解析的時(shí)候定位寄存器就必須知道發(fā)送的命令,為了便于分辨我們將命令存放在從站對(duì)象中。第二在解析響應(yīng)時(shí),如果兩條命令的響應(yīng)類似是沒法分辨的,所以我們還需要記住上一條命令是什么。也存儲(chǔ)于從站對(duì)象中。

而對(duì)于寫從站操作,無論寫的要求來自于哪里,對(duì)于協(xié)議棧來說肯定是其它的數(shù)據(jù)處理進(jìn)程發(fā)過來的,所接到要求后我們需要記錄是哪一個(gè)主站管理的哪一個(gè)從站的哪些參數(shù)。對(duì)于主站我們不需要分辨,因?yàn)槊總€(gè)主站都是獨(dú)立的處理進(jìn)程,但是對(duì)于從站和參數(shù)我們就需要分辨。每一個(gè)主站可以帶的站地址為0到255,但0和255已有定義,所以實(shí)際是1到254個(gè)。所以我們使用一個(gè)256位的變量,每位對(duì)應(yīng)站號(hào)來標(biāo)志其是否有需要寫的請(qǐng)求。記錄于主站,具體如下:

而每個(gè)從站的寫參數(shù)請(qǐng)求標(biāo)志則存儲(chǔ)于各個(gè)從站對(duì)象,因?yàn)椴煌膹恼究赡苡泻艽髤^(qū)別,存儲(chǔ)于各個(gè)從站更加靈活。

3 、如何實(shí)現(xiàn)

我們已經(jīng)設(shè)計(jì)了我們的更新,但具體如何實(shí)現(xiàn)它呢?我們主要從以下幾個(gè)方面來實(shí)現(xiàn)它。第一,實(shí)現(xiàn)主站對(duì)象類型和從站對(duì)象類型。第二,主站對(duì)象的實(shí)例化及從站對(duì)象的實(shí)例化。第三,讀從站的主站操作過程。第四,寫從站的主站操作過程。接下來我們將一一描述之。

3.1 、定義對(duì)象類型

在Modbus RTU協(xié)議棧的封裝中,我們需要定義主站對(duì)象和從站對(duì)象,自然也需要定義這兩種類型。至于其功能前述已經(jīng)描述過。

首先我們來定義本地主站的類型,其成員包括:一個(gè)uint32_t的寫從站標(biāo)志數(shù)組;從站數(shù)量字段;從站順序字段;本主站所管理的從站列表;4個(gè)數(shù)據(jù)更新函數(shù)指針。具體定義如下:

1 /* 定義本地RTU主站對(duì)象類型 */
 2 typedef struct LocalRTUMasterType{
 3   uint32_t flagWriteSlave[8];   //寫一個(gè)站控制標(biāo)志位,最多256個(gè)站,與站地址對(duì)應(yīng)。
 4   uint16_t slaveNumber;         //從站列表中從站的數(shù)量
 5   uint16_t readOrder;           //當(dāng)前從站在從站列表中的位置
 6   RTUAccessedSlaveType *pSlave;         //從站列表
 7   UpdateCoilStatusType pUpdateCoilStatus;       //更新線圈量函數(shù)
 8   UpdateInputStatusType pUpdateInputStatus;     //更新輸入狀態(tài)量函數(shù)
 9   UpdateHoldingRegisterType pUpdateHoldingRegister;     //更新保持寄存器量函數(shù)
10   UpdateInputResgisterType pUpdateInputResgister;       //更新輸入寄存器量函數(shù)
11 }RTULocalMasterType;

關(guān)于主站對(duì)象類型,在前面的更新設(shè)計(jì)中已經(jīng)講的很清楚了,只有兩個(gè)需要說明一下。第一,從站列表是用來記錄本主站所管理的從站對(duì)象。第二,readOrder字段表示為當(dāng)前訪問從站在列表中的位置,而slaveNumber是從站對(duì)象的數(shù)量,即列表的長(zhǎng)度。具體如下圖所示:

還需要定義從站對(duì)象,此從站對(duì)象只是便于主站而用于表示真實(shí)的從站。主站的從站列表中就是此對(duì)象。具體結(jié)構(gòu)如下:

1 /* 定義被訪問RTU從站對(duì)象類型 */
 2 typedef struct AccessedRTUSlaveType{
 3   uint8_t stationAddress;       //站地址
 4   uint8_t cmdOrder;             //當(dāng)前命令在命令列表中的位置
 5   uint16_t commandNumber;       //命令列表中命令的總數(shù)
 6   uint8_t (*pReadCommand)[8];   //讀命令列表
 7   uint8_t *pLastCommand;        //上一次發(fā)送的命令
 8   uint32_t flagPresetCoil;      //預(yù)置線圈控制標(biāo)志位
 9   uint32_t flagPresetReg;       //預(yù)置寄存器控制標(biāo)志位
10 }RTUAccessedSlaveType;

關(guān)于從站對(duì)象有兩個(gè)字段需要說一下,就是flagPresetCoil和flagPresetReg字段。這兩個(gè)字段用來表示對(duì)線圈和保持寄存器的寫請(qǐng)求。

3.2 、實(shí)例化對(duì)象

我們定義了主站即從站對(duì)象類型,我們?cè)谑褂脮r(shí)就需要實(shí)例化這些對(duì)象。一般來說一個(gè)硬件端口我們將其實(shí)例化為一個(gè)主站對(duì)象。

RTULocalMasterType hgraMaster;

/ 初始化RTU主站對(duì)象 /

InitializeRTUMasterObject(&hgraMaster,2,hgraSlave,NULL,NULL,NULL,NULL);

而一個(gè)主站對(duì)象會(huì)管理1到254個(gè)從站對(duì)象,所以我們可以將多個(gè)從站對(duì)象實(shí)例組成數(shù)組,并將其賦予主站管理。

RTUAccessedSlaveType hgraSlave[]={{1,0,2,slave1ReadCommand,NULL,0x00,0x00},{2,0,2,slave2ReadCommand,NULL,0x00,0x00}};

所以,根據(jù)主站和從站實(shí)例化的條件,我們需要先實(shí)例化從站對(duì)象才能完整實(shí)例化主站對(duì)象。在主站的初始化中,我們這里將4的數(shù)據(jù)處理函數(shù)指針初始化為NULL,有一個(gè)默認(rèn)的處理函數(shù)會(huì)復(fù)制給它,該函數(shù)是上一版本的延續(xù),在簡(jiǎn)單應(yīng)用時(shí)簡(jiǎn)化操作。從站的上一個(gè)發(fā)送的命令指針也被賦值為NULL,因?yàn)槌跏紩r(shí)還沒有命令發(fā)送。

3.3 、讀從站操作

讀從站操作原理上與以前的版本是一樣的。按照一定的順序給從站發(fā)送命令再對(duì)收到的消息進(jìn)行解析。我們對(duì)主站及其所管理的從站進(jìn)行了定義,將發(fā)送命令保存于從站對(duì)象,將從站列表保存于主站對(duì)象,所以我們需要對(duì)解析函數(shù)進(jìn)行修改。

1 /*解析收到的服務(wù)器相應(yīng)信息*/
 2 /*uint8_t *recievedMessage,接收到的消息列表*/
 3 /*uint8_t *command,發(fā)送的讀操作命令,若為NULL則在命令列表中查找*/
 4 void ParsingSlaveRespondMessage(RTULocalMasterType *master,uint8_t *recievedMessage,uint8_t *command)
 5 {
 6   int i=0;
 7   int j=0;
 8   uint16_t startAddress;
 9   uint16_t quantity;
10   uint8_t *cmd=NULL;
11  
12   /*如果不是讀操作的反回信息不需要處理*/
13   if(recievedMessage[1]>0x04)
14   {
15     return;
16   }
17  
18   /*判斷功能碼是否有誤*/
19   FunctionCode fuctionCode=(FunctionCode)recievedMessage[1];
20   if (CheckFunctionCode(fuctionCode) != MB_OK)
21   {
22     return;
23   }
24  
25   /*校驗(yàn)接收到的信息是否有錯(cuò)*/
26   uint16_t byteCount=recievedMessage[2];
27   bool chechMessageNoError=CheckRTUMessageIntegrity(recievedMessage,byteCount+5);
28   if(!chechMessageNoError)
29   {
30     return;
31   }
32  
33   if((command==NULL)||(!CheckMessageAgreeWithCommand(recievedMessage,command)))
34   {
35     while(islaveNumber)
36     {
37       if(master->pSlave[i].stationAddress==recievedMessage[0])
38       {
39         break;
40       }
41       i++;
42     }
43    
44     if(i>=master->slaveNumber)
45     {
46       return;
47     }
48    
49     if((master->pSlave[i].pLastCommand==NULL)||(!CheckMessageAgreeWithCommand(recievedMessage,master->pSlave[i].pLastCommand)))
50     {
51       j=FindCommandForRecievedMessage(recievedMessage,master->pSlave[i].pReadCommand,master->pSlave[i].commandNumber);
52      
53       if(j<0)
54       {
55         return;
56       }
57      
58       cmd=master->pSlave[i].pReadCommand[j];
59     }
60     else
61     {
62       cmd=master->pSlave[i].pLastCommand;
63     }
64   }
65   else
66   {
67     cmd=command;
68   }
69  
70   startAddress=(uint16_t)cmd[2];
71   startAddress=(startAddress<<8)+(uint16_t)cmd[3];
72   quantity=(uint16_t)cmd[4];
73   quantity=(quantity<<8)+(uint16_t)cmd[5];
74  
75   if((fuctionCode>=ReadCoilStatus)&&(fuctionCode<=ReadInputRegister))
76   {
77     HandleSlaveRespond[fuctionCode-1](master,recievedMessage,startAddress,quantity);
78   }
79 }

解析函數(shù)的主要部分是在檢查接收到的消息是否是合法的Modbus RTU消息。檢查沒問題則調(diào)用協(xié)議站解析。而最后調(diào)用的數(shù)據(jù)處理函數(shù)則是我們需要在具體應(yīng)用中編寫。在前面主站初始化時(shí),回調(diào)函數(shù)我們初始化為NULL,實(shí)際在協(xié)議棧中有弱化的函數(shù)定義,需要針對(duì)具體的寄存器和變量地址實(shí)現(xiàn)操作。

3.4 、寫從站操作

寫從站操作則是在其它進(jìn)程請(qǐng)求后,我們標(biāo)識(shí)需要寫的對(duì)象再統(tǒng)一處理。對(duì)具體哪個(gè)從站的寫標(biāo)識(shí)存于主站實(shí)例。而該從站的哪些變量需要寫則記錄在從站實(shí)例中。

所以在進(jìn)程檢測(cè)到需要寫一個(gè)從站時(shí)則置位對(duì)應(yīng)的位,即改變flagWriteSlave中的對(duì)應(yīng)位。而需要寫該站的哪些變量則標(biāo)記flagPresetCoil和flagPresetReg的對(duì)應(yīng)位。修改這些標(biāo)識(shí)都在其它請(qǐng)求更改的進(jìn)程中實(shí)現(xiàn),而具體的寫操作則在本主站進(jìn)程中,檢測(cè)到標(biāo)志位的變化統(tǒng)一執(zhí)行。

這部分不修改協(xié)議棧的代碼,因?yàn)楦髡炯案髯兞慷贾劣诰唧w對(duì)象相關(guān)聯(lián),所以在具體的應(yīng)用中修改。

4 、回歸驗(yàn)證

為了驗(yàn)證我們前面的更新設(shè)計(jì)是符合要求的,我們?cè)O(shè)計(jì)一個(gè)難度較高的實(shí)驗(yàn)系統(tǒng)。這一實(shí)驗(yàn)系統(tǒng)包括Modbus網(wǎng)關(guān),上位Modbus主站以及下位的Modbus從站。我們所要實(shí)現(xiàn)的是Modbus網(wǎng)關(guān)部分,其具體結(jié)構(gòu)圖設(shè)計(jì)如下:

從上圖我們知道,該Modbus網(wǎng)關(guān)需要實(shí)現(xiàn)一個(gè)Modbus從站用于和上位的通訊;需要實(shí)現(xiàn)兩個(gè)Modbus主站用于和下位的通訊。

在這個(gè)實(shí)驗(yàn)中,讀操作沒有什么需要說的,只需要發(fā)送命令,解析返回消息即可。所以我們重點(diǎn)描述一下寫操作,為了方便操作,在需要寫的連續(xù)段,我們只要找到第一個(gè)請(qǐng)求寫的位置后,就將后續(xù)連續(xù)可寫數(shù)據(jù)一次性寫入。修改寫標(biāo)志位的代碼如下:

1 /* 寫從站寄存器控制 */
  2 static void WriteSlaveRegisterControll(uint16_t startAddress,uint16_t endAddress)
  3 {
  4   if((12<=startAddress)&&(startAddress<=71)&&(12<=endAddress)&&(endAddress<=71))
  5   {
  6     ModifyWriteRTUSlaveEnableFlag(&hgraMaster,hgraMaster.pSlave[0].stationAddress,true);
  7    
  8     if((startAddress<=12)&&(13<=endAddress))
  9     {
 10       hgraMaster.pSlave[0].flagPresetReg|=0x01;
 11     }
 12     if((startAddress<=14)&&(15<=endAddress))
 13     {
 14       hgraMaster.pSlave[0].flagPresetReg|=0x02;
 15     }
 16     if((startAddress<=16)&&(17<=endAddress))
 17     {
 18       hgraMaster.pSlave[0].flagPresetReg|=0x04;
 19     }
 20     if((startAddress<=18)&&(19<=endAddress))
 21     {
 22       hgraMaster.pSlave[0].flagPresetReg|=0x08;
 23     }
 24     if((startAddress<=20)&&(21<=endAddress))
 25     {
 26       hgraMaster.pSlave[0].flagPresetReg|=0x10;
 27     }
 28     if((startAddress<=22)&&(23<=endAddress))
 29     {
 30       hgraMaster.pSlave[0].flagPresetReg|=0x20;
 31     }
 32     if((startAddress<=24)&&(25<=endAddress))
 33     {
 34       hgraMaster.pSlave[0].flagPresetReg|=0x40;
 35     }
 36     if((startAddress<=26)&&(27<=endAddress))
 37     {
 38       hgraMaster.pSlave[0].flagPresetReg|=0x80;
 39     }
 40    
 41     if((startAddress<=32)&&(32<=endAddress))
 42     {
 43       hgraMaster.pSlave[0].flagPresetReg|=0x100;
 44     }
 45     if((startAddress<=33)&&(33<=endAddress))
 46     {
 47       hgraMaster.pSlave[0].flagPresetReg|=0x200;
 48     }
 49     if((startAddress<=34)&&(34<=endAddress))
 50     {
 51       hgraMaster.pSlave[0].flagPresetReg|=0x400;
 52     }
 53     if((startAddress<=35)&&(35<=endAddress))
 54     {
 55       hgraMaster.pSlave[0].flagPresetReg|=0x800;
 56     }
 57     if((startAddress<=36)&&(36<=endAddress))
 58     {
 59       hgraMaster.pSlave[0].flagPresetReg|=0x1000;
 60     }
 61     if((startAddress<=37)&&(37<=endAddress))
 62     {
 63       hgraMaster.pSlave[0].flagPresetReg|=0x2000;
 64     }
 65     if((startAddress<=38)&&(38<=endAddress))
 66     {
 67       hgraMaster.pSlave[0].flagPresetReg|=0x4000;
 68     }
 69     if((startAddress<=39)&&(39<=endAddress))
 70     {
 71       hgraMaster.pSlave[0].flagPresetReg|=0x8000;
 72     }
 73     if((startAddress<=40)&&(40<=endAddress))
 74     {
 75       hgraMaster.pSlave[0].flagPresetReg|=0x10000;
 76     }
 77     if((startAddress<=41)&&(41<=endAddress))
 78     {
 79       hgraMaster.pSlave[0].flagPresetReg|=0x20000;
 80     }
 81     if((startAddress<=42)&&(42<=endAddress))
 82     {
 83       hgraMaster.pSlave[0].flagPresetReg|=0x40000;
 84     }
 85     if((startAddress<=43)&&(43<=endAddress))
 86     {
 87       hgraMaster.pSlave[0].flagPresetReg|=0x80000;
 88     }
 89     if((startAddress<=44)&&(44<=endAddress))
 90     {
 91       hgraMaster.pSlave[0].flagPresetReg|=0x100000;
 92     }
 93     if((startAddress<=45)&&(45<=endAddress))
 94     {
 95       hgraMaster.pSlave[0].flagPresetReg|=0x200000;
 96     }
 97     if((startAddress<=46)&&(46<=endAddress))
 98     {
 99       hgraMaster.pSlave[0].flagPresetReg|=0x400000;
100     }
101     if((startAddress<=47)&&(47<=endAddress))
102     {
103       hgraMaster.pSlave[0].flagPresetReg|=0x800000;
104     }
105    
106     if((startAddress<=52)&&(55<=endAddress))
107     {
108       hgraMaster.pSlave[0].flagPresetReg|=0x1000000;
109     }
110     if((startAddress<=56)&&(59<=endAddress))
111     {
112       hgraMaster.pSlave[0].flagPresetReg|=0x2000000;
113     }
114     if((startAddress<=60)&&(63<=endAddress))
115     {
116       hgraMaster.pSlave[0].flagPresetReg|=0x4000000;
117     }
118     if((startAddress<=64)&&(67<=endAddress))
119     {
120       hgraMaster.pSlave[0].flagPresetReg|=0x8000000;
121     }
122   }
123  
124   if((72<=startAddress)&&(startAddress<=131)&&(72<=endAddress)&&(endAddress<=131))
125   {
126     ModifyWriteRTUSlaveEnableFlag(&hgraMaster,hgraMaster.pSlave[1].stationAddress,true);
127    
128     if((startAddress<=72)&&(73<=endAddress))
129     {
130       hgraMaster.pSlave[1].flagPresetReg|=0x01;
131     }
132     if((startAddress<=74)&&(75<=endAddress))
133     {
134       hgraMaster.pSlave[1].flagPresetReg|=0x02;
135     }
136     if((startAddress<=76)&&(77<=endAddress))
137     {
138       hgraMaster.pSlave[1].flagPresetReg|=0x04;
139     }
140     if((startAddress<=78)&&(79<=endAddress))
141     {
142       hgraMaster.pSlave[1].flagPresetReg|=0x08;
143     }
144     if((startAddress<=80)&&(81<=endAddress))
145     {
146       hgraMaster.pSlave[1].flagPresetReg|=0x10;
147     }
148     if((startAddress<=82)&&(83<=endAddress))
149     {
150       hgraMaster.pSlave[1].flagPresetReg|=0x20;
151     }
152     if((startAddress<=84)&&(85<=endAddress))
153     {
154       hgraMaster.pSlave[1].flagPresetReg|=0x40;
155     }
156     if((startAddress<=86)&&(87<=endAddress))
157     {
158       hgraMaster.pSlave[1].flagPresetReg|=0x80;
159     }
160    
161     if((startAddress<=92)&&(92<=endAddress))
162     {
163       hgraMaster.pSlave[1].flagPresetReg|=0x100;
164     }
165     if((startAddress<=93)&&(93<=endAddress))
166     {
167       hgraMaster.pSlave[1].flagPresetReg|=0x200;
168     }
169     if((startAddress<=94)&&(94<=endAddress))
170     {
171       hgraMaster.pSlave[1].flagPresetReg|=0x400;
172     }
173     if((startAddress<=95)&&(95<=endAddress))
174     {
175       hgraMaster.pSlave[1].flagPresetReg|=0x800;
176     }
177     if((startAddress<=96)&&(96<=endAddress))
178     {
179       hgraMaster.pSlave[1].flagPresetReg|=0x1000;
180     }
181     if((startAddress<=97)&&(97<=endAddress))
182     {
183       hgraMaster.pSlave[1].flagPresetReg|=0x2000;
184     }
185     if((startAddress<=98)&&(98<=endAddress))
186     {
187       hgraMaster.pSlave[1].flagPresetReg|=0x4000;
188     }
189     if((startAddress<=99)&&(99<=endAddress))
190     {
191       hgraMaster.pSlave[1].flagPresetReg|=0x8000;
192     }
193     if((startAddress<=100)&&(100<=endAddress))
194     {
195       hgraMaster.pSlave[1].flagPresetReg|=0x10000;
196     }
197     if((startAddress<=101)&&(101<=endAddress))
198     {
199       hgraMaster.pSlave[1].flagPresetReg|=0x20000;
200     }
201     if((startAddress<=102)&&(102<=endAddress))
202     {
203       hgraMaster.pSlave[1].flagPresetReg|=0x40000;
204     }
205     if((startAddress<=103)&&(103<=endAddress))
206     {
207       hgraMaster.pSlave[1].flagPresetReg|=0x80000;
208     }
209     if((startAddress<=104)&&(104<=endAddress))
210     {
211       hgraMaster.pSlave[1].flagPresetReg|=0x100000;
212     }
213     if((startAddress<=105)&&(105<=endAddress))
214     {
215       hgraMaster.pSlave[1].flagPresetReg|=0x200000;
216     }
217     if((startAddress<=106)&&(106<=endAddress))
218     {
219       hgraMaster.pSlave[1].flagPresetReg|=0x400000;
220     }
221     if((startAddress<=107)&&(107<=endAddress))
222     {
223       hgraMaster.pSlave[1].flagPresetReg|=0x800000;
224     }
225    
226     if((startAddress<=112)&&(115<=endAddress))
227     {
228       hgraMaster.pSlave[1].flagPresetReg|=0x1000000;
229     }
230     if((startAddress<=116)&&(119<=endAddress))
231     {
232       hgraMaster.pSlave[1].flagPresetReg|=0x2000000;
233     }
234     if((startAddress<=120)&&(123<=endAddress))
235     {
236       hgraMaster.pSlave[1].flagPresetReg|=0x4000000;
237     }
238     if((startAddress<=124)&&(127<=endAddress))
239     {
240       hgraMaster.pSlave[1].flagPresetReg|=0x8000000;
241     }
242   }
243  
244   if((132<=startAddress)&&(startAddress<=191)&&(131<=endAddress)&&(endAddress<=191))
245   {
246     ModifyWriteRTUSlaveEnableFlag(&hgpjMaster,hgpjMaster.pSlave[0].stationAddress,true);
247   }
248  
249   if((192<=startAddress)&&(startAddress<=251)&&(192<=endAddress)&&(endAddress<=251))
250   {
251     ModifyWriteRTUSlaveEnableFlag(&hgpjMaster,hgpjMaster.pSlave[1].stationAddress,true);
252   }
253 }

然后在主站對(duì)象的進(jìn)程中檢測(cè)標(biāo)志位,根據(jù)標(biāo)志位的狀態(tài)來實(shí)現(xiàn)操作,具體的操作代碼很簡(jiǎn)單,且不具普遍性,在此不貼出。

5 、幾點(diǎn)注意

雖然我們對(duì)主站對(duì)象和從站對(duì)象進(jìn)行了封裝,但我們?cè)谑褂脮r(shí)人需要注意一些問題。

(1)、4個(gè)回調(diào)函數(shù)的定義,這4個(gè)回調(diào)函數(shù)用于處理從粘返回的信息,對(duì)應(yīng)Modbus定義的四種數(shù)據(jù),需要根據(jù)主站對(duì)象管理的從站情況來實(shí)現(xiàn)。

(2)、對(duì)于寫操作標(biāo)識(shí)符,一般都是在請(qǐng)求進(jìn)程置位,在主站對(duì)象所在的進(jìn)程檢測(cè)并操作,然后復(fù)位。

告之: 源代碼可上Github下載:https://github.com/foxclever/Modbus

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • MODBUS
    +關(guān)注

    關(guān)注

    28

    文章

    2008

    瀏覽量

    78968
  • ASCII
    +關(guān)注

    關(guān)注

    5

    文章

    172

    瀏覽量

    35673
  • RTU
    RTU
    +關(guān)注

    關(guān)注

    0

    文章

    432

    瀏覽量

    29270
  • 協(xié)議棧
    +關(guān)注

    關(guān)注

    2

    文章

    145

    瀏覽量

    34013
收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    開關(guān)量轉(zhuǎn)485、485轉(zhuǎn)開關(guān)量

    采用Modbus RTU,實(shí)現(xiàn)最快捷工業(yè)傳輸. RS485接口端有效實(shí)現(xiàn)光電隔離和電源隔離技術(shù),的效抑制閃電,雷擊,ESD和共地干擾.提供五年質(zhì)保服務(wù)。特點(diǎn):→8路數(shù)字量輸入→8路數(shù)字
    發(fā)表于 06-13 16:17

    Modbus TCP轉(zhuǎn)Modbus RTU實(shí)現(xiàn)

    使用ZLSN2040、NETCOM2040實(shí)現(xiàn)Modbus TCP到Modbus RTU的轉(zhuǎn)化。1.Modbus TCP與
    發(fā)表于 08-10 10:04

    中斷不能調(diào)printf的原因

    [導(dǎo)讀] 大家好,我是逸珺。前面說會(huì)寫一下Modbus-RTU實(shí)現(xiàn),寫了1000多字了,有興趣的稍等一下哈。前面在一個(gè)群里看到一個(gè)朋友在一個(gè)串口接收中斷里打印遇到了問題,今天聊下這個(gè)話題...
    發(fā)表于 01-27 08:10

    中斷不能調(diào)printf的原因

    關(guān)注、星標(biāo)嵌入式客棧,精彩及時(shí)送達(dá)[導(dǎo)讀] 大家好,我是逸珺。前面說會(huì)寫一下Modbus-RTU實(shí)現(xiàn),寫了1000多字了,有興趣的稍等一下哈。前面在一個(gè)群里看到一個(gè)朋友問在一個(gè)串口接收中...
    發(fā)表于 02-07 06:53

    Modbus RTU實(shí)現(xiàn)工控機(jī)與智能儀表通信

    能力等特點(diǎn),非常適合組成工業(yè)級(jí)的多機(jī)通信系統(tǒng)。Modbus RIU通信協(xié)議是目前國(guó)際智能化儀表普遍采用的主流通信協(xié)議之一。在各種工業(yè)儀器儀表大量使用的今天,Modbus RIU通信協(xié)議和RS - 485總線得到了廣泛的應(yīng)用。本文主要從應(yīng)用角度介紹在工業(yè)
    發(fā)表于 01-15 11:24 ?2次下載

    扒一扒中斷為什么不能調(diào)printf

    [導(dǎo)讀] 大家好,我是逸珺。前面說會(huì)寫一下Modbus-RTU實(shí)現(xiàn),寫了1000多字了,有興趣的稍等一下哈。前面在一個(gè)群里看到一個(gè)朋友在一個(gè)串口接收中斷里打印遇到了問題,今天聊下這個(gè)話題...
    發(fā)表于 12-03 14:51 ?0次下載
    扒一扒中斷為什么不能調(diào)printf

    扒一扒中斷為什么不能調(diào)printf

    [導(dǎo)讀] 大家好,我是逸珺。前面說會(huì)寫一下Modbus-RTU實(shí)現(xiàn),寫了1000多字了,有興趣的稍等一下哈。前面在一個(gè)群里看到一個(gè)朋友在一個(gè)串口接收中斷里打印遇到了問題,今天聊下這個(gè)話題...
    發(fā)表于 12-04 11:36 ?8次下載
    扒一扒中斷為什么不能調(diào)printf

    扒一扒中斷為什么不能調(diào)printf

    [導(dǎo)讀] 大家好,我是逸珺。前面說會(huì)寫一下Modbus-RTU實(shí)現(xiàn),寫了1000多字了,有興趣的稍等一下哈。前面在一個(gè)群里看到一個(gè)朋友在一個(gè)串口接收中斷里打印遇到了問題,今天聊下這個(gè)話題...
    發(fā)表于 12-04 12:21 ?6次下載
    扒一扒中斷為什么不能調(diào)printf

    扒一扒中斷為什么不能調(diào)printf?

    前面說會(huì)寫一下Modbus-RTU實(shí)現(xiàn),寫了1000多字了,有興趣的稍等一下哈。前面在一個(gè)群里看到一個(gè)朋友在一個(gè)串口接收中斷里打印遇到了問題,今天聊下這個(gè)話題。扒一扒printf對(duì)于單片...
    發(fā)表于 12-04 12:21 ?0次下載
    扒一扒中斷為什么不能調(diào)printf?

    扒一扒中斷為什么不能調(diào)printf

    [導(dǎo)讀] 大家好,我是逸珺。前面說會(huì)寫一下Modbus-RTU實(shí)現(xiàn),寫了1000多字了,有興趣的稍等一下哈。前面在一個(gè)群里看到一個(gè)朋友在一個(gè)串...
    發(fā)表于 01-25 17:52 ?0次下載
    扒一扒中斷為什么不能調(diào)printf

    西門子SMARTP通過MODBUS RTU實(shí)現(xiàn)一主多從的步驟

    通過SMART PLC進(jìn)行編程過程中,通常會(huì)遇到需要將多個(gè)RTU從站進(jìn)行傳輸,而作為SMARTPLC的主站接收多個(gè)從站傳輸過來的數(shù)據(jù),并同步顯示。
    的頭像 發(fā)表于 07-08 14:18 ?2336次閱讀
    西門子SMARTP通過<b class='flag-5'>MODBUS</b> <b class='flag-5'>RTU</b><b class='flag-5'>實(shí)現(xiàn)</b>一主多從的步驟

    Profibus DP主站轉(zhuǎn)Modbus RTU協(xié)議網(wǎng)關(guān)(Modbus RTU轉(zhuǎn)Profibus DP)

    Profibus DP主站轉(zhuǎn)Modbus RTU如何實(shí)現(xiàn)有效連接與通信,這一問題常常讓許多人感到困惑不已。現(xiàn)在,就來為大家專門解答這個(gè)疑問。遠(yuǎn)創(chuàng)智控YC-DPM-RTU設(shè)備有著極為出色
    的頭像 發(fā)表于 08-25 14:43 ?494次閱讀
    Profibus DP主站轉(zhuǎn)<b class='flag-5'>Modbus</b> <b class='flag-5'>RTU</b>協(xié)議網(wǎng)關(guān)(<b class='flag-5'>Modbus</b> <b class='flag-5'>RTU</b>轉(zhuǎn)Profibus DP)

    EtherCAT從站轉(zhuǎn)Modbus RTU總線協(xié)議轉(zhuǎn)換網(wǎng)關(guān)配置詳情

    ? EtherCAT轉(zhuǎn)Modbus RTU如何實(shí)現(xiàn)有效連接與通信,這一問題常常讓許多人感到困惑不已。現(xiàn)在,就來為大家專門解答這個(gè)疑問。遠(yuǎn)創(chuàng)智控YC-ECT-RTU型設(shè)備有著極為出色的表
    的頭像 發(fā)表于 08-27 16:02 ?529次閱讀
    EtherCAT從站轉(zhuǎn)<b class='flag-5'>Modbus</b> <b class='flag-5'>RTU</b>總線協(xié)議轉(zhuǎn)換網(wǎng)關(guān)配置詳情

    Profibus DP從站轉(zhuǎn)Modbus RTU主站總線協(xié)議轉(zhuǎn)換網(wǎng)關(guān)配置詳情

    Profibus DP轉(zhuǎn)Modbus RTU如何實(shí)現(xiàn)有效連接與通信,這一問題常常讓許多人感到困惑不已。現(xiàn)在,就來為大家專門解答這個(gè)疑問。遠(yuǎn)創(chuàng)智控YC-DPM-TCP型設(shè)備有著極為出色的表現(xiàn),能夠
    的頭像 發(fā)表于 08-27 16:20 ?559次閱讀
    Profibus DP從站轉(zhuǎn)<b class='flag-5'>Modbus</b> <b class='flag-5'>RTU</b>主站總線協(xié)議轉(zhuǎn)換網(wǎng)關(guān)配置詳情

    EtherCAT轉(zhuǎn)Modbus-RTU協(xié)議網(wǎng)關(guān)(Modbus-RTU轉(zhuǎn)EtherCAT)

    EtherCAT轉(zhuǎn)Modbus-RTU實(shí)現(xiàn)網(wǎng)絡(luò)協(xié)議互通是眾人關(guān)注焦點(diǎn),遠(yuǎn)創(chuàng)智控YC-ECT-RTU能夠很輕松解決這個(gè)問題。在這里作者將從該設(shè)備的主要功能、技術(shù)參數(shù)、性能優(yōu)勢(shì)、配置方法等幾個(gè)方面詳細(xì)
    的頭像 發(fā)表于 09-04 09:56 ?475次閱讀
    EtherCAT轉(zhuǎn)<b class='flag-5'>Modbus-RTU</b>協(xié)議網(wǎng)關(guān)(<b class='flag-5'>Modbus-RTU</b>轉(zhuǎn)EtherCAT)