<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          關(guān) 閉

          新聞中心

          EEPW首頁(yè) > 工控自動(dòng)化 > 設(shè)計(jì)應(yīng)用 > 基于C++Builder API函數(shù)的歐姆龍PLC串行通信

          基于C++Builder API函數(shù)的歐姆龍PLC串行通信

          作者: 時(shí)間:2016-10-10 來(lái)源:網(wǎng)絡(luò) 收藏

          1 引言

          本文引用地址:http://www.ex-cimer.com/article/201610/306696.htm

          計(jì)算機(jī)串行通信是計(jì)算機(jī)與控制設(shè)備(plc)進(jìn)行數(shù)據(jù)傳送的基本通信方式,也是實(shí)現(xiàn)工業(yè)自動(dòng)控制經(jīng)常用到的通信模式。每一種通信方式都嚴(yán)格約定了與其對(duì)應(yīng)的通信協(xié)議,要確保計(jì)算機(jī)與plc之間能正常通信,就必須遵照其通信協(xié)議編寫(xiě)通信程序。

          2

          串行通信在工業(yè)系統(tǒng)控制的范疇中一直占據(jù)著極其重要的地位,串行端口(rs-232)是計(jì)算機(jī)上的標(biāo)準(zhǔn)配置,常用于連接調(diào)制解調(diào)器來(lái)傳輸數(shù)據(jù),在計(jì)算機(jī)的硬件設(shè)備管理器中可以看到,定義為com1、com2等。常用的串行通信方式有兩種,分別是rs-232和rs-485,本文以rs-232方式為例進(jìn)行介紹。

          3 上位機(jī)編程

          3.1 c++builder編程

          c++builder是由borland公司推出的產(chǎn)品。它采用c++語(yǔ)言作為開(kāi)發(fā)語(yǔ)言,是面向?qū)ο笳Z(yǔ)言,具有可視化編程界面且功能強(qiáng)大。

          3.2 c++builder串行通信相關(guān)api函數(shù)

          c++builder本身并不提供單獨(dú)的串行通信組件,而是使用一些windows api的函數(shù)來(lái)達(dá)到此目的。這些函數(shù)是由操作系統(tǒng)所提供,可以為程序設(shè)計(jì)人員提供相當(dāng)多的執(zhí)行功能。api中與串行通信相關(guān)的函數(shù)約有20個(gè),本文將對(duì)經(jīng)常使用的函數(shù)作討論。

          (1) 打開(kāi)串行端口

          hcomm=createfile(comno,generic_read|generic_write,0,null,open_existing,0,0)

          函數(shù)參數(shù)定義如下:

          hcomm:createfile()函數(shù)的返回值,程序使用此返回值進(jìn)行相關(guān)的串行端口操作。

          comno:定義串行端口號(hào),為com1、com2等。

          generic_read|generic_write:對(duì)串行端口的讀/寫(xiě)操作。

          0:是否共享串行端口,通常不會(huì)將串行端口與其它程序共享,因此設(shè)為0,否則為1。

          null:函數(shù)的返回值hcomm是否可被子程序繼承,此處設(shè)為不可繼承。

          open_existing:打開(kāi)端口的方式,串行端口是一種設(shè)備,必須指定為open_existing方式。

          0:使用同步或異步方式傳輸數(shù)據(jù),同步方式編程簡(jiǎn)單,速率快,因此設(shè)為0,否則為1。

          0:由于使用串行端口編程,設(shè)為0。

          (2) 得到串行端口狀態(tài):

          getcommstate(hcomm,dcb)

          函數(shù)參數(shù)定義如下:

          hcomm:createfile()函數(shù)的返回值。

          dcb:串行端口控制塊地址,負(fù)責(zé)對(duì)串行端口參數(shù)進(jìn)行設(shè)置,具體參數(shù)如下:

          dcb.baudrate:設(shè)置串行端口的波特率,有19200kb/s、9600kb/s、4800kb/s幾種,一般為:9600kb/s。

          dcb.bytesize:設(shè)置串行端口的數(shù)據(jù)位數(shù),有5、6、7、8幾種,歐姆龍plc數(shù)據(jù)位數(shù)為7。

          dcb.parity:設(shè)置串行端口的校驗(yàn)位檢查,有none、even、odd幾種,設(shè)為none。

          dcb.stopbits:設(shè)置串行端口的停止位數(shù),有1、1.5、2幾種, 歐姆龍plc的停止位數(shù)為1。

          (3) 設(shè)置串行端口狀態(tài):

          setcommstate (hcomm,dcb)

          函數(shù)參數(shù)定義與getcommstate()函數(shù)相同。

          (4) 向串行端口寫(xiě)數(shù)據(jù):

          writefile(hcomm,senddata,bs,lrc,null)

          函數(shù)參數(shù)定義如下:

          hcomm:createfile()函數(shù)的返回值。

          senddata:寫(xiě)數(shù)據(jù)的地址。

          bs:寫(xiě)入數(shù)據(jù)的字節(jié)數(shù)。

          lrc:被寫(xiě)入的數(shù)據(jù)地址。

          null:寫(xiě)入數(shù)據(jù)的同步檢查,串行端口采用同步通信時(shí)可以設(shè)為null。

          (5) 清除串行端口的錯(cuò)誤或?qū)⒋卸丝诋?dāng)前的數(shù)據(jù)狀態(tài)送至輸入緩沖區(qū):

          clearcommerror(hcomm,dwerror,cs)

          函數(shù)參數(shù)定義如下:

          hcomm:createfile()函數(shù)的返回值。

          dwerror:返回錯(cuò)誤信息代碼。

          cs:指向串行端口狀態(tài)的結(jié)構(gòu)變量。

          (6) 從串行端口的輸入緩沖區(qū)讀出數(shù)據(jù):

          readfile(hcomm,inbuff,cs.cbinque,nbytesread,null);函數(shù)參數(shù)定義如下:

          hcomm:createfile()函數(shù)的返回值。

          inbuff:指向用來(lái)存儲(chǔ)數(shù)據(jù)的地址。

          cs.cbinque:讀取數(shù)據(jù)的字節(jié)數(shù)。

          nbytesread:總的讀取字節(jié)數(shù)。

          null:如果不進(jìn)行后臺(tái)工作,串行端口設(shè)為null。

          (7) 關(guān)閉串行端口:

          closehandle(hcomm)

          函數(shù)參數(shù)定義如下:

          hcomm:createfile()函數(shù)的返回值。

          4 plc通信數(shù)據(jù)幀介紹

          計(jì)算機(jī)與歐姆龍plc通信時(shí),按應(yīng)答方式進(jìn)行。由計(jì)算機(jī)發(fā)給plc一組ascii碼字符數(shù)據(jù),這一組數(shù)據(jù)成為命令塊。plc收到命令塊后經(jīng)分析認(rèn)為命令正常,則按照命令進(jìn)行操作,將操作結(jié)果返回給計(jì)算機(jī)。plc返回給計(jì)算機(jī)的這一組數(shù)據(jù)稱為響應(yīng)塊。若plc收到命令后經(jīng)分析確認(rèn)命令不正常,則返回給計(jì)算機(jī)錯(cuò)誤命令塊。計(jì)算機(jī)和plc通信時(shí),歐姆龍plc是被動(dòng)的,必須先由計(jì)算機(jī)給plc發(fā)出命令塊,plc再給計(jì)算機(jī)發(fā)出響應(yīng)塊。命令塊和響應(yīng)塊以幀(frame)為單位進(jìn)行傳送,一幀最多由131個(gè)字符組成。下面將歐姆龍plc命令幀與響應(yīng)幀的組成結(jié)構(gòu)介紹如下:

          4.1 命令幀

          命令幀組成結(jié)構(gòu)如圖1所示。

          14.jpg

          幀結(jié)構(gòu)解析:

          @:在起始處必須放置

          節(jié)點(diǎn)號(hào):有效值為00—31, 表示pc機(jī)最多可同32臺(tái)plc通信

          頭代碼:plc的命令代碼

          發(fā)送文本:pc機(jī)發(fā)送的命令參數(shù)

          fcs(frame check sequence) :幀檢查順序代碼(幀校驗(yàn)碼)

          幀校驗(yàn)碼是2位(bit) 十六進(jìn)制數(shù)。它是由幀數(shù)據(jù)包含的所有字符的ascii碼進(jìn)行位異或運(yùn)算的結(jié)果。

          終止符:“*”號(hào)和回車符“cr”

          舉例如下:

          讀h區(qū)命令幀結(jié)構(gòu)如圖2所示。

          13.jpg

          4.2 響應(yīng)幀

          響應(yīng)幀結(jié)構(gòu)如圖3所示。

          12.jpg

          幀結(jié)構(gòu)解析:

          @ :返回命令頭

          節(jié)點(diǎn)號(hào) :有效值為00—31,返回?cái)?shù)據(jù)的plc節(jié)點(diǎn)號(hào)

          頭代碼 :plc的命令代碼

          尾代碼 : 返回命令完成狀態(tài)碼

          接收文本: 在有數(shù)據(jù)時(shí)返回的數(shù)據(jù)

          fcs :幀檢查順序代碼

          終止符:“*”號(hào)和回車符“cr”

          舉例如下:

          讀h區(qū)響應(yīng)幀結(jié)構(gòu)圖4所示。

          11.jpg

          4.3 fcs(幀數(shù)據(jù)冗余校驗(yàn)碼)的計(jì)算

          為了降低串行通信的誤碼率,在接收和發(fā)送端都必須對(duì)數(shù)據(jù)進(jìn)行校驗(yàn),常用的方法是進(jìn)行fcs校驗(yàn)。對(duì)幀數(shù)據(jù)進(jìn)行冗余校驗(yàn)計(jì)算時(shí),應(yīng)對(duì)幀數(shù)據(jù)中各個(gè)字符的ascii碼進(jìn)行位異或運(yùn)算,然后將結(jié)果轉(zhuǎn)為2位十六進(jìn)制字符。

          5 c++builder api函數(shù)應(yīng)用

          5.1 通信主程序的設(shè)計(jì)架構(gòu)

          通信主程序的主要功能:實(shí)現(xiàn)計(jì)算機(jī)對(duì)plc的運(yùn)行控制和狀態(tài)監(jiān)視,即構(gòu)成一個(gè)閉環(huán)監(jiān)控系統(tǒng),程序設(shè)計(jì)架構(gòu)如圖5所示。

          10.jpg

          5.2 打開(kāi)串信端口

          (1) 打開(kāi)通信端口,對(duì)端口進(jìn)行初始化設(shè)置,工作流程如圖6示。

          9.jpg

          (2) 打開(kāi)通信端口程序源代碼:

          void__fastcall tform1::button1click(tobject *sender)

          {

          char *comno;

          dcb dcb;

          string temp;

          temp=“com”+inttostr(rdcom-》itemindex+1);

          comno=temp.c_str() ;

          hcomm=createfile(comno,generic_read|generic_write,

          0,null,open_existing,1,0);

          if(hcomm==invalid_handle_value)

          {

          messagebox(0,“打開(kāi)通信端口錯(cuò)誤,請(qǐng)檢查端口是否被占用!!” ,“comm error”,mb_ok);

          return;

          }

          getcommstate(hcomm,dcb);

          dcb.baudrate=cbr_9600;

          dcb.bytesize =7;

          dcb.parity =evenparity;

          dcb.stopbits =onestopbit;

          setcommstate(hcomm,dcb);

          if(!setcommstate(hcomm,dcb))

          {

          messagebox(0,“通信端口設(shè)置錯(cuò)誤!!!”,“set error”,mb_ok);

          closehandle(hcomm);

          return;

          }

          }

          5.3 寫(xiě)plc內(nèi)存數(shù)據(jù)

          (1) 將計(jì)算機(jī)發(fā)出的命令寫(xiě)入plc,實(shí)現(xiàn)計(jì)算機(jī)對(duì)plc的控制功能。工作流程如圖7示。

          8.jpg

          (2) 寫(xiě)plc內(nèi)存函數(shù)程序源代碼:

          string tform1::write(string address,string value)

          {

          unsigned long lrc,bs;

          string temp;

          char *senddata;

          char inbuff[1024];

          int ln,i=0;

          string word,check;

          dword nbytesread,dwevent,dwerror;

          comstat cs;

          word=“@00wd”+address+value;

          if(hcomm==0)

          {

          messagebox(0,“串口未打開(kāi)!!!”,“錯(cuò)誤信息”,mb_ok);

          return(0);

          }

          temp=outchecksum(word);

          senddata=temp.c_str() ;

          bs=strlen(senddata);

          loop:

          if(++i《=3)

          {

          writefile(hcomm,senddata,bs,lrc,null);

          sleep(100);

          if(hcomm==invalid_handle_value) return(0);

          clearcommerror(hcomm,dwerror,cs);

          if(cs.cbinque》sizeof(inbuff))

          {

          purgecomm(hcomm,purge_rxclear);

          return(0);

          }

          readfile(hcomm,inbuff,15,nbytesread,null);

          check=inbuff;

          if(check.substring(6,2)!=“00”)

          {

          goto loop;

          }

          }

          else

          {

          messagebox(0,“數(shù)據(jù)寫(xiě)錯(cuò)誤”,“通信錯(cuò)誤”,mb_ok);

          }

          }

          5.4 讀plc內(nèi)存數(shù)據(jù)

          (1)從plc中讀取數(shù)據(jù),監(jiān)視plc的運(yùn)行數(shù)據(jù),工作流程如圖8示。

          7.jpg

          (2) 讀plc內(nèi)存函數(shù)程序源代碼:

          string tform1::read(string address,string value)

          {

          string readdata,readdata1,readdata2;

          string temp;

          unsigned long lrc,bs;

          char *senddata;

          int ln,i=0,len;

          dword nbytesread,dwevent,dwerror;

          comstat cs;

          char inbuff[1024];

          string word;

          word=“@00rd”+address+value;

          if(hcomm==0) return(0);

          temp=outchecksum(word);

          senddata=temp.c_str();

          bs=temp.length();

          loop:

          if(++i《=3)

          {

          writefile(hcomm,senddata,bs,lrc,null);

          sleep(100);

          if(hcomm==invalid_handle_value) return(0);

          clearcommerror(hcomm,dwerror,cs);

          if(cs.cbinque》sizeof(inbuff))

          {

          purgecomm(hcomm,purge_rxclear);

          return(0);

          }

          cs.cbinque=4*strtoint(value)+11;

          readfile(hcomm,inbuff,cs.cbinque,nbytesread,null);

          inbuff[cs.cbinque]=`看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();