組態(tài)王及modbus通信課程設計_第1頁
已閱讀1頁,還剩23頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、<p><b>  測控網(wǎng)絡課程設計</b></p><p><b>  一、實踐要求</b></p><p>  本次實踐以開發(fā)DCS測控系統(tǒng)為最終目的,要求掌握DCS測控系統(tǒng)的工作原理,學習組態(tài)王工控組態(tài)軟件的使用方法,根據(jù)要求完成工程組態(tài);掌握MODBUS通信協(xié)議的原理,開發(fā)具有MODBUS通訊功能的智能儀表,最終完成和組態(tài)工程之

2、間的通訊。</p><p><b>  二、實踐內容</b></p><p>  分為兩大部分:1、組態(tài)王基本操作 2、 MODBUS通訊</p><p><b>  具體內容:</b></p><p>  熟悉組態(tài)王軟件安裝,基本開發(fā)環(huán)境,采用構建簡單的工程(采用仿真數(shù)據(jù)和設備,工程應包含PID功

3、能),計劃時間1天;</p><p>  根據(jù)罐區(qū)工藝的要求,完成相應的組態(tài)工程,實現(xiàn)對原油儲罐的監(jiān)控,計劃時間2天;</p><p>  掌握MODBUS通訊協(xié)議的工作原理,在MSP430F5438單片機上編程實現(xiàn)MODBUS客戶端服務程序,要求通過串行口將現(xiàn)場的溫度、泵狀態(tài)、流量等參數(shù)上傳到上位機上,計劃時間3天。</p><p>  在單片機上編程實現(xiàn)流量、溫

4、度上下限及儀表地址和波特率等參數(shù)設置功能,同時能從上位機對儀表參數(shù)進行設置,計劃時間2天。</p><p>  優(yōu)化設計,要求當出現(xiàn)通訊錯誤時在上位機和單片機上都要做出相應的反應,計劃時間0.5天。</p><p> ?、?上位機采用高級語言編程,實現(xiàn)對現(xiàn)場智能儀表的控制。</p><p>  ② 熟悉現(xiàn)場總線測控網(wǎng)絡系統(tǒng),搭建PROFIBUS網(wǎng)絡,實現(xiàn)對ET200

5、S和S7-200的控制。</p><p><b>  組態(tài)王部分</b></p><p><b>  一、設計要求</b></p><p>  根據(jù)罐區(qū)工藝的要求,完成相應的組態(tài)工程,實現(xiàn)對原油儲罐的監(jiān)控。</p><p><b>  1、罐區(qū)工藝流程圖</b></p&g

6、t;<p>  2- 儲油罐進口電動閥;3- 儲油罐排污電動閥;4- 儲油罐出口電動閥;5- 泵</p><p>  圖1:罐區(qū)工藝流程圖</p><p><b>  2、具體要求</b></p><p> ?。?)監(jiān)測各罐的液位(0-20m)/ (0-1m)/溫度(0-100度)(現(xiàn)場儀表4-20mA輸出)。</p>

7、<p> ?。?)根據(jù)各罐液位控制各罐出口電動閥(H>16m, 關進口閥,選擇最低液位的罐進油;H<2m,關出口閥,選擇最高液位的罐出油),手動遙控排污閥。</p><p>  液位H>15.5m高報警, H>17m高高報警; </p><p>  液位H<2m低報警, H<1.5m低低報警。 </p><p>  

8、界位>1m高報警, 界位>1.5m高高報警; </p><p>  界位<0.5m低報警, H<0.2m低低報警;</p><p> ?。?)啟動泵組設置出入口流量(100M3/h,200M3/h,250M3/h)</p><p><b>  二、設計內容</b></p><p> ?。ㄒ唬┙M態(tài)數(shù)

9、據(jù)庫: 數(shù)據(jù)庫-----數(shù)據(jù)詞典</p><p><b>  (二)組態(tài)畫面</b></p><p>  畫面1:工藝流程總畫面</p><p><b>  對畫面的基本說明:</b></p><p>  主要功能:對油罐液位的監(jiān)測。</p><p>  泵總開關控制進口的3

10、個泵的總開和總關;</p><p>  泵總關閉控制出口的3個泵的總關和總開;</p><p>  當同時按下泵提示和某一個泵的按鈕,顯示該泵的詳細信息; </p><p>  液位報警和界位報警時記錄相應的報警事件;</p><p>  液位實時和歷史曲線記錄油罐液位的變化情況。</p><p>  畫面2:各泵彈出

11、式放大畫面(包括參狀態(tài)/型號等),點擊總畫面上的泵彈出此畫面</p><p>  1、編寫事件命令語言:當同時按下泵提示和某一個泵的按鈕,顯示該泵的參數(shù)信息。</p><p><b>  2、彈出畫面</b></p><p>  畫面3:液位/界位報警畫面</p><p><b>  報警設置:</b&g

12、t;</p><p>  低低、低、高、高高報警值設置:</p><p><b>  液位報警畫面:</b></p><p>  畫面4:液位/溫度/界位各一個實時趨勢圖和歷史趨勢圖</p><p>  實時趨勢圖: 選擇工具箱中的 工具,在畫面上繪制一實時趨勢曲線窗口。在曲線定義選項卡中選擇要實時反映的變量。</

13、p><p>  歷史趨勢圖: 對于要以歷史趨勢曲線形式顯示的變量,必須設置變量的記錄屬性。在“定義變量”對話框中單擊“記錄和安全區(qū)”屬性頁,將不記錄改為數(shù)據(jù)變化記錄,變化靈敏為:0。在工程瀏覽器窗口左側的“工程目錄顯示區(qū)”中雙擊“系統(tǒng)配置”中的“歷史數(shù)據(jù)記錄”選項,彈出“歷史記錄配置”對話框。</p><p><b>  實時和歷史趨勢圖:</b></p>

14、<p>  畫面4:報表畫面(液位,溫度,界位)</p><p>  報表分為實時數(shù)據(jù)報表和歷史數(shù)據(jù)報表。</p><p><b> ?。?)優(yōu)化設置</b></p><p><b>  1、組態(tài)操作權限</b></p><p>  優(yōu)先級分 1~999 級,1 級最低999 級最高。每個

15、操作者的優(yōu)先級別只有一個。系統(tǒng)安全區(qū)共有64 個,用戶在進行配置時。每個用戶可選擇除“無”以外的多個安全區(qū),即一個用戶可有多個安全區(qū)權限。</p><p>  設置油罐用戶組,將管理員、操作員看成用戶,并設置管理員優(yōu)先級最高,并設置相應的密碼。 配置 運行現(xiàn)象 登陸界面</p><p>  2、通過鏈接切換畫面</p&

16、gt;<p>  增加報警畫面、趨勢圖、報表畫面,通過右側鏈接</p><p><b>  (4)畫面命令語言</b></p><p>  變量說明:g1、g2、g3、g4代表每個油罐的液位,in代表泵總開,out代表泵總關,in1、in2、in3、in4代表每個油罐的入口閥門,out1、out2、out3、out4代表每個油罐的出口閥門,clear1、

17、clear2、clear3、clear4代表手動排污閥。bengin1,2,3和bengout1,2,3代表進口泵和出口泵。</p><p>  num代表泵輸入總流量的比</p><p>  num=bengin1*1 + bengin2*2 + bengin3*2.5;</p><p>  num1代表泵輸出總流量的比</p><p> 

18、 num1=bengout1*1 + bengout2*2 + bengout3*2.5;</p><p>  設置每個油罐跟液位相關的系數(shù)值</p><p>  xishu1=0.25;</p><p>  xishu2=0.2;</p><p>  xishu3=0.15;</p><p>  xishu4=0.3

19、;</p><p>  if(in==1 && num>0)</p><p><b>  {</b></p><p>  如果油罐1液位最低,增加油罐1的液位</p><p>  if(g1<=g2 && g1<=g3 && g1<=g4 &

20、& g1<16)</p><p><b>  {</b></p><p><b>  in1=1;</b></p><p><b>  in2=0;</b></p><p><b>  in3=0;</b></p><p&

21、gt;<b>  in4=0;</b></p><p>  g1=g1+num*xishu1;</p><p><b>  }</b></p><p><b>  else </b></p><p><b>  {</b></p><p

22、>  如果油罐2液位最低,增加油罐2的液位</p><p>  if(g2<g1 && g2<=g3 && g2<=g4 && g2<16)</p><p><b>  {</b></p><p><b>  in1=0;</b></p&g

23、t;<p><b>  in2=1;</b></p><p><b>  in3=0;</b></p><p><b>  in4=0;</b></p><p>  g2=g2+xishu2*num;</p><p><b>  }</b>&

24、lt;/p><p><b>  else</b></p><p><b>  {</b></p><p>  如果油罐3液位最低,增加油罐3的液位</p><p>  if(g3<g1 && g3<g2 && g3<=g4 && g3&l

25、t;16)</p><p><b>  {</b></p><p><b>  in1=0;</b></p><p><b>  in2=0;</b></p><p><b>  in3=1;</b></p><p><b&g

26、t;  in4=0;</b></p><p>  g3=g3+xishu3*num;</p><p><b>  }</b></p><p><b>  else</b></p><p><b>  {</b></p><p>  如果油罐4

27、液位最低,增加油罐4的液位</p><p>  if(g4<g1 && g4<g2 && g4<g3 && g4<16)</p><p><b>  {</b></p><p><b>  in1=0;</b></p><p>

28、<b>  in2=0;</b></p><p><b>  in3=0;</b></p><p><b>  in4=1;</b></p><p>  g4=g4+xishu4*num;</p><p><b>  }</b></p>&l

29、t;p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p>  if(out==1 && num1>0)</p&g

30、t;<p><b>  {</b></p><p>  如果油罐1液位最高,降低油罐1的液位</p><p>  if(g1>=g2 && g1>=g3 && g1>=g4 && g1>2)</p><p><b>  {</b><

31、/p><p><b>  out1=1;</b></p><p><b>  out2=0;</b></p><p><b>  out3=0;</b></p><p><b>  out4=0;</b></p><p>  g1=g1

32、-xishu1*num1;</p><p><b>  }</b></p><p><b>  else</b></p><p><b>  {</b></p><p>  如果油罐2液位最高,降低油罐2的液位</p><p>  if(g2>=g

33、1 && g2>=g3 && g2>=g4 && g2>2)</p><p><b>  {</b></p><p><b>  out1=0;</b></p><p><b>  out2=1;</b></p><

34、p><b>  out3=0;</b></p><p><b>  out4=0;</b></p><p>  g2=g2-xishu2*num1;</p><p><b>  }</b></p><p><b>  else</b></p&g

35、t;<p><b>  {</b></p><p>  如果油罐3液位最高,降低油罐3的液位</p><p>  if(g3>=g1 && g3>=g2 && g3>=g4 && g3>2)</p><p><b>  {</b><

36、/p><p><b>  out1=0;</b></p><p><b>  out2=0;</b></p><p><b>  out3=1;</b></p><p><b>  out4=0;</b></p><p>  g3=g3

37、-xishu3*num1;</p><p><b>  }</b></p><p><b>  else</b></p><p><b>  {</b></p><p>  如果油罐4液位最高,降低油罐4的液位</p><p>  if(g4>=g

38、1 && g4>=g2 && g4>=g3 && g4>2)</p><p><b>  {</b></p><p><b>  out1=0;</b></p><p><b>  out2=0;</b></p><

39、p><b>  out3=0;</b></p><p><b>  out4=1;</b></p><p>  g4=g4-xishu4*num1;</p><p><b>  }</b></p><p><b>  }</b></p>

40、<p><b>  }}}</b></p><p>  if(clear1==1 || clear2==1 || clear3==1 || clear4==1)</p><p><b>  手動排污</b></p><p><b>  {</b></p><p> 

41、 g1=g1-clear1*0.1;</p><p>  g2=g2-clear2*0.1;</p><p>  g3=g3-clear3*0.1;</p><p>  g4=g4-clear4*0.1;</p><p>  //jiewei1=jiewei1-0.1*clear1;</p><p>  //jiewe

42、i2=jiewei2-0.1*clear2;</p><p>  //jiewei3=jiewei3-0.1*clear3;</p><p>  //jiewei4=jiewei4-0.1*clear4;</p><p><b>  }</b></p><p>  如果液位大于16,關閉相應的進口閥</p>

43、<p>  if(g1>=16)</p><p><b>  {in1=0;}</b></p><p>  if(g2>=16)</p><p><b>  {in2=0;}</b></p><p>  if(g3>=16)</p><p>&l

44、t;b>  {in3=0;}</b></p><p>  if(g4>=16)</p><p><b>  {in4=0;}</b></p><p>  如果液位小于2,關閉相應出口閥</p><p><b>  if(g1<=2)</b></p><

45、;p><b>  {out1=0;}</b></p><p><b>  if(g2<=2)</b></p><p><b>  {out2=0;}</b></p><p><b>  if(g3<=2)</b></p><p><

46、b>  {out3=0;}</b></p><p><b>  if(g4<=2)</b></p><p><b>  {out4=0;}</b></p><p>  if(num==0)</p><p><b>  {</b></p>&

47、lt;p><b>  in1=0;</b></p><p><b>  in2=0;</b></p><p><b>  in3=0;</b></p><p><b>  in4=0;</b></p><p><b>  }</b&g

48、t;</p><p>  if(num1==0)</p><p><b>  {</b></p><p><b>  out1=0;</b></p><p><b>  out2=0;</b></p><p><b>  out3=0;<

49、/b></p><p><b>  out4=0;</b></p><p><b>  }</b></p><p><b>  (5)運行總畫面</b></p><p> ?。?)與PLC通信設置</p><p>  在工程瀏覽器中選擇設備—com

50、1—新建,如下圖,配置com口跟PLC連接。</p><p>  設置bengin1,2,3和bengout1,2,3分別與Q0.0等相聯(lián)系,可觀察到PLC輸出指示燈會隨著這些變量的改變和改變。</p><p><b>  三、組態(tài)王部分總結</b></p><p>  組態(tài)王是組態(tài)王軟件是一種通用的工業(yè)監(jiān)控軟件,它融過程控制設計、現(xiàn)場操作以及

51、工廠資源管理于一體,將一個企業(yè)內部的各種生產系統(tǒng)和應用以及信息交流匯集在一起,實現(xiàn)最優(yōu)化管理,操作方便,界面美觀。組態(tài)王軟件結構由工程管理器、工程瀏覽器及運行系統(tǒng)三部分構成。通過這次課程設計,我們學會了如何建立一個組態(tài)王工程,如何設計界面,編寫命令語言、以及報警事件、趨勢曲線和報表的相關制作,權限的設置,以及與實際設備的簡單通信,通過本次實習,我想在以后工作中,我們會更好的應用此例軟件,完成工業(yè)監(jiān)控。</p><p&

52、gt;<b>  智能儀表部分</b></p><p>  一、MODBUS ASCII和MODBUS RTU通訊協(xié)議簡介</p><p>  Modbus 協(xié)議是應用于電子控制器上的一種通用語言。通過此協(xié)議,控制器相互之間、控制器經(jīng)由網(wǎng)絡(例如以太網(wǎng))和其它設備之間可以通信。此協(xié)議定義了一個控制器能認識使用的消息結構,而不管它們是經(jīng)過何種網(wǎng)絡進行通信的。它描述了控制

53、器請求訪問其它設備的過程,如果回應來自其它設備的請求,以及怎樣偵測錯誤并記錄。它制定了消息域格局和內容的公共格式。</p><p>  兩種串行傳輸模式:RTU 模式和 ASCII 模式。</p><p><b>  RTU傳輸模式:</b></p><p>  當設備使用RTU (Remote Terminal Unit) 模式在Modbus

54、 串行鏈路通信, 報文中每個8位字節(jié)含有兩個4 位十六進制字符。這種模式的主要優(yōu)點是較高的數(shù)據(jù)密度,在相同的波特率下比ASCII 模式有更高的吞吐率。每個報文必須以連續(xù)的字符流傳送。</p><p>  RTU 模式每個字節(jié)( 11 位 ) 的格式為 :</p><p>  編碼系統(tǒng): 8位二進制,報文中每個8 位字節(jié)含有兩個4 位十六進制字符(0–9, A–F。)</p>

55、<p>  Bits per Byte: 1 起始位,8 數(shù)據(jù)位,首先發(fā)送最低有效位,1 位作為奇偶校驗,1停止位。</p><p><b>  ASCII傳輸模式</b></p><p>  當 Modbus 串行鏈路的設備被配置為使用ASCII (American Standard Code for Information Interchange) 模式

56、通信時, 報文中的每個 8 位子節(jié)以兩個ASCII 字符發(fā)送。</p><p>  ASCII 模式每個字節(jié)( 10 位 ) 的格式為 :</p><p>  編碼系統(tǒng): 十六進制,ASCII 字符 0-9,A-F。報文中每個ASCII 字符含有1 十六進制字符。</p><p>  Bits per Byte: 1 起始位,7 數(shù)據(jù)位,首先發(fā)送最低有效位,1 位奇

57、偶校驗,1 停止位。</p><p><b>  03讀保持寄存器</b></p><p>  上位機發(fā)送數(shù)據(jù)格式:</p><p>  “ : ” ADDRESS 03 ADDRH ADDRL NUMH NUML LRC 0X0D 0X0A</p><p>  正確時變頻器返回數(shù)據(jù)格式:</p><

58、p>  “ : “ ADDRESS 03 BYTECOUNT DATA1 DATA2 DATA3 DATAN LRC 0D 0A</p><p>  06 寫單個保持寄存器值</p><p>  上位機發(fā)送數(shù)據(jù)格式:</p><p>  “ : “ ADDRESS 06 ADDRH ADDRL DATAH DATAL LRC 0X0D 0X0A</p&g

59、t;<p>  正確時變頻器返回數(shù)據(jù)格式:</p><p>  “ : “ ADDRESS 06 ADDRH ADDRL DATAH DATAL LRC 0X0D 0X0A</p><p>  二、MODBUS ASCII編程以及與組態(tài)王通信</p><p><b>  1、變量定義</b></p><p>

60、;  unsigned char ERR[21]= " Input LRC ERROR!"; //出錯時顯示字符</p><p>  unsigned char RX[32]; //單片機接受數(shù)據(jù)數(shù)組</p><p>  unsigned char TX[32]; //03功能時單片機發(fā)送數(shù)據(jù)數(shù)組</p><p>  unsigned char

61、TX6[32]; //06功能時單片機發(fā)送數(shù)據(jù)數(shù)組</p><p>  unsigned char Buf[10]; //存儲數(shù)據(jù)的數(shù)組</p><p>  unsigned int flag; // 上位機發(fā)送數(shù)據(jù)標志位</p><p>  unsigned int flag1; //單片機應答數(shù)據(jù)標志位</p><p>  unsigne

62、d int flow; // 流量值</p><p>  unsigned int temperature; //溫度值</p><p>  unsigned char LRC; //上位機發(fā)送數(shù)據(jù)校驗碼</p><p>  unsigned char LRCt; //單片機應答數(shù)據(jù)校驗碼</p><p>  2、通過UART中斷完成上位機給

63、單片機發(fā)送</p><p><b>  編程思路:</b></p><p>  通過UART中斷,實現(xiàn)上位機給單片機發(fā)送數(shù)據(jù),當單片機接受到:,表示上位機要向單片機發(fā)送指令,相應標志位置1,當再次發(fā)生中斷時,就開始接受數(shù)據(jù),同時存入RX[32]的數(shù)組里,直到接收到回車換行符,則發(fā)送命令結束。此時發(fā)送標志位置1,進入應答程序。</p><p> 

64、 #pragma vector=USCI_A1_VECTOR</p><p>  __interrupt void USCI_A1_ISR(void)</p><p><b>  {</b></p><p>  while (!(UCA1IFG & UCTXIFG)); // 判斷是否發(fā)送完畢</p

65、><p>  if(UCA1RXBUF == ':') //:為起始標志,如果開始,標志位flag置位</p><p><b>  {</b></p><p><b>  flag = 1;</b></p><p><b>  }</b></p>&

66、lt;p>  if(flag==1) //當標志位flag置位說明發(fā)送命令開始,開始接受命令數(shù)據(jù)</p><p><b>  {</b></p><p>  RX[0] = ':';</p><p>  if(UCA1RXBUF != 0x0D && UCA1RXBUF != 0x0A ) //只要不是回

67、車換行符,就依次將數(shù)據(jù)存入接受數(shù)組RX中,同時計數(shù)變量tempnumb加1</p><p><b>  {</b></p><p>  tempnumb++;</p><p>  RX[tempnumb] = UCA1RXBUF ;</p><p><b>  }</b></p>&l

68、t;p>  if(UCA1RXBUF == 0x0D) //若是回車</p><p><b>  {</b></p><p>  tempnumb++;</p><p>  RX[tempnumb] = 'D' ;</p><p><b>  }</b></p>

69、<p>  if(UCA1RXBUF == 0x0A) //若是換行</p><p><b>  {</b></p><p>  tempnumb++;</p><p>  RX[tempnumb] = 'A' ;</p><p>  flag=0; //接受標志位清零

70、</p><p>  flag1=1; //發(fā)送標志位置1</p><p>  TTXX(); //調用發(fā)送數(shù)據(jù)函數(shù)</p><p><b>  }</b></p><p><b>  }</b></p><p><b>

71、;  }</b></p><p>  3、單片機通過UART中斷向上位機發(fā)送應答指令</p><p><b>  編程思路:</b></p><p>  先計算上位機發(fā)送數(shù)據(jù)的校驗碼,如果和發(fā)送的校驗碼相同,單片機再應答。設置寄存器地址0001,存儲流量數(shù)據(jù);設置寄存器0002,存儲溫度數(shù)據(jù)。然后判斷是03號功能還是06號功能,若是

72、03號功能,按照相應的格式發(fā)送數(shù)據(jù),若是06號功能,按照命令更改數(shù)據(jù),并返回應答命令。</p><p>  void TTXX()</p><p><b>  {</b></p><p><b>  int i;</b></p><p><b>  int j;</b><

73、/p><p>  unsigned int b;</p><p>  unsigned int c;</p><p>  unsigned int d;</p><p>  In_LRC(); //計數(shù)上位機發(fā)送命令校驗碼</p><p>  if(RX[8]=='1') //如果地址為寄存器0001,發(fā)

74、送流量數(shù)據(jù)</p><p>  shitohex(flow);</p><p>  if(RX[8]=='2') //如果地址位寄存器0002,發(fā)送溫度數(shù)據(jù)</p><p>  shitohex(temperature); </p><p>  if(RX[3]=='0' && RX[4]==

75、'3') //如果是03號功能</p><p><b>  {</b></p><p>  if((LRCHi == RX[tempnumb-3]) &&(LRCLo == RX[tempnumb-2])) //如果上位機發(fā)送校驗碼正確</p><p><b>  {</b></p&g

76、t;<p>  for(b=0;b<=4;b++)</p><p><b>  { </b></p><p>  TX[b] = RX[b];</p><p><b>  }</b></p><p>  temp = asciitohex(RX[tempnumb-4]); //計

77、算單片機要發(fā)送數(shù)據(jù)的字節(jié)數(shù)</p><p>  TX[5] = hextoascii(((temp*2)>>4)&0x0F);</p><p>  TX[6] = hextoascii((temp*2)&0x0F);</p><p>  for(i=0;i<temp*4;i+=2)</p><p><b

78、>  {</b></p><p>  TX[7+i] = hextoascii(Buf[i]); //要發(fā)送的數(shù)據(jù)</p><p>  TX[8+i] = hextoascii(Buf[i+1]);</p><p><b>  }</b></p><p>  tempnumt = 7+i; //統(tǒng)計數(shù)據(jù)

79、長度,用于計算校驗碼</p><p>  Out_LRC(); //計算單片機發(fā)送數(shù)據(jù)校驗碼</p><p>  TX[7+i] = LRCtHi;</p><p>  TX[8+i] = LRCtLo;</p><p>  TX[9+i] = 0x0D;</p><p>  TX[10+i] = 0x0A; <

80、/p><p>  for(j=0;j<=(10+i);j++) //單片機發(fā)送數(shù)據(jù)</p><p><b>  {</b></p><p>  while (!(UCA1IFG & UCTXIFG)); // 判斷是否發(fā)送完畢</p><p>  UCA1TXBUF=TX[j];

81、</p><p><b>  }</b></p><p><b>  }</b></p><p>  else //如果校驗碼不正確,返回錯誤代碼 Input LRC ERROR!只能通過串口調試看到</p><p><b>  {</b></p><p

82、>  ERR[19]='8';</p><p>  ERR[20]=TX[4];</p><p>  for(d=0;d<=20;d++)</p><p><b>  {</b></p><p>  while (!(UCA1IFG & UCTXIFG));

83、// 判斷是否發(fā)送完畢</p><p>  UCA1TXBUF=ERR[d] ; </p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p>  else if(RX[3]=

84、='0' && RX[4]=='6') //如果是06號功能</p><p><b>  {</b></p><p>  for(c=0;c<=tempnumb;c++)</p><p><b>  {</b></p><p>  TX6

85、[c] = RX[c];</p><p>  while (!(UCA1IFG & UCTXIFG)); // 判斷是否發(fā)送完畢</p><p>  UCA1TXBUF=TX6[c];</p><p><b>  }</b></p><p>  selflow(TX6[10]);

86、 //設置流量值</p><p>  seltemp(TX6[11]); //設置溫度值</p><p><b>  }</b></p><p>  flag1=0; //單片機發(fā)送標志位清零</p><p>  tempnumb=0; //上位機發(fā)送數(shù)據(jù)計算值清零</p>

87、<p><b>  } </b></p><p><b>  4、輔助模塊部分</b></p><p> ?。?)、LRC校驗模塊</p><p><b>  編程思路 :</b></p><p>  LRC 的計算, 對報文中的所有的連續(xù)8 位字節(jié)相加,忽略任何進位

88、,然后求出其二進制補碼。</p><p>  unsigned char *auchMsg; 指向含有用于生成LRC 的二進制數(shù)據(jù)報文緩沖區(qū)的指針,</p><p>  unsigned short usDataLen; 報文緩沖區(qū)的字節(jié)數(shù).</p><p>  unsigned char MODBUS_LRC(unsigned char *auchMsg, uns

89、igned short usDataLen)</p><p><b>  {</b></p><p>  unsigned char uchLRC = 0 ; // LRC 初始化</p><p>  while (usDataLen--) // 完成整個報文緩沖區(qū)</p><p>  uchLRC += *auchMs

90、g++ ; //緩沖區(qū)字節(jié)相加,無進位</p><p>  return ((unsigned char)(-((char)uchLRC))) ; // 返回二進制補碼</p><p><b>  }</b></p><p> ?。?)發(fā)送和應答校驗碼計數(shù)程序</p><p>  void In_LRC()</p&

91、gt;<p><b>  {</b></p><p>  unsigned int a;</p><p>  for(a=1;a<(tempnumb-3);a+=2)</p><p><b>  {</b></p><p>  tempRX[(a-1)/2] = (asciito

92、hex(RX[a])<<4) | asciitohex(RX[a+1]);</p><p><b>  }</b></p><p>  LRC=MODBUS_LRC(&tempRX[0],(tempnumb-4)/2); //進行LRC效驗計算</p><p>  LRCHi = hextoascii((LRC>>

93、;4)&0x0F);</p><p>  LRCLo = hextoascii(LRC&0x0F);</p><p><b>  }</b></p><p>  void Out_LRC()</p><p><b>  {</b></p><p>  unsi

94、gned int c;</p><p>  for(c=1;c<tempnumt;c+=2)</p><p><b>  {</b></p><p>  tempTX[(c-1)/2] = (asciitohex(TX[c])<<4);</p><p>  tempTX[(c-1)/2] = (asci

95、itohex(TX[c])<<4) | asciitohex(TX[c+1]);</p><p><b>  }</b></p><p>  LRCt=MODBUS_LRC(&tempTX[0],(tempnumt-1)/2); //進行LRC效驗計算</p><p>  LRCtHi = hextoascii((LRCt&

96、gt;>4)&0x0F);</p><p>  LRCtLo = hextoascii(LRCt&0x0F); </p><p><b>  }</b></p><p> ?。?)進制之間轉換程序</p><p>  由于發(fā)送和讀取的數(shù)據(jù)是字符,而寄存器中數(shù)據(jù)多按照十六進制存儲,故需要各種進制間的相

97、互轉換。</p><p>  //十六進制數(shù)轉換為ASCII碼</p><p>  unsigned char hextoascii(unsigned char hex)</p><p><b>  {</b></p><p>  if(hex<=0x09)</p><p>  return

98、 hex+0x30;</p><p><b>  else</b></p><p>  return hex+0x37;</p><p><b>  }</b></p><p>  //ASCII碼轉換為十六進制的數(shù)</p><p>  unsigned char ascii

99、tohex(unsigned char ascii)</p><p><b>  {</b></p><p>  if(ascii<=0x39)</p><p>  return ascii-0x30;</p><p><b>  else</b></p><p>  

100、return ascii-0x37;</p><p><b>  }</b></p><p>  //十進制轉十六進制,由于組態(tài)王通信時會自動將十六進制數(shù)轉換位十進制數(shù),因此需要在單片機內將十進制數(shù)轉換位十六進制數(shù),這樣組態(tài)王讀到的就是十進制的數(shù)據(jù)。</p><p>  unsigned char shitohex(unsigned int s

101、hi)</p><p><b>  {</b></p><p>  int i,b,d,c;</p><p><b>  int a=0;</b></p><p><b>  d=4;</b></p><p>  char shiliu[10];<

102、/p><p>  while (shi) //shi代表相應的十進制數(shù)</p><p><b>  {</b></p><p>  c=shi%16; //每次除以16取余求得相應的十六進制數(shù)</p><p>  shi=shi/16;</p><p>  shiliu[a] = c;

103、</p><p><b>  a++;</b></p><p><b>  }</b></p><p>  for(i=a;i<=4;i++) //得到的數(shù)據(jù)首位倒置,才是要求的十六進制數(shù)</p><p><b>  {</b></p><p> 

104、 shiliu[i]=0;</p><p><b>  }</b></p><p>  for(b=0;b<4;b++)</p><p><b>  {</b></p><p><b>  d--;</b></p><p>  Buf[b]=shi

105、liu[d];</p><p><b>  }</b></p><p><b>  return 0;</b></p><p><b>  }</b></p><p> ?。?)波特率,流量、溫度的設置</p><p><b>  //選定流量

106、</b></p><p>  void selflow(unsigned char selflow)</p><p><b>  {</b></p><p>  switch(selflow)</p><p><b>  {</b></p><p>  case

107、'0':flow=100; break;</p><p>  case '1':flow=1799; break; </p><p>  case '2':flow=5000; break;</p><p>  default:flow=1799; break;</p><p><b&

108、gt;  }</b></p><p><b>  }</b></p><p><b>  //選定溫度</b></p><p>  void seltemp(unsigned char seltemp)</p><p><b>  {</b></p>

109、<p>  switch(seltemp)</p><p><b>  {</b></p><p>  case '0':temperature=1;break;</p><p>  case '1':temperature=20; break; </p><p>  ca

110、se '2':temperature=100; break;</p><p>  default:temperature=20; break;</p><p><b>  }</b></p><p><b>  }</b></p><p><b>  //設定波特率<

111、/b></p><p>  void selbps(unsigned char selbps)</p><p><b>  {</b></p><p>  switch(selbps)</p><p><b>  {</b></p><p>  case '0&

112、#39;: UCA1CTL1 |= UCSSEL_1; // 時鐘源選擇</p><p>  UCA1BR0 = 0x1B; //1200 </p><p>  UCA1BR1 = 0x00;</p><p>  UCA1MCTL = 04; &l

113、t;/p><p><b>  break;</b></p><p>  case '1': UCA1CTL1 |= UCSSEL_1; // 時鐘源選擇</p><p>  UCA1BR0 = 0x0D; //2400

114、 </p><p>  UCA1BR1 = 0;</p><p>  UCA1MCTL = 0X0A; </p><p><b>  break;</b></p><p>  case '2': UCA1CTL1 |= UCSSEL_1; // 時鐘源選擇</p>

115、<p>  UCA1BR0 = 6; //4800 </p><p>  UCA1BR1 = 0;</p><p>  UCA1MCTL = 0x0C;</p><p>  UCA1CTL1 &= ~UCSWRST; // 使能串

116、口功能</p><p>  UCA1IE |= UCRXIE; // 使能接收中斷</p><p>  _BIS_SR(GIE); </p><p><b>  break;</b></p><p>  case '3': UCA1CTL1 |= UCSSEL_1;

117、 // 時鐘源選擇</p><p>  UCA1BR0 = 3; //9600 </p><p>  UCA1BR1 = 0;</p><p>  UCA1MCTL = 06; </p><p>  UCA1CTL1 &=

118、 ~UCSWRST; // 使能串口功能</p><p>  UCA1IE |= UCRXIE; // 使能接收中斷</p><p>  _BIS_SR(GIE); </p><p><b>  break;</b></p><p>  default:UCA1CTL1

119、|= UCSSEL_1; // 時鐘源選擇</p><p>  UCA1BR0 = 3; // 32768hz/3=9600</p><p>  UCA1BR1 = 0;</p><p>  UCA1MCTL = 06; </p><p><b>  break;</b

120、></p><p><b>  }</b></p><p><b>  }</b></p><p>  5、實驗現(xiàn)象: 測試IO設備界面</p><p>  組態(tài)王畫面:實現(xiàn)讀寫功能</p><p>  三、MODBUS RTU編程以及與組態(tài)王通信</p>

121、<p><b>  1、變量定義</b></p><p>  int R_flag=1; // 延時3.5字符標志</p><p>  int R_flag1=0;</p><p>  int R_flag2=1;</p><p>  unsigned char Crc_RX[32]; //存儲上位機發(fā)送的

122、字符的數(shù)組</p><p>  unsigned char Crc_TX[32]; //存儲單片機應答的字符的數(shù)組</p><p>  unsigned int crcnumt; // 統(tǒng)計上位機發(fā)送字符數(shù)據(jù)長度</p><p>  unsigned int crcnumr; //統(tǒng)計單片機應答數(shù)據(jù)長度</p><p>  unsigned

123、 char CRCHi8; //上位機發(fā)送數(shù)據(jù)的校驗碼高位</p><p>  unsigned char CRCLo8; //上位機發(fā)送數(shù)據(jù)的校驗碼低位</p><p>  unsigned char CRCtHi8; //單片機發(fā)送數(shù)據(jù)的校驗碼高位</p><p>  unsigned char CRCtLo8; //單片機應答數(shù)據(jù)的校驗碼低位</p>

124、;<p>  unsigned char Buf[10]; //測試數(shù)據(jù)</p><p>  2、設計延時3.5字符控制發(fā)送和接受數(shù)據(jù)的開始和接受</p><p>  while (1) //接收 起始 結束 判斷函數(shù)</p><p><b>  {</b></p><p>  if(R_fla

125、g1==1)</p><p><b>  {</b></p><p>  if(count_leg==300) //此時間遠大于3.5個字符,確保通信的正確</p><p><b>  {</b></p><p><b>  RTU_T();</b></p>&l

126、t;p>  R_flag = 1;</p><p>  count_leg=0;</p><p>  R_flag1=0;</p><p><b>  }</b></p><p><b>  else</b></p><p><b>  {</b>

127、</p><p>  count_leg=count_leg+1;</p><p><b>  }</b></p><p><b>  }</b></p><p>  3、通過UART中斷完成上位機給單片機發(fā)送</p><p>  編程思路:通過UART中斷完成上位機給單片機

128、發(fā)送,當延時大于3.5個字符,R_flag==1,依次將值存入 Crc_RX[]數(shù)組中 ,再判斷,若延時大于3.5個字符,則發(fā)送結束,R_flag1=1。</p><p>  #pragma vector=USCI_A1_VECTOR</p><p>  __interrupt void USCI_A1_ISR(void)</p><p><b>  {&

129、lt;/b></p><p>  if(R_flag==1)</p><p><b>  {</b></p><p>  Crc_RX[crcnumr] = UCA1RXBUF;</p><p>  crcnumr++;</p><p>  if(crcnumr==8)</p>

130、<p><b>  { </b></p><p>  R_flag1=1;</p><p><b>  R_flag=0;</b></p><p><b>  } </b></p><p><b>  }</b></p><

131、;p>  4.通過UART中斷完成單片機應答上位機</p><p>  首先計算校驗碼,若校驗碼正確,計算應答指令每位的值,存入Crc_TX[]中。</p><p>  void RX_TX()</p><p><b>  {</b></p><p>  unsigned int b;</p><

132、;p>  In_CRC(); //計算上位機發(fā)送數(shù)據(jù)的校驗碼</p><p>  if((CRCHi8 == Crc_RX[crcnumr-2])&&(CRCLo8 == Crc_RX[crcnumr-1]))</p><p>  { //若校驗碼正確</p><p>  for(b=0;b<2;b++)</p>&l

133、t;p><b>  { </b></p><p>  Crc_TX[b] = Crc_RX[b];</p><p><b>  }</b></p><p>  Bytenum(); //計算單片機應答的字節(jié)數(shù)</p><p>  Out_CRC(); //計算單片機應答數(shù)據(jù)的校驗碼</p

134、><p><b>  }</b></p><p><b>  }</b></p><p>  void RTU_T() //通過該程序將Crc_TX[]發(fā)送到上位機</p><p><b>  {</b></p><p><b>  int i;

135、 </b></p><p><b>  int j;</b></p><p><b>  RX_TX();</b></p><p>  for(j=0;j<=200;j++) ; // 延時4毫秒——發(fā)送開始</p><p>  for(i=0;i<=(crc

136、numt+1);i++) </p><p><b>  {</b></p><p>  while (!(UCA1IFG & UCTXIFG)); // 判斷是否發(fā)送完畢 </p><p>  UCA1TXBUF =Crc_TX[i];</p><p><b>  }<

137、;/b></p><p>  for(j=0;j<=200;j++) ; // 延時4毫秒——發(fā)送結束</p><p>  crcnumr=0;</p><p><b>  }</b></p><p><b>  5、輔助模塊</b></p><p&g

138、t; ?。?)CRC校驗程序</p><p><b>  編程思路:</b></p><p>  1. 將一個16 位寄存器裝入十六進制FFFF (全1). 將之稱作CRC 寄存器.</p><p>  2. 將報文的第一個8位字節(jié)與16 位CRC 寄存器的低字節(jié)異或,結果置于CRC 寄存器.</p><p>  3.

139、將CRC 寄存器右移1位(向LSB 方向), MSB 充零. 提取并檢測LSB.</p><p>  4. (如果LSB 為0): 重復步驟3 (另一次移位).</p><p>  (如果LSB 為1): 對CRC 寄存器異或多項式值0xA001 (1010 0000 0000 0001).</p><p>  5. 重復步驟3 和 4,直到完成8 次移位。當做完此

140、操作后,將完成對8位字節(jié)的完整操作。</p><p>  6. 對報文中的下一個字節(jié)重復步驟2 到5,繼續(xù)此操作直至所有報文被處理完畢。</p><p>  7. CRC 寄存器中的最終內容為CRC 值.</p><p>  8. 當放置CRC 值于報文時,如下面描述的那樣,高低字節(jié)必須交換。</p><p><b>  數(shù)據(jù)表:&

141、lt;/b></p><p>  static unsigned char auchCRCHi[] = {</p><p>  0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,</p><p>  0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論