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