《電子技術(shù)應(yīng)用》
您所在的位置:首頁(yè) > 嵌入式技術(shù) > 設(shè)計(jì)應(yīng)用 > 基于易控的51系列單片機(jī)通用驅(qū)動(dòng)程序設(shè)計(jì)
基于易控的51系列單片機(jī)通用驅(qū)動(dòng)程序設(shè)計(jì)
來(lái)源:電子技術(shù)應(yīng)用2011年第11期
李建平, 鄭 萍, 葉建平, 陶 平, 溫百東, 朱光燦
(西華大學(xué) 電氣信息學(xué)院, 四川 成都610039)
摘要: 設(shè)計(jì)了一種基于易控(INSPEC)組態(tài)軟件的51單片機(jī)外部設(shè)備的通用驅(qū)動(dòng)程序,以解決基于51單片機(jī)的底層設(shè)備驅(qū)動(dòng)問(wèn)題。該通用驅(qū)動(dòng)程序通過(guò)電壓監(jiān)測(cè)儀表進(jìn)行了應(yīng)用調(diào)試,證明了該驅(qū)動(dòng)程序?qū)嵱靡仔?,并為其他的設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)提供了設(shè)計(jì)思路和程序框架。
中圖分類(lèi)號(hào): TP273
文獻(xiàn)標(biāo)識(shí)碼: A
文章編號(hào): 0258-7998(2011)11-0144-03
Design of general driver for the 51 series MCU based on the INSPEC
Li Jianping, Zheng Ping, Ye Jianping, Tao Ping, Wen Baidong, Zhu Guangcan
School of Electrical and Information Engineering, Xihua University, Chengdu 610039, China
Abstract: A general device driver was designed based on the INSPEC which extremely widespread application of 51 series MCU, in order to solve the underlying driver problems of 51 series MCU . The driver was debugged by using the infrared Remote voltage monitoring instrument. The result proved that the driver is practical and feasible, and has provided the design ideas and the program frame for the design of general device driver.
Key words : data communication; INSPEC; configuration software;MCU; driver


    目前,工業(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變量具有&ldquo;只寫(xiě)/讀寫(xiě)&rdquo;屬性,并且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)擊&ldquo;下一步&rdquo;進(jìn)行設(shè)備的選擇,編寫(xiě)好的設(shè)備驅(qū)動(dòng)&ldquo;單片機(jī)通用設(shè)備&rdquo;已經(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)擊&ldquo;完成&rdquo;即建好通道。

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.

此內(nèi)容為AET網(wǎng)站原創(chuàng),未經(jīng)授權(quán)禁止轉(zhuǎn)載。