文獻(xiàn)標(biāo)識(shí)碼: A
文章編號(hào): 0258-7998(2011)11-0144-03
目前,工業(yè)組態(tài)軟件已經(jīng)廣泛應(yīng)用于工業(yè)控制領(lǐng)域,易控(INSPEC)是北京九思易自動(dòng)化軟件有限公司(ControlEase AutomationSoftware)推出的一套通用數(shù)據(jù)采集和監(jiān)控(SCADA)軟件,具有最新的.NET Framework 框架平臺(tái),應(yīng)用極為廣泛。為了與現(xiàn)場(chǎng)設(shè)備進(jìn)行交互, INSPEC提供了國(guó)內(nèi)外各種常用的工控設(shè)備的驅(qū)動(dòng)程序。但是由于現(xiàn)場(chǎng)設(shè)備種類(lèi)繁多,支持的通信協(xié)議各不相同,因此,需要針對(duì)不同的底層設(shè)備編寫(xiě)相應(yīng)的驅(qū)動(dòng)程序,以實(shí)現(xiàn)同組態(tài)軟件的信息交互。許多底層設(shè)備采用單片機(jī)進(jìn)行設(shè)計(jì),本文針對(duì)基于51單片機(jī)的設(shè)備進(jìn)行了通用的驅(qū)動(dòng)程序設(shè)計(jì),通過(guò)此通用驅(qū)動(dòng)程序,設(shè)計(jì)者只需簡(jiǎn)單的設(shè)置就可以將基于51單片機(jī)的儀表、設(shè)備接入INSPEC,無(wú)需重新開(kāi)發(fā)驅(qū)動(dòng)程序。而且只需將所設(shè)計(jì)的驅(qū)動(dòng)程序進(jìn)行少量改動(dòng),即可適應(yīng)各種類(lèi)型的設(shè)備,或與其他類(lèi)型的單片機(jī)進(jìn)行通信。
1 基于51單片機(jī)的設(shè)備與上位組態(tài)軟件的連接
對(duì)于易控組態(tài)軟件,底層設(shè)備屬于I/O設(shè)備。上位機(jī)通過(guò)硬件通道與硬件設(shè)備建立連接關(guān)系,按照對(duì)應(yīng)的通信協(xié)議與硬件設(shè)備交換數(shù)據(jù),并將采集到的運(yùn)行數(shù)據(jù)經(jīng)轉(zhuǎn)換后通過(guò)數(shù)據(jù)庫(kù)接口傳送至數(shù)據(jù)庫(kù),同時(shí)響應(yīng)數(shù)據(jù)庫(kù)關(guān)聯(lián)變量來(lái)改變事件,將輸入數(shù)據(jù)寫(xiě)入硬件設(shè)備。51單片機(jī)提供了一個(gè)全雙工標(biāo)準(zhǔn)接口,通過(guò)電平轉(zhuǎn)換芯片MAX232及相關(guān)外圍電路來(lái)實(shí)現(xiàn)TTL信號(hào)和RS-232電平信號(hào)之間的轉(zhuǎn)換,并實(shí)現(xiàn)與計(jì)算機(jī)串口RS-232的硬件通信通道連接。通過(guò)設(shè)備驅(qū)動(dòng)程序,完成基于51單片機(jī)的設(shè)備與上位組態(tài)軟件的數(shù)據(jù)交互。其接口結(jié)構(gòu)如圖1所示。
2 利用開(kāi)發(fā)向?qū)沈?qū)動(dòng)程序的框架[1-2]
根據(jù)INSPEC組態(tài)軟件I/O系統(tǒng)的驅(qū)動(dòng)設(shè)計(jì)規(guī)范, I/O系統(tǒng)由服務(wù)器類(lèi)(DeviceIoMgr)、通道類(lèi)(Channel)、設(shè)備類(lèi)(Device)、I/O變量類(lèi)(IoTag)構(gòu)成。INSPEC提供了設(shè)備驅(qū)動(dòng)程序開(kāi)發(fā)包(SDK),驅(qū)動(dòng)程序的開(kāi)發(fā)環(huán)境為Visual Studio 2008。采用C#為開(kāi)發(fā)語(yǔ)言,易控提供驅(qū)動(dòng)程序開(kāi)發(fā)模板。
2.1 設(shè)備驅(qū)動(dòng)程序的建立
設(shè)備驅(qū)動(dòng)程序的建立需運(yùn)行Microsoft Visual Studio 2008,新建項(xiàng)目類(lèi)型為“Visual C# 易控(INSPEC)”,在“我的模板”位置會(huì)出現(xiàn)“設(shè)備通信”模板,輸入項(xiàng)目名稱(chēng)為單片機(jī)通用驅(qū)動(dòng),支持通道名稱(chēng)選擇串口,根據(jù)向?qū)瓿尚陆?xiàng)目的配置。然后修改項(xiàng)目的三個(gè)重要屬性:
(1) 程序集名稱(chēng)要遵從“Controlease.IoDrive.廠家名.設(shè)備名”的規(guī)則。在項(xiàng)目屬性設(shè)置窗口中,點(diǎn)擊“應(yīng)用程序”, 將程序集名稱(chēng)修改為ControlEase.IoDrive.Control
Ease.單片機(jī)通用驅(qū)動(dòng)。
(2) 生成事件是生成I/O設(shè)備驅(qū)動(dòng)的DLL文件。由于易控啟動(dòng)時(shí)從文件夾..\ControlEase\INSPEC\Devices下加載驅(qū)動(dòng),所以將生成驅(qū)動(dòng)DLL的路徑設(shè)置在此目錄。
(3) 引用路徑是驅(qū)動(dòng)項(xiàng)目中引用類(lèi)庫(kù)的路徑,一般設(shè)置在..\ControlEase\INSPEC\目錄下。
2.2 驅(qū)動(dòng)程序的設(shè)計(jì)方法
在易控提供的驅(qū)動(dòng)程序開(kāi)發(fā)模板下,為了實(shí)現(xiàn)I/O設(shè)備的自定義功能,主要修改設(shè)備通信模板的讀、寫(xiě)以及特殊操作方法。本通用驅(qū)動(dòng)程序的設(shè)計(jì)修改了單片機(jī)通用驅(qū)動(dòng)Protocol.cs類(lèi)中的ReadPacket(SampleTagPacket packet)和WriteTag(IoTag tag)方法。
(1) 設(shè)備數(shù)據(jù)采集
易控采用循環(huán)采集的方式來(lái)采集現(xiàn)場(chǎng)設(shè)備數(shù)據(jù)。所有具有“只讀/讀寫(xiě)”屬性的I/O量,都會(huì)按照I/O變量設(shè)置的“查詢(xún)周期”進(jìn)行采集。每次采集過(guò)程都會(huì)進(jìn)入ReadPacket方法中。
設(shè)備數(shù)據(jù)采集過(guò)程,默認(rèn)采集方式為變量包采集方式。在該設(shè)備通信程序開(kāi)發(fā)包里,把所有在INSPEC軟件中添加的可讀IoTag都添加到了一個(gè)數(shù)據(jù)包中,采集程序從bool ReadPacket(SampleTagPacket packet)方法進(jìn)入,數(shù)據(jù)采集流程圖如圖2所示。
數(shù)據(jù)采集部分編程如下:
public override bool ReadPacket(SampleTagPacket packet)
{
int sendCount = FormReadOrder(packet);
int toReceiveCount = packet.Length * 4 + 5;
if (packet.RegType == RegTypeList.CoilStatus.ToString()
|| packet.RegType == RegTypeList.InputStatus.ToString())
{
toReceiveCount = packet.Length % 8 == 0 ? (packet.
Length/8+5) : (packet.Length/8+1+5);
}
int receiveCount=WriteAndRead(sendCount, toReceive
Count);
if (receiveCount < toReceiveCount)
{
TraceLog.TraceError(string.Format(Resources.NOT_ENOUGH_
DATA_RECEIVED, receiveCount));
return false;
}
if (!CheckOutReceivedData(receiveCount))
{
return false;
}
return ParseIO(packet, receiveCount);
}
在這段代碼中,首先調(diào)用FormReadOrde方法,組成了通信協(xié)議幀,并返回讀命令長(zhǎng)度。然后通過(guò)WriteAndRead方法,完成了串口的讀寫(xiě)操作,即完成了上位機(jī)與設(shè)備間的一次通信。收到返回?cái)?shù)據(jù)以后,調(diào)用CheckOutReceivedData方法,對(duì)從串口接收到的數(shù)據(jù)進(jìn)行校驗(yàn)。最后,調(diào)用數(shù)據(jù)解析ParseI/O方法,將接收到的數(shù)據(jù)轉(zhuǎn)換成I/O變量的值。
(2) 寫(xiě)設(shè)備變量
易控中所有的賦值操作,只要I/O變量具有“只寫(xiě)/讀寫(xiě)”屬性,并且I/O變量關(guān)聯(lián)的數(shù)據(jù)庫(kù)變量的值發(fā)生變化,都會(huì)觸發(fā)寫(xiě)操作,并進(jìn)入WriteTag方法。將參數(shù)寫(xiě)到設(shè)備里面,默認(rèn)調(diào)用方式為寫(xiě)IoTag,程序從bool WriteTag(IoTag tag)方法進(jìn)入,寫(xiě)設(shè)備變量流程圖如圖3所示。
寫(xiě)設(shè)備變量部分編程如下:
public override bool WriteTag(IoTag tag)
{
int sendCount = FillWriteFrame(tag);
if (sendCount <= 0)
{
return true;
}
const int toReceiveCount = 10;
int receiveCount = WriteAndRead(sendCount, toReceive-
Count);
if(!CheckOutReceivedData(receiveCount, toReceiveCount))
{
return false;
}
return true;
}
在這段代碼中,首先調(diào)用FormWriteOrder方法,組成了通信協(xié)議幀,并返回寫(xiě)命令長(zhǎng)度,然后通過(guò)WriteAndRead方法,完成了串口的讀寫(xiě)操作,即上位機(jī)與設(shè)備完成了一次通信。在收到返回?cái)?shù)據(jù)以后,調(diào)用CheckOutReceivedData方法,對(duì)串口接收到的數(shù)據(jù)進(jìn)行校驗(yàn)。
2.3 數(shù)據(jù)打包
易控進(jìn)行設(shè)備數(shù)據(jù)采集的最小單位是一個(gè)數(shù)據(jù)包(SampleTagPacket)。在默認(rèn)設(shè)備采集過(guò)程中,所有的查詢(xún)周期相同的IoTag都將會(huì)打包到同一個(gè)數(shù)據(jù)包中。這個(gè)數(shù)據(jù)包就是易控的基本采集單位變量包packet,即IoTag的集合。設(shè)備類(lèi)中的CanAddToPacket方法是為讀打包服務(wù)的,該方法將返回一個(gè)Bool值,用來(lái)判斷是否可以打成一個(gè)包。在該方法下設(shè)計(jì)需要打包寄存器的條件,只要返回TRUE,滿(mǎn)足條件的寄存器就會(huì)自動(dòng)打成一個(gè)包。
CanAddToPacket有兩個(gè)參數(shù),packet指的就是包,它包括多個(gè)滿(mǎn)足打包條件的tag(tag指準(zhǔn)備要打包的寄存器)。如果滿(mǎn)足打包條件,tag就會(huì)被添加到packet中。具體實(shí)現(xiàn)方法如下:
Protected override bool CanAddToPacket(SampleTagPacket packet, IoTag tag)
{
if (packet.RegType != tag.RegType)
{
return false;
}
if(SerialDevice1BaseInfo.IsBitRegister(packet.RegType) &&Get-
CombineLength(packet,tag)>=SerialDevice1BaseInfo.MaxCombine
Length * 16)
{
return false;
}
if(GetCombineLength(packet,tag)>=SerialDevice1BaseInfo.
MaxCombineLength * 16)
{
return false;
}
return base.CanAddToPacket(packet, tag);
}
2.4 驅(qū)動(dòng)程序通道配置
INSPEC在I/O通信的通道中配置復(fù)雜的串行端口參數(shù)(如波特率大小,數(shù)據(jù)位長(zhǎng)度,停止位位數(shù),有無(wú)奇偶校驗(yàn)等)、初始化和讀寫(xiě)操作,用戶(hù)可以針對(duì)不同設(shè)備的通信協(xié)議進(jìn)行相關(guān)的配置,即可將51單片機(jī)儀表和設(shè)備接入INSPEC,避免了驅(qū)動(dòng)程序的重復(fù)開(kāi)發(fā)。
通道配置完成后,點(diǎn)擊“下一步”進(jìn)行設(shè)備的選擇,編寫(xiě)好的設(shè)備驅(qū)動(dòng)“單片機(jī)通用設(shè)備”已經(jīng)加載到了易控可選設(shè)備中,如圖4所示。由于易控中提供兩種數(shù)據(jù)傳遞類(lèi)型,一種是比較常用的字節(jié)形式(ByteArrayParseInfo),另一種是在智能儀表中常用的ASCII碼字符串形式(StringParseInfo)。根據(jù)協(xié)議能很方便地確認(rèn)設(shè)備采用的是哪一種形式,然后根據(jù)需要定義對(duì)應(yīng)的數(shù)據(jù)轉(zhuǎn)換信息類(lèi),這里選擇的是字符串方式。點(diǎn)擊“完成”即建好通道。
3 基于51單片機(jī)的通信程序設(shè)計(jì)[3]
該驅(qū)動(dòng)程序具有較強(qiáng)的通用性,在INSPEC中用戶(hù)只需根據(jù)底層設(shè)備的通信協(xié)議進(jìn)行通道配置即能完成INSPEC與下位機(jī)之間的通信;另一方面,用戶(hù)也可以先配置好INSPEC的通道,并根據(jù)通道配置在下位51單片機(jī)的通信程序里進(jìn)行相關(guān)協(xié)議的編寫(xiě),實(shí)現(xiàn)上位和下位機(jī)的通信協(xié)議的一致性。
51單片機(jī)的串行口內(nèi)部有兩個(gè)物理上獨(dú)立的接收、發(fā)送緩沖器SBUF,可同時(shí)發(fā)送、接收數(shù)據(jù)。用戶(hù)將數(shù)據(jù)存放在SBUF寄存器里來(lái)完成與上位機(jī)INSPEC的數(shù)據(jù)交互。為了更好地體現(xiàn)驅(qū)動(dòng)程序的通用性,在驅(qū)動(dòng)程序里定義了收發(fā)數(shù)據(jù)的緩沖區(qū)大小,用戶(hù)只需將底層設(shè)備的數(shù)據(jù)存儲(chǔ)到已定義的緩沖區(qū)里就能完成數(shù)據(jù)的交互,編程如下:
private readonly byte[] mReceiveBuffer = new byte[2048] //用于保存接收到的數(shù)據(jù)
private readonly byte[] mSendBuffer = new byte[1024]
//用于保存發(fā)送的命令
這里單片機(jī)串口工作于方式1,數(shù)據(jù)幀格式為8 bit數(shù)據(jù)位,1 bit停止位,定時(shí)/計(jì)數(shù)器1用作波特率發(fā)生器,PCON中的SMOD位為0,發(fā)送的波特率為9 600,系統(tǒng)初始化程序如下:
TMOD=0x22; //定時(shí)器T1,在方式2中斷產(chǎn)生
//波特率
PCON &=0x00; //波特率不倍增,SMOD=0
SCON=0x40;
TH1=0xfd; //波特率設(shè)置為9 600
TL1=0xfd;
4 通用驅(qū)動(dòng)程序在電壓監(jiān)測(cè)儀表上的應(yīng)用
該應(yīng)用中下位機(jī)采用STC89C52系列單片機(jī)為主控芯片的電壓監(jiān)測(cè)儀表,上位機(jī)監(jiān)控軟件為INSPEC。由于已經(jīng)編寫(xiě)了單片機(jī)的通信協(xié)議,所以在易控中進(jìn)行通道配置時(shí)應(yīng)該與單片機(jī)通信協(xié)議保持一致,即8 bit數(shù)據(jù)位,1 bit停止位,波特率為9 600。通道配置完成后,在設(shè)備中選擇單片機(jī)通用驅(qū)動(dòng)就完成了I/O通信的配置。
電壓監(jiān)測(cè)儀表中的電壓傳感器將采集的電壓信號(hào)傳給A/D模塊進(jìn)行數(shù)據(jù)轉(zhuǎn)換,并進(jìn)入單片機(jī)進(jìn)行數(shù)據(jù)處理,經(jīng)RS-232端口與上位機(jī)的監(jiān)控軟件INSPEC通信。通過(guò)數(shù)據(jù)交互,可在上位機(jī)上直接顯示現(xiàn)場(chǎng)的電壓值,以達(dá)到對(duì)現(xiàn)場(chǎng)電壓的實(shí)時(shí)監(jiān)測(cè)。
4.1 上位機(jī)監(jiān)控界面的設(shè)計(jì)[4]
INSPEC軟件能夠很方便地實(shí)現(xiàn)對(duì)自動(dòng)化過(guò)程和裝備的監(jiān)測(cè)和控制。在INSPEC中添加實(shí)時(shí)數(shù)據(jù)庫(kù)變量,其中包括了控制系統(tǒng)所需的數(shù)據(jù)交互信息:電壓設(shè)定值、監(jiān)測(cè)電壓值、電壓報(bào)警指示和監(jiān)測(cè)電壓的實(shí)時(shí)曲線圖等變量,使監(jiān)控窗口和數(shù)據(jù)通道的變量關(guān)聯(lián)起來(lái)。
4.2 驅(qū)動(dòng)程序的裝載
在Microsoft Visual Studio 2008開(kāi)發(fā)環(huán)境中,驅(qū)動(dòng)程序編譯后在文件夾..\ControlEase\INSPEC\Devices下生成ControlEase.IoDrive.ControlEase.,單片機(jī)通用驅(qū)動(dòng).dll驅(qū)動(dòng)文件。啟動(dòng)易控開(kāi)發(fā)環(huán)境時(shí),會(huì)自動(dòng)將驅(qū)動(dòng)文件加載到易控的設(shè)備選擇中供用戶(hù)選擇。
針對(duì)組態(tài)軟件應(yīng)用中驅(qū)動(dòng)程序的開(kāi)發(fā)問(wèn)題,本文設(shè)計(jì)了基于INSPEC的51系列單片機(jī)通用驅(qū)動(dòng)程序。實(shí)現(xiàn)了INSPEC和單片機(jī)控制的外部設(shè)備進(jìn)行通信,解決了基于51系列單片機(jī)設(shè)備驅(qū)動(dòng)程序的重復(fù)設(shè)計(jì)問(wèn)題。為以后開(kāi)發(fā)其他設(shè)備驅(qū)動(dòng)程序提供了設(shè)計(jì)思路和程序框架,對(duì)實(shí)現(xiàn)底層設(shè)備方便接入組態(tài)軟件進(jìn)行了有益的探索。
參考文獻(xiàn)
[1] 北京九思易自動(dòng)化軟件有限公司.易控(INSPEC)高級(jí)開(kāi)發(fā)指南[M]. 2009.
[2] ROBINSON S, CORNES O. C#高級(jí)編程[M]. 康博,譯. 北京:清華大學(xué)出版社,2002.
[3] 李全利,遲榮強(qiáng).單片機(jī)原理及接口技術(shù)[M].北京:高等教育出版社,2004.
[4] 北京九思易自動(dòng)化軟件有限公司.易控(INSPEC)培訓(xùn)教程[M]. 2009.