狠狠色丁香久久综合婷婷亚洲成人福利在线-欧美日韩在线观看免费-国产99久久久久久免费看-国产欧美在线一区二区三区-欧美精品一区二区三区免费观看-国内精品99亚洲免费高清

            產(chǎn)品展廳收藏該商鋪

            您好 登錄 注冊(cè)

            當(dāng)前位置:
            上海翰粵自動(dòng)化系統(tǒng)有限公司>技術(shù)文章>運(yùn)用VC#編程通過(guò)OPC方式實(shí)現(xiàn)PC機(jī)與西門子PLC通訊

            技術(shù)文章

            運(yùn)用VC#編程通過(guò)OPC方式實(shí)現(xiàn)PC機(jī)與西門子PLC通訊

            閱讀:1578          發(fā)布時(shí)間:2016-1-6

            運(yùn)用VC#編程通過(guò)OPC方式實(shí)現(xiàn)PC機(jī)與西門子PLC通訊

            1、 配置OPC服務(wù)器
              對(duì)于服務(wù)器的配置與同步通訊的配置一樣,這里不需再講解,若有不清楚的,可以參閱之前發(fā)布的<運(yùn)用VC#編程通過(guò)OPC方式實(shí)現(xiàn)PC機(jī)與西門子PLC通訊>

            2、 OPC編程
              變量組、項(xiàng)的命名規(guī)則與同步通訊的一樣,這里不再描敘,下面主要就開(kāi)發(fā)一個(gè)異步通訊類 AsynServer來(lái)講解如何編程。

            <1>、引用
              在VC#開(kāi)發(fā)環(huán)境中添加對(duì)OpcRcw.Da庫(kù)以及OpcRcw.Comn庫(kù)的引用,該庫(kù)屬于.NET庫(kù),不屬于COM庫(kù),西門子雖然編寫了類庫(kù),以提供對(duì).NET平臺(tái)的支持,但這些類庫(kù)仍然難于編程,里面包含了大量的在托管和非托管區(qū)傳輸數(shù)據(jù),因此我們需要在它的基礎(chǔ)上再開(kāi)發(fā)一個(gè)類庫(kù),以簡(jiǎn)化以后的編程,首先在類的開(kāi)頭使用命名空間:
            using OpcRcw.Comn;
            using OpcRcw.Da;
            using System.Runtime.InteropServices;
            using System.Collections;

            <2>、編程
              異步編程的原理就是在OPC服務(wù)器那邊檢測(cè)當(dāng)前活動(dòng)的變量組,一但檢測(cè)到某一個(gè)變量,譬如變量Q0.0從1變成0,就會(huì)執(zhí)行一個(gè)回調(diào)函數(shù),以實(shí)現(xiàn)針對(duì)變量發(fā)生變化時(shí)需要實(shí)現(xiàn)的動(dòng)作,在這里可以采用委托來(lái)實(shí)現(xiàn)該功能。

              1、 在命名空間的內(nèi)部、類 AsynServer聲明之前添加委托的申明:
            // 定義用于返回發(fā)生變化的項(xiàng)的值和其對(duì)應(yīng)的客戶句柄
            public delegate void DataChange(object[] values,int[] itemsID);

              2、 該類繼承于西門子提供的庫(kù)接口IOPCDataCallback
            public class AsynServer:IOPCDataCallback
            在類的開(kāi)頭部分聲明變量:
            struct groupStru
            {
            public int groupID;
            public object groupObj;
            }
            internal const int LOCALE_ID = 0x407; //本地語(yǔ)言
            private Guid iidRequiredInterface;
            private string serverType="";
            private int hClientGroup = 0; //客戶組號(hào)
            private int nSvrGroupID; // server group handle for the added group 
            private Hashtable hashGroup; //用于把組收集到一起
            private int hClientItem=0; //Item號(hào)

               3、編寫構(gòu)造函數(shù),接收委托參數(shù)已確定當(dāng)數(shù)據(jù)發(fā)生變化時(shí)需要執(zhí)行的方法入口點(diǎn):
            //創(chuàng)建服務(wù)器
            //svrType 服務(wù)器類型的枚舉
            //dataChange 提供用于在數(shù)據(jù)發(fā)生變化時(shí)需要執(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)建一個(gè)OPC Server接口
            //error 返回錯(cuò)誤信息
            //若為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="錯(cuò)誤信息:"+err.Message;success=false;
            }
            return success;
            }

              5、 編寫添加Group的函數(shù)
            ///


            /// 添加組
            /// 
            /// 組名
            /// /創(chuàng)建時(shí),組是否被激活
            /// //組的刷新頻率,以ms為單位
            /// 返回錯(cuò)誤信息
            /// 若為true,添加成功,否則添加失敗
            public bool AddGroup(string groupName,int bActive,int updateRate,out string error)

            error="";bool success=true;
            int dwLCID = 0x407; //本地語(yǔ)言為英語(yǔ) 
            int pRevUpdateRate;
            float deadband = 0;
            // 處理非托管COM內(nèi)存
            GCHandle hDeadband;
            IntPtr pTimeBias = IntPtr.Zero;
            hDeadband = GCHandle.Alloc(deadband,GCHandleType.Pinned);
            try
            {
            pIOPCServer.AddGroup(groupName, //組名
            bActive, //創(chuàng)建時(shí),組是否被激活
            updateRate, //組的刷新頻率,以ms為單位
            hClientGroup, //客戶號(hào)
            pTimeBias, //這里不使用
            (IntPtr)hDeadband,
            dwLCID, //本地語(yǔ)言
            out nSvrGroupID, //移去組時(shí),用到的組ID號(hào)
            out pRevUpdateRate, //返回組中的變量改變時(shí)的zui短通知時(shí)間間隔
            ref iidRequiredInterface,
            out pobjGroup1); //指向要求的接口
            hClientGroup=hClientGroup+1; 
            groupStru grp=new groupStru();
            grp.groupID=nSvrGroupID;grp.groupObj=pobjGroup1;
            this.hashGroup.Add(groupName,grp);//儲(chǔ)存組信息
            // 對(duì)異步操作設(shè)置回調(diào),初始化接口
            pIConnectionPointContainer = (IConnectionPointContainer)pobjGroup1;
            Guid iid = typeof(IOPCDataCallback).GUID;
            pIConnectionPointContainer.FindConnectionPoint(ref iid,out pIConnectionPoint);
            pIConnectionPoint.Advise(this,out dwCookie);
            }
            catch (System.Exception err) //捕捉失敗信息
            {
            error="錯(cuò)誤信息:"+err.Message;success=false;
            }
            finally
            {
            if (hDeadband.IsAllocated) hDeadband.Free();
            }
            return success;
            }

              6、 編寫激活、或者取消激活組的函數(shù)

              在同步編程中對(duì)于組的激活或者取消激活沒(méi)有實(shí)質(zhì)的意義,但在異步通訊編程中卻異常重要,這是因?yàn)镺PC服務(wù)器只對(duì)當(dāng)前處于活動(dòng)狀態(tài)的組中的變量進(jìn)行監(jiān)控,同時(shí)這也是很有必要的,因?yàn)槲覀兛梢园巡煌缑嬷械淖兞烤幊滩煌慕M,即同一界面中的變量規(guī)成一個(gè)組,而在某一時(shí)刻提供給用戶的只有一個(gè)界面,讓該界面中用到的組處于活動(dòng)狀態(tài),這樣執(zhí)行委托調(diào)用時(shí)只會(huì)執(zhí)行于該界面中有關(guān)的變量檢測(cè),而如果讓所有的組處于活動(dòng)狀態(tài),則當(dāng)前沒(méi)有顯示給用戶的界面用到的變量若發(fā)生變化也會(huì)觸發(fā)對(duì)委托函數(shù)的調(diào)用,這根本是沒(méi)有必要的,同時(shí)會(huì)大大降低程序的性能,請(qǐng)嚴(yán)格控制組的激活。
            ///
            /// 激活或者取消激活組
            /// 
            /// 組名
            /// true為激活,false為取消激活
            /// 若有錯(cuò)誤,返回錯(cuò)誤信息
            /// 若為true,添加成功,否則添加失敗
            public bool AciveGroup(string groupName,bool toActive,out string error)
            {
            error="";bool success=true;
            //通過(guò)名稱獲取組
            object grp=((groupStru)hashGroup[groupName]).groupObj;
            IOPCGroupStateMgt groupStateMgt=(IOPCGroupStateMgt)grp;
            //初始化傳遞參數(shù)
            IntPtr pRequestedUpdateRate = IntPtr.Zero; //由客戶的Item更新間隔時(shí)間
            int nRevUpdateRate = 0; //由服務(wù)器返回的能夠更新的zui短時(shí)間間隔
            IntPtr hClientGroup = IntPtr.Zero; //客戶組
            IntPtr pTimeBias = IntPtr.Zero;
            IntPtr pDeadband = IntPtr.Zero;
            IntPtr pLCID = IntPtr.Zero; 

            // 激活或者取消激活組
            int nActive = 0; 
            GCHandle hActive = GCHandle.Alloc(nActive,GCHandleType.Pinned);
            if(toActive)
            hActive.Target = 1;
            else
            hActive.Target = 0;
            try 
            {
            groupStateMgt.SetState(pRequestedUpdateRate,out nRevUpdateRate,hActive.AddrOfPinnedObject(),pTimeBias,pDeadband,pLCID,hClientGroup); 
            }
            catch(System.Exception err)
            {
            error="錯(cuò)誤信息:"+err.Message;success=false;
            }
            finally
            {
            hActive.Free(); 
            }
            return success;
            }

            7、 向的組中添加變量的函數(shù)
            ///
            /// 向的組添加一系列項(xiàng)
            /// 
            /// 組名
            /// 完整的item名數(shù)組
            /// 由服務(wù)器返回讀寫數(shù)據(jù)時(shí)需要使用的item號(hào)
            /// 無(wú)錯(cuò)誤,返回true,否則返回false
            public bool AddItems(string groupName,string[] iteame,int[] itemsID)
            {
            bool success=true;
            OPCITEMDEF[] ItemDefArray=new OPCITEMDEF[iteame.Length];
            for(int i=0;i {
            hClientItem=hClientItem+1; //客戶項(xiàng)自動(dòng)加1
            ItemDefArray[i].szAccessPath = ""; // 可選的通道路徑,對(duì)于Simatiic Net不需要。
            ItemDefArray[i].szItemID = iteame[i]; // ItemID, see above
            ItemDefArray[i].bActive = 1; // item is active
            ItemDefArray[i].hClient = hClientItem; // client handle ,在OnDataChange中會(huì)用到
            ItemDefArray[i].dwBlobSize = 0; // blob size
            ItemDefArray[i].pBlob = IntPtr.Zero; // pointer to blob 
            ItemDefArray[i].vtRequestedDataType = 4; //DWord數(shù)據(jù)類型
            }
            //初始化輸出參數(shù)
            IntPtr pResults = IntPtr.Zero;
            IntPtr pErrors = IntPtr.Zero;
            try 
            {
            // 添加項(xiàng)到組
            object grp=((groupStru)hashGroup[groupName]).groupObj;
            ((IOPCItemMgt)grp).AddItems(iteame.Length,ItemDefArray,out pResults,out pErrors);

            int[] errors = new int[iteame.Length]; 
            IntPtr pos = pResults;
            Marshal.Copy(pErrors, errors, 0,iteame.Length);
            for(int i=0;i {
            if (errors[i] == 0)
            {
            OPCITEMRESULT result = (OPCITEMRESULT)Marshal.PtrToStructure(pos, typeof(OPCITEMRESULT));
            itemsID[i] = result.hServer; 
            pos = new IntPtr(pos.ToInt32() + Marshal.SizeOf(typeof(OPCITEMRESULT)));
            }
            else
            {
            String pstrError;
            pIOPCServer.GetErrorString(errors[0],0x407,out pstrError); 
            success=false;
            break;
            }
            }
            SetItenClient(groupName,itemsID,itemsID); //要求始終只有一個(gè)組被激活,才不會(huì)引起沖突。
            }
            catch (System.Exception err) // catch for error in adding items.
            {
            success=false;
            //error="錯(cuò)誤信息:"+error+err.Message;
            }
            finally
            {
            // 釋放非托管內(nèi)存
            if(pResults != IntPtr.Zero)
            {
            Marshal.FreeCoTaskMem(pResults);
            pResults = IntPtr.Zero;
            }
            if(pErrors != IntPtr.Zero)
            {
            Marshal.FreeCoTaskMem(pErrors);
            pErrors = IntPtr.Zero; 
            }
            }
            return success;
            }

            收藏該商鋪

            請(qǐng) 登錄 后再收藏

            提示

            您的留言已提交成功!我們將在第一時(shí)間回復(fù)您~

            對(duì)比框

            產(chǎn)品對(duì)比 產(chǎn)品對(duì)比 聯(lián)系電話 二維碼 在線交流

            掃一掃訪問(wèn)手機(jī)商鋪
            021-60531200
            在線留言