西門子Prodave6.0在C#中地應(yīng)用_第1頁
西門子Prodave6.0在C#中地應(yīng)用_第2頁
西門子Prodave6.0在C#中地應(yīng)用_第3頁
西門子Prodave6.0在C#中地應(yīng)用_第4頁
西門子Prodave6.0在C#中地應(yīng)用_第5頁
已閱讀5頁,還剩10頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、實用文案實用文案標(biāo)準(zhǔn)文檔標(biāo)準(zhǔn)文檔最近在做一個數(shù)據(jù)采集項目,涉及到許多與西門子S7系列PLC的通信,由于自己的 VC水平屬于半瓶子晃蕩,所以就想利用 C#來進(jìn)行開發(fā)(個人比較喜歡 C#的代碼風(fēng)格,看著很清爽),雖然 C#這種高 級語言與底層的設(shè)備通訊效率確實不如 C+ ,但好在數(shù)據(jù)量不大,實時性要求不算太高,用 C#還是可以 應(yīng)付的。在界面開發(fā)方面,高級語言確實不如WinCC , Intouch之類的組態(tài)軟件,但在數(shù)據(jù)處理上面,卻有很大的靈活性。在這里很感謝吳向陽,在中國工控網(wǎng)上面發(fā)現(xiàn)了他的文章,因為我是從 C#轉(zhuǎn)到工控方向的,以前對 PLC一點都不懂,剛接觸這一行時,學(xué)習(xí)起來很吃力,看了他的這

2、篇文章,讓我對PLC的有了更加深入的了解。我的這個DCProdave.cs 就是在他的基礎(chǔ)上修改的,加了一些自己的東西。還望各位多多提意見,多多交 流!Prodave 版本:PRODAVE6.0 - W95_S7.DLLPLC 模擬環(huán)境:PLCSIM V5.4開發(fā)環(huán)境:VS.NET 2005.從w95_s7.dll中導(dǎo)入PLC通訊函數(shù)的方法DllImport在使用 DllImport 之前,必須弓I入 InteropServices, 代碼如下:using System.Runtime.InteropServices;具體使用方法可以參考我的博客中轉(zhuǎn)載的一篇文章C#(.net)中的DllImp

3、ort用法轉(zhuǎn)寫的很不錯,千萬要注意C+數(shù)據(jù)類型到C#的對應(yīng)關(guān)系,選用合適的類型。比如 char*可以用string來轉(zhuǎn)換,指針類型 可以ref或者數(shù)組。.定義結(jié)構(gòu)體類型2.1 PLC連接參數(shù)結(jié)構(gòu)體/定義結(jié)構(gòu)體連接PLC所需參數(shù)public struct PLCConnParampublic byte Addres;/ 定義 CPU 的 MPI/DP 地址/publicbyte SegmentId;/ 保留為0publicbyte Rack;定義 CPU的機架號publicbyte Slot;定義 CPU的槽號.2 PLC存儲區(qū)域類別編號/定義枚舉類型PLC的存儲區(qū)域編號public enum

4、PLCBlockType3三I = 1, /Input bytesQ =2, /Output bytesM =3, /Flag bytesT =4, /Timer wordsZ =5, /Counter wordsD =6, /Data from DB三.常用函數(shù)詳細(xì)講解3.1建立PLC連接函數(shù)首先從W95_S7.DLL中導(dǎo)入連接函數(shù),訪問權(quán)限為私有,C#將會對此函數(shù)進(jìn)行封裝,供外部調(diào)用,稍后講解./summary 與PLC建立連接,該函數(shù)必須在其他所有函數(shù)調(diào)用之前被調(diào)用/ /summary/ 連接數(shù),在DOS,WIN3.1 最多可以有 4個在 WIN95 以上最多可以有 16個/ 與 PLC

5、 通訊的設(shè)備名稱,一般為 S7ONLINE / 參數(shù)列表,4個值分別為 MPI/DP 地址保留值=0,槽號 機架號/ 0正常返回,非0為錯誤號DllImport( w95_s7.dll)private extern static int load_tool( byte nr, string device, byte , adr_table);說明:在一個MPI/DP網(wǎng)絡(luò)中若有多個PLC時,可指定多個連接列。最后一列的所有參數(shù)須置0,以標(biāo)志參數(shù)列結(jié)束。例如一個MPI/DP網(wǎng)中有兩個PLC,他們的MPI地址分別為2和3,槽號均為2,機架號均為0, 則可按如下方式調(diào)用:byte, ba=2,0,2,

6、0,3,0,2,0,0,0,0,0; int err=load_tool(1, s7online,ba); 返 回值為int型,如果返回0則表示執(zhí)行成功,非零值,則需要根據(jù)錯誤號查找到錯誤具體信息,具體參照本文第五部分:錯誤代碼字典當(dāng)然如果PLC使用的是DP網(wǎng)絡(luò)時,只需要將Set PG/PC Interface中接口參數(shù)分配選為PLCSIM(PROFIBUS)即可,Prodave不需要做任何修改(當(dāng)然PLC地址肯定也是 DP 口的地址哦),具體如下 圖:個人不太習(xí)慣西門子的這種函數(shù)命名,索性就按照C#的常用習(xí)慣,進(jìn)行一下簡單的封裝,供外部調(diào)用/ 建立連接,同一個連接只容許調(diào)用一次/ / 連接號

7、 connNo 為 1-4/ 連接參數(shù),PLCConnParam 定義的參數(shù)結(jié)構(gòu)體 / 返回10進(jìn)制錯誤號,0表示沒有錯誤 public static int Open( byte connNo, PLCConnParam口 connParam)7三int PLCCPUCnt = connParam.Length;if (PLCCPUCnt =0) /傳遞參數(shù)不正確10中11 return -1;12卜byte , btr = new byte PLCCPUCnt + 1, 4; 多分配1個用于存放0作為連接結(jié)束標(biāo)記/轉(zhuǎn)換連接表for (int i = 0; i connParam.Lengt

8、h; i+)16中btri,0= connParami.Addres; TOC o 1-5 h z btri,1= 0;btri,2= connParami.Slot;btri,3= connParami.Rack;btrconnParam.Length,0=0;btrconnParam.Length,1=0;btrconnParam.Length,2=0;btrconnParam.Length,3=0;/調(diào)用初始化函數(shù),打開連接int errCode = load_tool(connNo,S7ONLINE , btr);return errCode;L 29 建立于PLC的連接,只需在數(shù)采程

9、序啟動的時候調(diào)用即可,并且只能打開一次,否則報錯.驅(qū)動設(shè)備名稱S7ONLINE, 一般情況下是不會有變化的,所以這里就寫死了 .特別需要指出的是,這個函數(shù)的第一個參數(shù)(連 接號),是指當(dāng)前連接有多少個PLC連接(嚴(yán)格意義上來講,是CPU的個數(shù),因為有可能2個PLC共用1個CPU,之間通過IM467組態(tài)),激活連接并交換數(shù)據(jù)的時候,和這個值有點關(guān)系.在建立連接的時候默認(rèn)激活第1個連接.2斷開與PLC的連接從W95_S7.DLL中導(dǎo)入函數(shù),依然是私有,因為我要對所有的導(dǎo)入函數(shù)進(jìn)行封裝./ 斷開與PLC的連接,必須退出數(shù)采軟件之前調(diào)用,否則PLC的連接一直被占用,影響下次連接/ / 0正常返回,非0

10、為錯誤號DllImport( w95_s7.dll)private extern static int unload_tool();關(guān)閉PLC的連接函數(shù)進(jìn)行 C#封裝,沒有改變?nèi)魏未a,只是換了個函數(shù)名.public static int Close()%return unload_tool();3.3激活連接,當(dāng)前連接列中某個時刻有且只有1個PLC是激活狀態(tài).建立連接的時候,默認(rèn)激活第1個連接./summary 激活與MPI網(wǎng)中的哪個 CPU通訊,load_tool后默認(rèn)激活第一個 CPU連接/summary/param name=no 連接號,對應(yīng)于參數(shù) adr_table 所傳遞的連接參

11、數(shù)順序 /returns0正常返回,非0為錯誤號,若激活的連接在 MPI網(wǎng)中沒有,則返回錯誤號517/returnsDllImport( w95_s7.dll)private extern static int new_ss( byte no);其參數(shù)與load_tool中參數(shù)adr_table所傳遞的連接參數(shù)順序?qū)?yīng)譬如byte, btr=2,0,2,0,3,020,0,0,0,0 , new_ss(1) 則激活第1個連接即與 MPI地址為2的PLC通訊,類似的new_ss(2)則激活與MPI地址為3的PLC通訊在數(shù)采系統(tǒng)中,為了讀取所有PLC的數(shù)據(jù),采用定時循環(huán)激活每個PLC的連接,然后讀

12、取其數(shù)據(jù).C#封裝如下:1 public static int ActiveConn( int connNO)2日return new_ss( byte )connNO);3.4從DB塊中讀取字節(jié)數(shù)據(jù)(返回BYTE數(shù)組)1日/ 從DB中讀取BYTE數(shù)組(字節(jié)數(shù)可以是任意長度的)/ / DB 塊號 / DBB 起始編號,0 表示 DBB0,1 表示 DBB1,跨度為 BYTE/ 讀取的BYTE長度(任意長度,可以為奇數(shù))/ 返回值,BYTE 型 buffer / 0正常返回,非0為錯誤號DllImport( w95_s7.dll)private extern static int d_field

13、_read( int blockno, int no, int amount, byte buffer);C#封裝如下:/ 讀取 DB 塊的 BYTE 數(shù)據(jù)/ / DB 塊號,如:DB2 / DB數(shù)據(jù)的起始字節(jié),如DBB2則從2開始讀/ 要讀取的字節(jié)數(shù),如從 DBB2-DBB5,共 4 個字節(jié) / BYTE 型緩存區(qū),存儲讀取的數(shù)據(jù) / 數(shù)據(jù)緩存區(qū)的起始位置 / 返回值0:成功非0:錯誤代碼public static int GetDBByteData( int DBBlockNO, int DBBNO, int DBByteAmount, byte buffe r, int StartInd

14、ex)10日byte bBufTemp = new byte DBByteAmount;int errCode=d_field_read(DBBlockNO, DBBNO, DBByteAmount, bBufTemp);for (int i= 0;iDBByteAmount;i+)14中15 bufferi+StartIndex = bBufTempi;16卜return errCode;這個函數(shù)是用的最多的一個函數(shù),在數(shù)采系統(tǒng)中,習(xí)慣一次性的將所有需要用到數(shù)據(jù),全部讀到字節(jié)數(shù)組 中,統(tǒng)一處理,避免不同時期凌亂讀取造成的數(shù)據(jù)不一致.需要提醒的是,必須保證數(shù)據(jù)處理函數(shù)得到的數(shù)據(jù)是PLC 一次掃

15、描周期內(nèi)的5從DB中讀取整數(shù)值(int32型)1日/ 從DB中讀取INT數(shù)據(jù)(DBW:INT16 或者DBD:INT32),最多4個字節(jié)的整數(shù)/ /DB 塊號 /DBW 起始編號,0 表示 DBW0,1 表示DBW2,跨度為WORD/讀取的 WORD 長度(1 個 WORD=2個BYTE) 2:DBW ,4:DBD/返回值,int 型整數(shù)(十進(jìn)制)/ 0正常返回,非0為錯誤號DllImport( w95_s7.dll)private extern static int db_read( int dbno, int dwno, ref int anzahl, ref int buffer); C

16、#封裝/ 從DB塊中讀取整型數(shù)據(jù)/要讀取 DB2.DBW6,則DB塊號為2,DBB號為6,字節(jié)長度為 2/要讀取DB2.DBD6,則DB塊號為2,DBB號為6,字節(jié)長度為 4/ / DB 塊號,如:DB2 / DBB的起始字節(jié)號,如DBW2則從2開始讀,由于是 WORD(2 個BYT E),DBB號必須為偶數(shù)/ vparam name=DBByteAmount”要讀取的BYTE數(shù),必須是偶數(shù)(這里只能是 2和4,在PLC中只有DBW,DBD兩種整數(shù))/ vparam name=buffer INT32型緩存區(qū),存儲讀取的十進(jìn)制數(shù)據(jù) L_一 /returns返回值0:成功非0:錯妖代碼/retu

17、rnspublic static int GetDBInt32Data( int DBBlockNO, int DBBNO, int DBByteAmount, ref int buffer)11日int DBWNO = DBBNO /2;int DBWordAmount = DBByteAmount /2;int errCode = db_read(DBBlockNO, DBWNO, ref DBWordAmount, ref buffer);byte bbuf = new byte 4;GetByteFromInt32(buffer, bbuf,true);buffer = bbuf 0

18、* 0 x1000000 + bbuf 1 * 0 x10000 + bbuf 2 * 0 x100 + bbuf 3;return errCode;這個函數(shù)讀取的是一個整數(shù),因為DB中有DBB,DBW,DBD3 種數(shù)據(jù)類型,最大的DBD是4個字節(jié),所以設(shè)計 了這個函數(shù),讀取單個的整型值,不用再進(jìn)行BYTE口到INT的轉(zhuǎn)換了 .這里值得一提的是整數(shù)高位優(yōu)先,還是低 位優(yōu)先的問題,字節(jié)數(shù)組的順序切記要矯正,另外buffer = bbuf 0 * 0 x1000000 + bbuf 1 * 0 x10000 + bbuf 2 * 0 x100 + bbuf 3;這行代碼很有意 思,16進(jìn)制的字節(jié)進(jìn)

19、位是 0 x100.3.6 M,I,Q 3種塊的讀取函數(shù)類似(參數(shù)都是一樣的),這里放在一起進(jìn)行說明M區(qū)讀取函數(shù)/summary 讀取PLC中的M 字節(jié)數(shù)據(jù)/summary/param name=no 指定 M字節(jié)號,譬如要讀取 MB10的值,則指定 no等于10/param name=anzahl”指定讀取的字節(jié)數(shù),譬如需要讀取MB10 至MB14 之間的值,則可指定為 5/ 返回獲取的值,這是一個十進(jìn)制的值,如果需要獲取某一個 M位的狀態(tài), 需要把它轉(zhuǎn)換成二進(jìn)制 / 0正常返回,非0為錯誤號DllImport( w95_s7.dll)private extern static int m_

20、field_read( int no, int anzahl, byte buffer);I區(qū)讀取函數(shù),一直不明白為什么輸入?yún)^(qū)(單詞input)簡稱為I,而函數(shù)名卻為A,后來才曉得,這個A是德文的 表示方法,(Pordave是西門子公司的東東).日/ 讀取 Output 值/ / QB #/ 讀出多少個 QB 字節(jié) / 返回讀出的值 ,十進(jìn)制 / 0正常返回,非0為錯誤號DllImport( w95_s7.dll)private extern static int a_field_read( int no, int anzahl, byte buffer);Q區(qū)讀取函數(shù),參數(shù)與I 一樣.Dll

21、Import( w95_s7.dll)private extern static int e_field_read( int no, int anzahl, byte buffer);C#封裝,M,I,Q 3種塊的讀取函數(shù)類似,這里放在一個函數(shù)里,利用枚舉類型PLCBlockType進(jìn)行區(qū)分/ 從M,I,Q區(qū)中讀取字節(jié)數(shù)組/ / Block 類別,在枚舉 PLCBlockType 中定義,如要讀取 M 區(qū)的值,則 b lockType=PLCBlockType.M / 區(qū)號,如 IB10,MB10 , / 要讀取的字節(jié)數(shù)量,如 IB10-IB14 共 5 個字節(jié) / byte口 類型的 buf

22、fer / byte口 存儲的起始位置 / 0正常返回,非0為錯誤號public static int GetMIQByteData(PLCBlockType blockType, int BlockNO, int ByteAmount, by te bbuf, int StartIndex)10之int errCode =0;byte bBufTemp = new byte ByteAmount;局部變量,不用擔(dān)心內(nèi)存釋放的問題 .C+程序員看到new估計很謹(jǐn)慎.switch (blockType) 根據(jù)塊類別,調(diào)用相應(yīng)的塊讀取函數(shù).3 case PLCBlockType.M: errCod

23、e = m_field_read(BlockNO, ByteAmount, bBufTemp);break;case PLCBlockType.I : errCode = e_field_read(BlockNO, ByteAmount, bBufTemp);break ;case PLCBlockType.Q: errCode = a_field_read(BlockNO, ByteAmount, bBufTemp);breakfor (int i = 0; i ByteAmount; i+) 由于C#中對指針有所限制,從數(shù)組指定的起始位置,逐個賦 值.3 bbufi + Startinde

24、x = bBufTempi;四,BYTE,INT,BOOL幾種類型的數(shù)據(jù)轉(zhuǎn)換函數(shù)4.1從32位整數(shù)中提取字節(jié)數(shù)組(4個byte)/ 從INT32型數(shù)據(jù)中提取byte字節(jié)數(shù)組/ / 源數(shù)據(jù)(long 型)/ 字節(jié)數(shù)組,存放提取的 Byte 數(shù)據(jù) / 起始位置 / 提取的字節(jié)數(shù) / long型源數(shù)據(jù)是否高位優(yōu)先,如果不是,則進(jìn)行反向提取public static void GetByteFromInt32( int ibuf, byte bbuf , bool isBigEndian)9三if (isBigEndian) /高位優(yōu)先,則反向提取. TOC o 1-5 h z for (int i

25、= 0; i =8; / 右移 8 位17卜18 else 低位優(yōu)先,按順序提取.19目20 for (int i =3; i = 0; i-)21中22bbufi = ( byte )(ibuf & 0 x000000ff );23ibuf =8;24卜 4.2從字節(jié)數(shù)據(jù)中提取 bit數(shù)組(8個bit),以bool型數(shù)據(jù)代替位表示./ 從 Byte 數(shù)據(jù)中取得所有 bit 的值(1Byte=8Bit , false:0 , true:1)/ / 源數(shù)據(jù)(Byte 型),其中的 8 個 bit 位,從右到左 0-7 編# / bit 數(shù)組,存放 Byte 中的 8 個 bit 的值,0:fal

26、se, 1:true / 在 bit 數(shù)組中存放的起始位置 public static void GetBitFromByte( byte byteData, bool 口 bitArray, int startIndex)7三byte byteArray = new byte 1 ;byteArray 0 = byteData;System.Collections.BitArray BA = new System.Collections.BitArray(byteArray);for (int i = 0; i = 7; i+) /依次取8個位,逐個賦值12中bitArraystartInd

27、ex + i = BA.Get(i);4.3從字節(jié)數(shù)據(jù)中提取某一位的狀態(tài),以bool型返回/ 從 Byte 數(shù)據(jù)中取得某一位 bit 的值(false:0 , true:1)/ / 源數(shù)據(jù)(Byte 型),其中的 8 個 bit 位,從右到左 0-7 編# / bit 位編號,從右到左以 0-7 編號 / bit 值,以 bool 型返回,false:0 , true:1 public static void GetBitFromByte( byte byteData, int bitNo, ref bool bitData)7Hl if (bitNo =0 & bitNo =7) / 位號必須在 07 之間byte byteArray = new byte 1 ;byteArray 0 = byteData;System.Collections.BitArrayBA = new System.Collections.BitArray(byteArray);bitData = BA.Get(bitNo);五.錯誤代碼字典/ 根據(jù)錯誤代碼返回錯誤信息/ 例如 int errCode=ActiveConn(1); sring errInfo = GetErrl

溫馨提示

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

評論

0/150

提交評論