{心中有空間,夢想就有可能}
{西門子與客戶攜手,讓關(guān)鍵所在,逐一實現(xiàn)}
聯(lián) 系 人: 黃勇《黃工》 24小時聯(lián)系手機: 13701633515
直線銷售 電 話: 021-31660605 在 線 商 務(wù) QQ: 77956468
單位:臺 產(chǎn)品單價:電議
供貨數(shù)量:不限 最小定量:1
包裝說明:齊全 產(chǎn)品規(guī)格:全新原裝
在S7-200編程中,子程序想必大家都用過,使用子程序可以更好地組織程序結(jié)構(gòu),便于閱讀和調(diào)試,也可以縮短程序代碼。但是使用子程序也有一些需要注意的地方,除了子程序在同一周期內(nèi)被多次調(diào)用時,不能使用上升沿、下降沿、定時器和計數(shù)器之外,還有子程序中局部變量的特點,在編程多次調(diào)用帶參數(shù)子程序時要特別注意。下面就是前些天熱線上遇到的一個Case,非常有代表性,在這里跟大家分享。
E:您好,西門子技術(shù)支持。
C:您好,我想問下,200子程序是不是多次調(diào)用時會不好使?
E:不會啊,您是不是在子程序里使用了沿指令或者定時器?
C:沒有啊,我就編了一句很簡單的開關(guān)程序,開關(guān)閉合,線圈導通,然后主程序里調(diào)用了兩次這個子程序,結(jié)果第一個I點閉合了,兩個Q點都導通了。
E:(心里活動:看來是和子程序的局部變量有關(guān)了,估計客戶程序邏輯有問題)那請您描述一下您的子程序吧,我?guī)湍纯础?/span>
于是客戶描述了一下自己的程序,大致了解了之后告知客戶我這邊測試下,稍后回復。
客戶的程序是這樣的:
子程序:是個常見的自保持邏輯,接口參數(shù)如紅框所示。
圖. 01
主程序:調(diào)用了兩次上面的子程序,實現(xiàn)I0.0和I0.1控制Q0.0的閉合和斷開,I0.2和I0.3控制Q0.1的閉合和斷開。
圖. 02
那么在線測試下程序執(zhí)行情況,發(fā)現(xiàn)果然如客戶所描述的,I0.0為1后,Q0.0和Q0.1都為1了。見下圖.03所示。而如果閉合I0.2,則Q0.0和Q0.1都斷開。
圖. 03
為什么會這樣呢?首先我們先明確子程序局部變量的特點。局部變量的變量類型分為四種:IN,IN_OUT,OUT和TEMP,局部變量存儲區(qū)是在子程序調(diào)用時開辟的,子程序調(diào)用完成,局部變量占用的存儲空間釋放。
我們來分析下客戶的子程序。
在主程序第一次調(diào)用子程序時,如果I0.0為1,I0.1為0,它們將自身值分別傳給輸入局部變量#AA和#BB,子程序中程序邏輯執(zhí)行如下圖.04所示。此時局部變量#CC值為1,子程序完成,#CC將值傳送到輸出參數(shù)Q0.0上,使其置1。根據(jù)局部變量的特點,子程序第一次調(diào)用完成后,局部變量存儲區(qū)釋放。
圖.04
那么當主程序第二次調(diào)用該子程序時,開辟臨時存儲空間,但是此時的存儲空間與第一次調(diào)用時開辟的不一定一致?墒,也有可能由于程序簡單,仍然使用第一次調(diào)用時占用的存儲空間。如果這種情況發(fā)生了,那么第一次調(diào)用時已經(jīng)將#CC的L0.2置了1,而此值依舊存在,那么第二次調(diào)用時雖然輸入?yún)?shù)I0.2和I0.3為0 ,但是#CC(L0.2)為1,由于客戶的子程序邏輯有自保持部分,所以最后L0.2的邏輯結(jié)果仍然是1。子程序完成后,#CC將值傳送到輸出參數(shù)Q0.1上,使其置1。所以就會出現(xiàn)客戶反映的那種問題。
那么該如何避免這種情況呢?
大家是否還記得剛剛介紹局部變量參數(shù)類型時除了IN, OUT類型外,還有一種類型叫IN_OUT,這種類型的參數(shù)是先讀入,然后再寫出,這里我們就可以利用它的特點解決上面的問題。
下面對子程序的參數(shù)進行修改,將原先的#CC變量類型改為IN_OUT。如下圖所示:
圖.05
主程序結(jié)構(gòu)不變,如下所示,可以看到由于#CC的類型是IN-OUT,它在子程序塊的接口位置也轉(zhuǎn)到了左側(cè)輸入側(cè)。
圖.06
下面再次將I0.0置1,其他輸入都為0,監(jiān)控程序狀態(tài),如圖.07所示,可以看到只有Q0.0為1,Q0.1狀態(tài)為0。而如果將I0.1置1, Q0.0被復位,Q0.1還是0,這樣就符合客戶的控制要求了。
圖.07
同樣,如果只給I0.2置1,那么也只有Q0.1會亮,不會再影響Q0.0。
了解了IN_OUT類型變量的特點,就不難分析以上的結(jié)果。因為每次調(diào)用子程序時,局部變量#CC都會先去讀取輸入?yún)?shù)Q0.0或Q0.1的狀態(tài),所以即使兩次調(diào)用子程序時,#CC變量使用的同一區(qū)域,該區(qū)域的值也會在開始被Q點的狀態(tài)所修改,就不存在兩次調(diào)用相互影響的情況了。
另外,如果在子程序一開始就添加一條指令,對局部變量#CC進行賦初值(如圖.08),也可以避免臨時變量區(qū)數(shù)值不定的問題,您可以嘗試測試下。
圖.08
所以,在編寫200子程序時要特別注意局部變量的特點,一旦出現(xiàn)多次調(diào)用不正常的情況,就可以從局部變量的特點出發(fā)分析,看看是不是存在隱患。善加利用IN_OUT變量也許可以解決許多問題。
1、 配置OPC服務(wù)器
對于服務(wù)器的配置與同步通訊的配置一樣,這里不需再講解,若有不清楚的,可以參閱之前發(fā)布的<運用VC#編程通過OPC方式實現(xiàn)PC機與西門子PLC通訊>
2、 OPC編程
變量組、項的命名規(guī)則與同步通訊的一樣,這里不再描敘,下面主要就開發(fā)一個異步通訊類 AsynServer來講解如何編程。
<1>、引用
在VC#開發(fā)環(huán)境中添加對OpcRcw.Da庫以及OpcRcw.Comn庫的引用,該庫屬于.NET庫,不屬于COM庫,西門子雖然編寫了類庫,以提供對.NET平臺的支持,但這些類庫仍然難于編程,里面包含了大量的在托管和非托管區(qū)傳輸數(shù)據(jù),因此我們需要在它的基礎(chǔ)上再開發(fā)一個類庫,以簡化以后的編程,首先在類的開頭使用命名空間:
using OpcRcw.Comn;
using OpcRcw.Da;
using System.Runtime.InteropServices;
using System.Collections;
<2>、編程
異步編程的原理就是在OPC服務(wù)器那邊檢測當前活動的變量組,一但檢測到某一個變量,譬如變量Q0.0從1變成0,就會執(zhí)行一個回調(diào)函數(shù),以實現(xiàn)針對變量發(fā)生變化時需要實現(xiàn)的動作,在這里可以采用委托來實現(xiàn)該功能。
1、 在命名空間的內(nèi)部、類 AsynServer聲明之前添加委托的申明:
// 定義用于返回發(fā)生變化的項的值和其對應的客戶句柄
public delegate void DataChange(object[] values,int[] itemsID);
2、 該類繼承于西門子提供的庫接口IOPCDataCallback
public class AsynServer:IOPCDataCallback
在類的開頭部分聲明變量:
struct groupStru
{
public int groupID;
public object groupObj;
}
internal const int LOCALE_ID = 0x407; //本地語言
private Guid iidRequiredInterface;
private string serverType="";
private int hClientGroup = 0; //客戶組號
private int nSvrGroupID; // server group handle for the added group
private Hashtable hashGroup; //用于把組收集到一起
private int hClientItem=0; //Item號
3、編寫構(gòu)造函數(shù),接收委托參數(shù)已確定當數(shù)據(jù)發(fā)生變化時需要執(zhí)行的方法入口點:
//創(chuàng)建服務(wù)器
//svrType 服務(wù)器類型的枚舉
//dataChange 提供用于在數(shù)據(jù)發(fā)生變化時需要執(zhí)行的函數(shù)入口
public AsynServer(ServerType svrType,DataChange dataChange)
{
switch(svrType)
{
case ServerType.OPC_SimaticHMI_PTPR
serverType="OPC.SimaticHMI.PTPro";break;
case ServerType.OPC_SimaticNET:
serverType="OPC.SimaticNET";break;
case ServerType.OPC_SimaticNET_DP:
serverType="OPC.SimaticNET.DP";break;
case ServerType.OPC_SimaticNET_PD:
serverType="OPC.SimaticNET.PD";break;
case ServerType.OPCServer_WinCC:
serverType="OPCServer.WinCC";break;
}
hashGroup=new Hashtable(11);
dtChange=dataChange;
}
4、創(chuàng)建服務(wù)器
// 創(chuàng)建一個OPC Server接口
//error 返回錯誤信息
//若為true,創(chuàng)建成功,否則創(chuàng)建失敗
public bool Open(out string error)
{
error="";bool success=true;
Type svrComponenttyp ;
//獲取 OPC Server COM 接口
iidRequiredInterface = typeof(IOPCItemMgt).GUID;
svrComponenttyp = System.Type.GetTypeFromProgID(serverType);
try
{
//創(chuàng)建接口
pIOPCServer =(IOPCServer)System.Activator.CreateInstance(svrComponenttyp);
error="";
}
catch (System.Exception err) //捕捉失敗信息
{
error="錯誤信息:"+err.Message;success=false;
}
return success;
}
5、 編寫添加Group的函數(shù)
///
定貨號 | 注釋 |
6EP1331-1SH02 | 單相220VAC輸入,輸出24VDC 1.3A |
6EP1331-2BA00 | 單相220VAC輸入,輸出24VDC 2A |
6EP1332-2BA00 | 單相220VAC輸入,輸出24VDC 3.8A |
6EP1332-2BA10 | 單相120/220VAC輸入,輸出24VDC 2.5A |
6EP1333-2AA00 | 單相220VAC輸入,輸出24VDC 5A 工業(yè)可并聯(lián) |
6EP1333-2AA01 | 單相120/230VAC輸入,輸出24VDC 5A 工業(yè)可并聯(lián) |
6EP1333-2BA00 | 單相120VAC/220VAC輸入,輸出24VDC 5A |
6EP1333-2BA01 | 單相120VAC/220VAC輸入,輸出24VDC 5A |
6EP1333-3BA00 | 單相120VAC/220to500VAC輸入,輸出24VDC 5A |
6EP1334-2AA00 | 單相220VAC輸入,輸出24VDC 10A 工業(yè)可并聯(lián) |
6EP1334-2AA01 | 單相120/220VAC輸入,輸出24VDC 10A 工業(yè)可并聯(lián) |
6EP1334-2BA00 | 單相220VAC輸入,輸出24VDC 10A |
6EP1334-2BA01 | 單相220VAC輸入,輸出24VDC 10A |
6EP1334-3BA00 | 單相120/220VACto500VAC輸入,輸出24VDC 10A |
6EP1336-2BA00 | 單相220VAC輸入,輸出24VDC 20A |
6EP1336-3BA00 | 單相220VAC輸入,輸出24VDC 20A 工業(yè)可并聯(lián) |
6EP1337-3BA00 | 單相120/230,40A |
6EP1434-2BA00 | 三相380VAC輸入,輸出24VDC 10A 工業(yè)可并聯(lián) |
6EP1436-2BA00 | 三相380VAC輸入,輸出24VDC 20A 工業(yè)可并聯(lián) |
6EP1332-2BA20 | 三相380VAC輸入,輸出24VDC 20A 新型模塊式電源 |
6EP1332-2BA30 | 三相380VAC輸入,輸出24VDC 30A 工業(yè)可并聯(lián) |
6EP1333-2AA02 | 三相380VAC輸入,輸出24VDC 40A 工業(yè)可并聯(lián) |
6EP1333-2AA03 | 三相380VAC輸入,輸出24VDC 40A 工業(yè)可并聯(lián) |
6EP1252-0AA00 | 單相230VAC輸入,輸出41.5V/1.3A |
6EP1252-0AA01 | 單相230VAC輸入,輸出41.5V/2A |
6EP1457-3BA00 | 三相380VAC輸入,輸出48VDC 20A 工業(yè)可并聯(lián) |
SIYOUNG 電源 | |
6EP0123-2AA00-0AA0 | 單相230VAC輸入,輸出24VDC 2.5A |
6EP0123-2AA00-0AB0 | 單相230VAC輸入,輸出24VDC 4A |
6EP0123-3AA00-0AB0 | 單相230VAC輸入,輸出24VDC 6A |
6EP0123-4AA00-0AB0 | 單相230VAC輸入,輸出24VDC 12A |
SITOP facets | |
6EP1331-2BA10 | 單相120/230VAC輸入,輸出24VDC 0.5A |
6EP1333-1AL12 | 單相120/230VAC輸入,輸出24VDC 5A |
6EP1334-1AL12 | 單相120/230VAC輸入,輸出24VDC 10A |
6ES7307-1EA80-0AA0 | 單相120/230VAC輸入,輸出24VDC 10A |
6EP1353-2BA00 | 單相120/230VAC輸入,輸出24VDC 設(shè)定范圍3~52DC 10A |
LOGO! Power 微型電源組 | |
6EP1332-1SH42 | 單相220VAC輸入,輸出24VDC 2.5A |
6EP1332-1SH51 | 單相220VAC輸入,輸出24VDC 4A |
SITOP 附加設(shè)備 | |
6EP1961-3BA10 | 信號模塊,輸入范圍240VAC/6A,只能和模塊式SITOP電源共用 |
6EP1961-3BA00 | 緩沖模塊,輸入24VDC,輸出電流40A,可并聯(lián),只能和模塊式SITOP電源共用 |
6EP1961-3BA20 | 冗余模塊,輸入24VDC,輸出電流40A |
6EP1961-2BA00 | 診斷模塊,輸入24VDC,輸出電流4*10A |