1771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC3171771-IXHR ABGE IC693ACC317
利用軟件編程方式,可以更加靈活實現(xiàn)各種非常規(guī)的通訊。
由于自行編寫的程序在工程師站/操作員站運行,需要占用一定的CUP時間及內(nèi)存,因此在通訊數(shù)據(jù)量較大,同時要求通訊速度較快時,由于沒有專業(yè)通訊軟件的“例外報告”機制,建議不要采用自行開發(fā)程序的辦法。
由于自行編寫的程序通常沒有“數(shù)據(jù)緩存”機制,在傳送非常重要的數(shù)據(jù)時應(yīng)該謹慎使用。
自行編程主要工作為了兩方面,一為I/A數(shù)據(jù)的讀寫及處理,一為通訊的實現(xiàn)。
通常自行開發(fā)通訊軟件包括:串口通訊(如智能前端)、TCP/IP通訊(如實時數(shù)據(jù)傳送)、FTP通訊(如定期傳送報表文本)、基于TCP/IP的MODBUS協(xié)議通訊。
以上幾種通訊方式在通訊的實現(xiàn)方式上不同,但在I/A’s內(nèi)數(shù)據(jù)的讀寫操作是一樣的,接下來將闡述軟件編程時的主要函數(shù)及方式:
4.1I/A’s數(shù)據(jù)的讀寫及處理
Foxboro公司I/A’s系統(tǒng)提供強大的內(nèi)部編程函數(shù)(C函數(shù)、FORTRAN),主要包括有:
lOMCALL函數(shù)–實現(xiàn)I/A’s系統(tǒng)內(nèi)部數(shù)據(jù)的讀寫操作。
主要函數(shù)有:
2intgetval(char*name,intobj_type,intimport,char*value,unsignedint*status,intdata_len)
此函數(shù)實現(xiàn)單個數(shù)據(jù)的讀操作。
2intom_getval(char*name,intobj_type,intimport,charvalue,unsignedint*status,intdata_len,PSAP_ADDR*psap_ptr)
此函數(shù)實現(xiàn)單個數(shù)據(jù)的讀操作,它使用PSAP指針。
2intsetval(char*name,intobj_type,intimport,char*value,unsigned*status,intdata_len)
此函數(shù)實現(xiàn)單個數(shù)據(jù)的寫操作。
2intom_setval(char*name,intobj_type,intimport,char*value,unsigned*status,intdata_len,PASP_ADDR*psap_ptr);
此函數(shù)實現(xiàn)單個數(shù)據(jù)的寫操作,它使用PSAP指針。
2intomopen(structom_header_node*om_debor,intopen_id)
此函數(shù)實現(xiàn)打開一個LIST,為數(shù)據(jù)的讀寫操作做準備。
2intomread(intomopen_id,intsize_list,structvalue*var_list)
此函數(shù)實現(xiàn)從打開的LIST中讀取數(shù)據(jù)。
2intomwrite(intomopen_id,intsize_list,structvalue*var_list);
此函數(shù)實現(xiàn)向打開的LIST中寫數(shù)據(jù)。
2intomclose(intopen_id,structom_header_node*header,structopen_var*var_list,structnet_addr*addr_tbl)
此函數(shù)實現(xiàn)關(guān)閉一個已經(jīng)打開的LIST。
2頭部文件、OM結(jié)構(gòu)及例程
#include
#include
#include
#include
#include
main()
{
structopen_varin_var_list[8];
structheader_nodein_om_desc;
structnet_adrin_net_adr_tbl[2];
intin_open_id;
intrtn;
floatdelta_temp,delta_fc,delta_df;
structvalue*in_data_list,*temp;
inti;
delta_temp=5.0;
delta_fc=1.0;
delta_df=0.5;
in_om_desc.task_status=OM_R_ACCESS;
in_om_desc.net_adr_tbl_ptr=in_net_adr_tbl;
in_om_desc.size_net_adr_tbl=2;
in_om_desc.open_list_ptr=in_var_list;
in_om_desc.size_open_list=8;
……
}
2特點
使用getval、setval、om_getval、om_setval函數(shù)進行編程比較簡單,但效率較差;用omopen、omread、omwrite、omclose編程需要復(fù)雜的聲明,編程比較復(fù)雜,但程序通用性好(不要FOXAPI的支持)、效率高。
lFOXAPI函數(shù)–實現(xiàn)I/A’s系統(tǒng)內(nèi)部數(shù)據(jù)的讀寫操作及強大的C/S結(jié)構(gòu)編程。
主要函數(shù)有:
2intsbopen(int*gw_array,intnument,char*name_array,int*valtyp_array,intacctyp,float*delta_array,intclexit,intrsr,intwsr,float*wdelta_array,int*dset,int*index_array,int*error_array,int*reterr)
此函數(shù)實現(xiàn)以連續(xù)更新的方式打開一個讀寫SET。
2intbread(intdset,long*value_array,int*status_array,int*reterr)
此函數(shù)實現(xiàn)從一個已經(jīng)打開SET中讀取數(shù)據(jù)。
2intbwrite(intdset,long*value_array,int*error_array,int*reterr)
此函數(shù)實現(xiàn)向一個已經(jīng)打開SET中寫數(shù)據(jù)。
2intclsset(intdset,int*reterr)
此函數(shù)實現(xiàn)關(guān)閉一個已經(jīng)打開SET,釋放程序所使用的內(nèi)存空間,釋放對CP中數(shù)據(jù)的控制權(quán)。
2頭部函數(shù),F(xiàn)OXAPI結(jié)構(gòu)定義及例程
#include
#include
#include
#include
#include
#include
#include
#defineOBJNUM100
#defineSETNUM20
typedefunion
{
longlval;
shortival;
floatfval;
charbval;
}IAXVAL;
/*PredefinedParameterofI/Avalue*/
staticintgw[SETNUM][OBJNUM];/*GatewayArray*/
charname[SETNUM][OBJNUM][32];/*ObjectNameArray*/
chardesc[SETNUM][OBJNUM][15];/*ObjectdebionArray*/
staticintvaltype[SETNUM][OBJNUM];/*ObjectValueTypeArray*/
staticintacctype=1;/*Read-onlyArray*/
staticfloatrdelta[SETNUM][OBJNUM];/*ObjectsReadDeltaArray*/
staticfloatwdelta[SETNUM][OBJNUM];/*ObjectsWriteDeltaArray*/
interror[SETNUM][OBJNUM];/*ObjectsErrorArray*/
intindex[SETNUM][OBJNUM];/*ObjectsIndexesArray*/
intstatus[SETNUM][OBJNUM];/*ObjectsStatusArray*/
IAXVALvalue[SETNUM][OBJNUM];/*ObjectsValueArray*/
staticintrsr=4;/*ReadScanRate*/
staticintwsr=4;/*WriteScanRate*/
staticintclexit=1;/*IgnoredinUNIX*/
intreterr[SETNUM];/*OpenSetreturnErrorCode*/
/*PredefineParameterofutility*/
intset[SETNUM];/*OpenSetNumber*/
intTotal_SET;/*TotalSetNumber*/
intLast_SET_Num;/*LastSetValueNuber*/
intTotal_Num;/*TotalNumberofbs*/
intTotal_File;/*TotaloutputfilesNumber*/
intINTERVAL;/*Communicateinterval*/
intCol_Num;/*Valuenumberperline*/
main()
{
……scopen(gw[i],k,name[i],valtype[i],acctype,rdelta[i],clexit,rsr,\
wsr,wdelta[i],&set[i],index[i],error[i],&reterr[i]);
printf(“ReturnErrorCode=%-d\n”,reterr[i]);
printf(“ReturnDataSet=%-d\n”,set[i]);
……rtn=bread(set[i],value[i],status[i],&reterr[i]);
if(reterr[i]!=0)
{
printf(“BufferedReadObjectsError%d,%d,%d\n”,rtn,\
reterr[i],set[i]);
}
……for(i=0;i
{
clsset(set[i],&reterr[i]);
}
……
}
2特點
使用FOXAPI編程比較簡單,程序效率也很高,但程序的執(zhí)行需要FOXAPI的支持,編譯好的程序只能在裝有FOXAPI的AW、AP機器中運行。PI實時數(shù)據(jù)庫實際上便是利用FOXAPI函數(shù)編寫的應(yīng)用程序。
lHICALL函數(shù)–實現(xiàn)具有I/A’s風格的人機界面(HUMANINTERFACE)編程,包括顯示元素,如:矩形、圓弧、填充色;對話框、菜單結(jié)構(gòu)、鼠標鍵盤驅(qū)動、查詢、文件驅(qū)動等,事實上,整個I/A’s的人機界面編寫既是通過這些函數(shù)完成。
lIPCALL函數(shù)–實現(xiàn)I/A’s系統(tǒng)內(nèi)部通訊編程,如:SOE軟件等。
lICCAPI函數(shù)–實現(xiàn)I/A’s控制處理器CP中CIO的相關(guān)操作。
l數(shù)學庫–提供各種經(jīng)典數(shù)值計算的調(diào)用函數(shù)。
l物理特性庫–提供各種物理特性計算的調(diào)用函數(shù),包括水、蒸汽的焓、熵等計算。
2intvpt(floatp,floatt,float*v)
此函數(shù)根據(jù)蒸汽的壓力及溫度計算蒸汽的容積。
2inthpt_stm(floatp,floatt,float*h)
此函數(shù)根據(jù)蒸汽的壓力及溫度計算蒸汽的焓。
2intspt_stm(floatp,floatt,float*s)
此函數(shù)根據(jù)蒸汽的壓力及溫度計算蒸汽的熵。
2inthpt_wtr(floatp,floatt,float*h)
此函數(shù)根據(jù)水的壓力及溫度計算水的焓。
2intspt_wtr(floatp,floatt,float*s)
此函數(shù)根據(jù)水的壓力及溫度計算水的熵。
2inthpt_air(floatp,floatt,float*h)
此函數(shù)根據(jù)空氣的壓力及溫度計算空氣的焓。
2intspt_air(floatp,floatt,float*s)
此函數(shù)根據(jù)空氣的壓力及溫度計算空氣的熵。
lINFORMIX編程。
在某些需要對歷史數(shù)據(jù)進行操作的場合,可以利用INFORMIX及E-SQL進行編程。
4.2通訊的實現(xiàn)
在用軟件編程實現(xiàn)通訊時所采用的具體的通訊硬件上,既可以通過串口實現(xiàn)RS-232通訊,也可以通過AUI網(wǎng)卡、BNC網(wǎng)卡、RJ-45網(wǎng)卡實現(xiàn)FTP通訊、TCP/IP通訊。
當與I/A’s通訊的其它設(shè)備(如智能數(shù)據(jù)采集前端、GPS、自動同期裝置等非通用設(shè)備)可以提供串口通訊,且通訊點數(shù)量不多時,采用專門的硬件實現(xiàn)通訊硬件不是一個非常經(jīng)濟的方案,此時可以采用RS-232實現(xiàn)通訊。
用RS-232實現(xiàn)通訊時,首先應(yīng)初始化通訊端口,然后可以按RS-232通訊規(guī)程(RXD,TXD,RTS,CTS,DSR,DTR,DCD信號),發(fā)送指令并接受數(shù)據(jù)。
以下是初始化端口的一段例程:
intinit_port(intk,int*fd,char*comport)
{
intsavef;
if((*fd=open(comport,O_RDWR|O_NDELAY|O_NONBLOCK))《0)
return(1);
fflush(stdout);
fflush(stdin);
if(savef=fcntl(*fd,F(xiàn)_GETFL,0)《0)
return(2);
if(fcntl(*fd,F(xiàn)_SETFL,savef|O_NDELAY)《0)
return(3);
if(ioctl(*fd,TCGETS,&termio)《0)
return(4);
/*Settheportbeteras9600Baudrate,8databits,1siopbit,
Enablereceiver,Evenparityenable*/
termio.c_cflag=B9600|CS8|CREAD|PARENB|CLOCAL;
termio.c_cflag&=~CSTOPB;
termio.c_cflag&=~PARODD;
termio.c_iflag=INPCK;
termio.c_iflag&=~ISTRIP;
termio.c_lflag=0;
termio.c_oflag=0;
termio.c_cc[VMIN]=1;
termio.c_cc[VTIME]=0;
if(ioctl(*fd,TCSETS,&termio)《0)
return(5);
sleep(1);
return(0);
}
以下是讀寫端口的一段例程:
intcomm(unsignedcharnum,intfd)
{
intI,rtn,tioc;
unsignedcharT[200];
unsignedcharbuff[200];
……ioctl(fd,TIOCMGET,&tioc);
tioc=tioc|TIOCM_RTS;
ioctl(fd,TIOCMSET,&tioc);
……write(fd,T,200);
rtn=ioctl(fd,TCSBRK,1);
strcpy(buf,”“,200);
read(fd,buf,200);
}
如果與I/A’s進行通訊的是PC機或其它DCS,比較好的通訊辦法是利用RJ-45等通訊口,按FTP協(xié)議或TCP/IP協(xié)議進行通訊。其中,F(xiàn)TP通訊的效率較低,且一直有讀盤/寫盤動作,對機器的影響較大,但此方法比較簡單,容易實現(xiàn),因此,在通訊不頻繁的時候(建議大于一小時),也可以采用這個辦法。在更多的時候,則建議使用TCP/IP協(xié)議進行通訊。
利用TCP/IP進行通訊時,有兩個協(xié)議可以選擇:TCP及UDP,其中TCP(TransportControlProtocol,傳輸控制協(xié)議)是面向聯(lián)接的,它提供高可靠性服務(wù),尤其適用于傳輸大量報文信息。UDP(UserDatagramProtocol,用戶數(shù)據(jù)報協(xié)議)是無聯(lián)接的,它提供高效率的服務(wù),適用于一次傳輸少量報文信息的場合。
UDP通訊的程序的編寫也比較容易,只需指定客戶機的IP地址(或主機名)及傳送端口號即可,下面是一段利用UDP初始化例程:
#include
#include
#include
#include
#include
#include
intsock,length;
structsockaddr_in,sockname;
charbuff[1024];
intInit_Socket()
{
char*clientName=“AW5101”;
intportNum=10002;
structhostent*hp,*gethostbyname();
/*Creatsocketonwhichtosend.*/
sock=socket(AF_INET,SOCK_DGRAM,0);
if(sock==-1)
{
perror(“opendatagramsocketerr0r”);
exit(1);
}
hp=gethostbyname(clientName);
if(hp==(structhostent*)0)
{
printf(“unkownhost:%s\n”,clientName);
exit(2);
}
memcpy((char*)&sockname.sin_addr,(char*)hp-》h_addr,hp-》h_length);
sockname.sin_family=AF_INET;
sockname.sin_port=htons(atoi(portNum);
return(0);
}……