運用VC#編程通過MPI方式與西門子S7系列PL;大家只要找到西門子的ProDave中的動態連接庫;由于W95_S7.DLL是用C語言編寫的,很多函;一、C#中調用DLL庫的方法;1、在名稱空間之前使用:;usingSystem.Runtime.Inte;2、導入每一個庫函數,均要在函數聲明之前使用屬性;[DllImport("w95_s7.;譬如
運用VC#編程通過MPI方式與西門子S7系列PLC通訊 西門子S7300/400系列的PLC沒有公開通訊協議,但西門子公司提供的ProDave軟件公開了一系列庫函數,使用計算機高級語言調用這些函數,可實現以MPI的方式與PLC通訊。當今的高級語言VC#有著非常高效的開發手段,在把基礎類庫、標準模塊都編好的情況下,開發監控界面的速度比WinCC慢不了多少,但靈活性卻是WInCC無法比的。
大家只要找到西門子的ProDave中的動態連接庫:W95_S7.DLL,并把它注冊到你的計算機即可(當然,你若有一套完整的ProDave安裝程序,安裝即可自動注冊),然后在C#這邊編程調用,下面來講解如何在C#中調用動態庫。
由于W95_S7.DLL是用C語言編寫的,很多函數接口不適用于C#,因此我們可以創建一個C#類庫,把這些函數進行封裝,每次開發監控界面調用此類庫即可。
一、 C#中調用DLL庫的方法
1、 在名稱空間之前使用:
using System.Runtime.InteropServices; //用于調用動態庫的接口,一定要引用
2、 導入每一個庫函數,均要在函數聲明之前使用屬性字段:
[DllImport("w95_s7.dll")]
譬如與PLC建立連接的庫函數load_tool(),應使用如下的方式進行聲明:
[DllImport("w95_s7.dll")]
private extern static int load_tool(byte nr,string device,byte[,] adr_table);
二、 ProDave中的重要庫函數介紹
1、 與PLC建立通訊連接的庫函數:load_tool()
該函數必須在其他所有函數調用之前被調用,在C中的聲明為:int load_tool(int nr,char* device,char* adr_table);由于C#在安全模式下不容許使用指針,因此我們把它轉換成C#模式:
private extern static int load_tool(byte nr,string device,byte[,] adr_table);
參數 nr: 指定連接號1-4,一般設為1
device: 設備名稱,西門子的示例是設為"s7online",測試時,若改成其他名稱好像連不上。
adr_table: 一個二維數組,指定一系列連接參數,依次為:MPI地址、保留為0、CPU槽號、CPU機架號。在一個MPI網絡中若有多個CPU時,可指定一個以上的連接列。最后一列的參數的MPI地址應制定為0,以標志參數列結束。 e.g.一個MPI網中有兩個CPU,他們的MPI地址分別為2和3,槽號均為2,機架號均為0,則可按如下方式調用: byte[,]
bt={{2,0,2,0},{3,0,2,0},{0,0,0,0}};
int err=load_tool(1, "s7online",bt);
注:ProDave中的所有庫函數均返回整數數據,為0表示調用該函數成功,為其他十進制數時,可以查找西門子文檔,看是什么錯誤。
可以看出,上面的函數不利于我們使用,我們可對他進行封裝:
<1>、在類之前聲明用于傳遞參數列表的結構:
#region 定義與外部聯系的結構變量
///
/// 定義MPI鏈接參數
///
public struct ConnectionInfo{
///
/// 定義CPU的MPI地址
///
public byte Addres;
///
/// 定義CPU的機架號
///
public byte Rack;
///
/// 定義CPU的槽號
///
public byte Slot;
}
#endregion
<2>、編寫實現上述功能的公有方法:
#region 與動態庫函數相對應的公開函數
///
/// 建立連接,同一個連接只容許調用一次
///
/// 連接號1-4
/// 指定鏈接參數
/// 返回10進制錯誤號,0表示沒有錯誤
public static int Open(byte cnnNo,ConnectionInfo[] cnnInfo){ int err;
//傳遞參數不正確
if(cnnInfo.Length<=0){
return -1;
}
byte[,] btr=new byte[cnnInfo.Length+1,4];
//轉換鏈接表
for(int i=0;i<CNNINFO.LENGTH;I++){
btr[i,0]=cnnInfo[i].Addres;
btr[i,1]=0;
btr[i,2]=cnnInfo[i].Slot;
btr[i,3]=cnnInfo[i].Rack;
}
btr[cnnInfo.Length,0]=0;
btr[cnnInfo.Length,1]=0;
btr[cnnInfo.Length,2]=0;
btr[cnnInfo.Length,3]=0;
//調用初始化函數
err=load_tool(cnnNo,"s7online",btr);
return err;
}
#endregion
這樣,我們需要打開連接時,可以使用如下方式:
ConnectionInfo[] cnn=new ConnectionInfo[2];
Cnn[0] .Addres=2;
Cnn[0].Slot=2;
Cnn[0].Rack=0;
Cnn[1] .Addres=3;
Cnn[1].Slot=2;
Cnn[1].Rack=0;
int err=Open(1,Cnn);
2、 斷開連接的unload_tool()函數
該函數與load_tool()正好相反,用于斷開與PLC的連接,一般在退出組態軟件之前調用,該函數沒有參數,C#聲明方式如下:
private extern static int unload_tool();
3、 激活某一個連接的函數new_ss()
該函數用于設定與MPI網中的哪一個CPU通訊,其參數與load_tool中的參數adr_table所傳遞的連接參數順序對應,譬如針對上例:new_ss(1)則激活第一個連接,即與MPI地址為2的PLC通訊,類似的new_ss(2)則激活與MPI地址為3的PLC通訊。若激活的連接在MPI網中沒有,則返回錯誤號517。 C#聲明方式如下:
private extern static int new_ss(byte no);
4、 讀取PLC中的M字節的函數在C#中聲明方式如下:
private extern static int m_field_read (short no,short anzahl,ref long buffer);
參數 no : 指定M字節號,譬如要讀取MB10的值,則指定no等于10
Anzahl :指定讀取的字節數,譬如需要讀取MB10至MB14之間的值,則可指定為5
Buffer : 返回獲取的值,這是一個十進制的值,如果需要獲取某一個M位的狀態,需要把它轉換成二進制,后面有介紹。
5、 向PLC中的M字節寫入值在C#中聲明方式如下:
private extern static int m_field_write(short no,short anzahl,ref
long buffer);
參數 no和anzahl與m_field_read的一樣,而buffer指定的是向PLC中寫入的值。
例如:向MB15中寫入值3,即將m15.0和m15.1強制為1,可調用函數如下: int err= m_field_write(15,1,3);
三、 ProDave中的其他一些函數的C#聲明方式如下:
///
/// 讀取Output值
///
/// 指定QB號
/// 指定有多少個QB字節需要讀出
/// 返回讀出的值
///
[DllImport("w95_s7.dll")]
private extern static int a_field_read (int no,int anzahl,ref long buffer);
///
/// 向Output寫入值
///
/// 指定QB號
/// 指定有多少個QB字節需要寫入
/// 指定寫入值
///
[DllImport("w95_s7.dll")]
private extern static int a_field_write (int no,int anzahl,ref long buffer);
///
/// 獲取PLC的運行狀態
///
/// 返回0或者1,0表示Run;1表示Stop或者Restart
///
[DllImport("w95_s7.dll")]
private extern static int ag_zustand (ref byte buffer);
///
/// 測試指定的DB塊是否存在
///
/// 返回一系列塊的存在狀態,=0不存在,!=0存在
///
[DllImport("w95_s7.dll")]
private extern static int db_buch (ushort[] buffer);
///
/// 從DB中讀取數據
///
/// 指定DB塊號
/// 指定讀取的起始字序號,=0表示DBW0,=1表示DBW2
/// 指定讀取的對象有多少個字
/// 返回值
///
[DllImport("w95_s7.dll")]
private extern static int db_read(int dbno, int dwno, ref int anzahl, ref long buffer);
///
/// 向DB中寫入數據
///
/// 指定DB塊號
/// 指定寫入的起始字序號,=0表示DBW0,=1表示DBW2
/// 指定寫入的對象有多少個字
/// 寫入值
///
[DllImport("w95_s7.dll")]
private extern static int db_write(int dbno, int dwno, ref int anzahl, ref long buffer);
///
/// 讀取Input的值
///
/// 指定IB號
/// 指定有多少個IB字節需要讀出
/// 讀取返回的值
///
[DllImport("w95_s7.dll")]
private extern static int e_field_read (int no,int anzahl,ref long buffer);
///
/// 獲取MB變量的位狀態值
///
/// 指定M字節號
/// 指定位號,范圍為0-7
/// 返回值,>0表示該位為1,=0表示該位為0
///
[DllImport("w95_s7.dll")]
private extern static int mb_bittest(short mbno,short bitno,ref short retwert);
///
/// 復位MB變量的位狀態
///
|