• <tr id="yyy80"></tr>
  • <sup id="yyy80"></sup>
  • <tfoot id="yyy80"><noscript id="yyy80"></noscript></tfoot>
  • 99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

    IEC61131標(biāo)準(zhǔn)的結(jié)構(gòu)化文本語言解釋器設(shè)計(jì)

    2019-01-17 03:14:50,,,,
    關(guān)鍵詞:序號(hào)指令定義

    ,,,,

    (南京南瑞繼保電氣有限公司,南京 211102)

    引 言

    IEC61131是國際電工委員會(huì)(IEC)頒布的可編程控制器(PLC)國際標(biāo)準(zhǔn)[1-5],它可以規(guī)范工業(yè)控制系統(tǒng)平臺(tái)和應(yīng)用程序開發(fā),從而降低用戶的使用難度和維護(hù)成本[6]。IEC61131-3為軟件設(shè)計(jì)提供了標(biāo)準(zhǔn)化的編程概念和編程方法,定義了5種語言規(guī)范,國內(nèi)外工控廠家和科研機(jī)構(gòu)已經(jīng)開始提供基于該標(biāo)準(zhǔn)的產(chǎn)品并進(jìn)行了應(yīng)用[7-10]。參考文獻(xiàn)[7]介紹了嵌入式軟PLC系統(tǒng)的架構(gòu),設(shè)計(jì)了將IEC61131-3語言轉(zhuǎn)換為C語言的開發(fā)系統(tǒng)。參考文獻(xiàn)[8]提出一種將ST語言轉(zhuǎn)換為IL指令的方法,解決了ST語言語法分解和優(yōu)先級(jí)算法的相關(guān)問題。參考文獻(xiàn)[9]提出了基于指令向量表的軟PLC系統(tǒng)實(shí)現(xiàn)方法,實(shí)現(xiàn)了梯形圖指令的高效執(zhí)行。參考文獻(xiàn)[10]是本課題組的前期研究成果,介紹了結(jié)構(gòu)化文本的虛擬機(jī)指令架構(gòu)和編譯優(yōu)化方法。PLC系統(tǒng)編程指令的執(zhí)行方式有編譯型和解釋型方式。編譯型效率高,需要針對(duì)運(yùn)行的硬件環(huán)境開發(fā)專門的編譯器。解釋型執(zhí)行方式具有靈活性高、易于跨平臺(tái)移植的特點(diǎn),適用于在線無擾更新的應(yīng)用場(chǎng)景,但在實(shí)時(shí)性方面存在不足。針對(duì)參考文獻(xiàn)[10]開發(fā)的編譯器形成的二進(jìn)制虛擬機(jī)指令,設(shè)計(jì)了配套的上位機(jī)仿真用解釋器,本文介紹了一種高效解釋執(zhí)行的方案。

    1 解釋器設(shè)計(jì)

    1.1 指令格式設(shè)計(jì)

    本文在指令設(shè)計(jì)時(shí)參考了VCODE和CIL指令集的部分理念[10]:使執(zhí)行頻繁的部分保持高效,使其他部分保持正確。根據(jù)ST語言的規(guī)范和特性,支持可變形參,可內(nèi)置調(diào)用更豐富的庫函數(shù)接口。以算術(shù)運(yùn)算為例,在存儲(chǔ)時(shí)指令類型占用1字節(jié),指令存在二元運(yùn)算如add(rd,rs1,rs2)、一元運(yùn)算如not(rd,rs)、跳轉(zhuǎn)指令jmp(lab)、函數(shù)調(diào)用scall等模式。采用緊湊型存儲(chǔ),根據(jù)指令類型動(dòng)態(tài)輸出形參個(gè)數(shù)??紤]內(nèi)存對(duì)齊、方便快速掃描定位的前提下,內(nèi)存中三地址碼指令存儲(chǔ)格式定義如下:

    指令碼(2 Bytes)參數(shù)1(2 Bytes)參數(shù)2可選(2 Bytes)參數(shù)3可選(2 Bytes)

    存儲(chǔ)和讀取時(shí)根據(jù)指令類型動(dòng)態(tài)計(jì)算參數(shù)偏移,例如add指令為3個(gè)形參,not指令為2個(gè)形參。

    1.2 指令文件格式

    圖1 指令文件格式

    在上位機(jī)通過工具處理將ST/FBD/LD/SFC等類型的POU編譯形成解釋器側(cè)所需的指令文件,文件采用小端方式存儲(chǔ)。文件結(jié)構(gòu)如圖1所示,包括文件頭 、引用的外部變量信息區(qū)、POU變量區(qū)、常量區(qū)、臨時(shí)變量區(qū)、指令區(qū)、字符串池(變長(zhǎng)存儲(chǔ))、擴(kuò)展信息段等。

    圖中的變量區(qū)按照POU聲明的變量順序排列,即POU的輸入變量、輸出變量、輸入-輸出變量、中間變量。變量序號(hào)從0遞增,指令區(qū)的操作數(shù)記錄的是變量序號(hào),對(duì)于復(fù)雜結(jié)構(gòu)體采用深度優(yōu)先遍歷平鋪展開為基本變量類型的成員變量。

    1.3 關(guān)鍵數(shù)據(jù)結(jié)構(gòu)定義

    單個(gè)IEC61131定義的基本變量用IecVar結(jié)構(gòu)體表示,作為最小粒度的邏輯分區(qū)存儲(chǔ)單元,它有兩個(gè)子結(jié)構(gòu)體成員,為VAR_FLAG和VAR_VALUE。邏輯變量定義如圖2所示。

    圖2 邏輯變量定義

    VAR_FLAG是個(gè)2字節(jié)的結(jié)構(gòu)體,記錄變量下IEC61131定義的變量屬性:

    struct VAR_FLAG{

    ushort var_type: 5; //參照ST的標(biāo)準(zhǔn)定義

    ushort bretain: 1; //是否掉電保留

    ushort bnegate: 1; //是否取反,

    ushort bin_out: 1; //是否為輸入-輸出類型

    ushort bconst: 1; //是否為常量,寫保護(hù)

    ushort bredge: 1; //是否上升沿檢測(cè)

    ushort bfedge: 1; //是否下降沿檢測(cè)

    ushort bwrite_back: 1; //是否需要回寫

    ushort bupdate: 1; //更新位

    ushort resv : 3;

    };

    VAR_VALUE用于表示變量的值、字符串類型信息、時(shí)間類型變量信息,為枚舉結(jié)構(gòu):

    union LOGIC_VAR_VALUE{

    uint m_uint;

    int m_int;

    float m_float;

    USTR m_str; //字符串

    uint64 m_uint64;

    double m_double;

    IEC_TIME m_t;

    IEC_DATE m_date;

    …};

    其中字符串用4字節(jié)的結(jié)構(gòu)體表示,2字節(jié)表示長(zhǎng)度,2字節(jié)表示在字符串池中的起始位置。

    指令編碼定義如下:

    struct IRCode {

    OpType tp; //指令類型add/sub等

    ushort arg1; //通常是目的地址序號(hào)

    ushort arg2; //通常是源操作數(shù)序號(hào)1

    ushort arg3; //通常是源操作數(shù)序號(hào)2

    };

    指令運(yùn)行條目信息,存儲(chǔ)運(yùn)行中變量地址和關(guān)聯(lián)的指令執(zhí)行函數(shù),是運(yùn)行時(shí)調(diào)度的基本單位:

    struct IRItem{

    ushort idx; //指令序號(hào)

    uint parg1; //形參1對(duì)應(yīng)變量區(qū)變量地址

    uint parg2; //形參2對(duì)應(yīng)變量區(qū)變量地址

    uint parg3; //形參地址或立即數(shù)

    void (*irfunc)(IRItem* p); //指令執(zhí)行函數(shù)

    };

    指令文件類定義如下:

    class CMidFile {

    public:

    CMidFile(); ~CMidFile();

    public:

    MID_HEADER m_header; //文件頭

    QList m_externVarList; //外部變量區(qū)

    QList m_pouVarList; //POU數(shù)據(jù)區(qū)

    QList m_constVarList; //常量區(qū)

    QList m_tempVarList; //臨時(shí)變量區(qū)

    QList m_IRList; //指令數(shù)組

    QList m_strList;

    //存儲(chǔ)字符串列表

    …};

    解釋器在初始化時(shí),讀取指令文件,形成變量鏈表和指令數(shù)組。

    1.4 解釋器架構(gòu)設(shè)計(jì)

    根據(jù)控制器內(nèi)ST指令文件解析、執(zhí)行的流程,可將解釋器的功能結(jié)構(gòu)分為三個(gè)子模塊,如圖3所示。

    圖3 解釋器運(yùn)行模型

    初始化加載:對(duì)指令文件進(jìn)行初步解析,包括將緊湊排列的變量按照以IecVar為單位分配,方便數(shù)據(jù)信息的結(jié)構(gòu)化封裝以及索引定位。

    解釋執(zhí)行任務(wù):根據(jù)預(yù)處理后形成的內(nèi)存文件,對(duì)指令區(qū)的指令逐條解釋執(zhí)行,并讀取外部變量區(qū)和本地變量區(qū)的相關(guān)數(shù)據(jù)。

    數(shù)據(jù)刷新任務(wù):通過監(jiān)視接口對(duì)內(nèi)存文本中的數(shù)據(jù)進(jìn)行設(shè)置、觀測(cè),通過調(diào)試接口和調(diào)試符號(hào)表對(duì)指令區(qū)執(zhí)行過程進(jìn)行干預(yù)控制。

    1.5 初始化設(shè)計(jì)

    解釋器在初始化時(shí)讀取指令文件,先讀取文件頭,獲取各個(gè)變量區(qū)變量個(gè)數(shù)、指令個(gè)數(shù)等統(tǒng)計(jì)信息。之后依次讀取變量區(qū)、指令區(qū)、字符串池、調(diào)試表、擴(kuò)展信息區(qū)。為了節(jié)省空間,變量值VAR_VALUE在文件中存儲(chǔ)時(shí)按照實(shí)際類型大小存儲(chǔ),在讀取時(shí),需要根據(jù)變量類型動(dòng)態(tài)調(diào)整讀取的buf長(zhǎng)度,單個(gè)變量的讀取示例如下:

    CIecVar* pvar = new CIecVar(varIdx++);

    varList.append(pvar);

    getMemory(buf, &tmpoff, (uchar*)&pvar->flag, len1);

    switch( pvar->m_flag.var_type){

    case e_BOOL:

    case e_SINT:

    pvar->m_val.m_char = (char)getChar(buf, &tmpoff);

    break;

    case e_USINT:

    case e_BYTE:

    pvar->m_val.m_uchar = getChar(buf, &tmpoff);

    break;

    …}

    指令區(qū)解析根據(jù)指令類型解析若干形參,形成指令編碼如下:

    IRCode* pIR = new IRCode();

    m_IRList.append(pIR);

    pIR->tp = (OpType)getInt16(pbuf, &tmpoff);

    switch(pIR->tp){

    case e_add: //3個(gè)形參

    case e_div:

    pIR->arg1 = getInt16(pbuf, &tmpoff);

    pIR->arg2 = getInt16(pbuf, &tmpoff);

    pIR->arg3 = getInt16(pbuf, &tmpoff);

    break;

    case e_asgn: // 2個(gè)形參

    case e_not:

    pIR->arg1 = getInt16(pbuf, &tmpoff);

    pIR->arg2 = getInt16(pbuf, &tmpoff);

    break;

    case e_jmp:// 1個(gè)形參

    case e_lab:

    pIR->arg1 = getInt16(pbuf, &tmpoff);

    break;

    }

    在初始化過程中,通過如下處理為運(yùn)行時(shí)提高效率創(chuàng)造條件:

    ① 在讀取完變量區(qū)和指令區(qū)后,根據(jù)指令形參中記錄的變量區(qū)序號(hào),查找到動(dòng)態(tài)分配的IecVar變量的地址,形成IRItem條目結(jié)構(gòu),并根據(jù)指令類型關(guān)聯(lián)對(duì)應(yīng)的指令解析函數(shù)或系統(tǒng)庫函數(shù)指針,在初始化時(shí)完成數(shù)據(jù)形參、執(zhí)行函數(shù)的關(guān)聯(lián),實(shí)現(xiàn)初始化一次查找關(guān)聯(lián),執(zhí)行時(shí)直接使用轉(zhuǎn)換。圖4是add指令的形參和執(zhí)行函數(shù)的關(guān)聯(lián)過程。

    圖4 IRItem形成過程示例

    ② 創(chuàng)建lab標(biāo)號(hào)和指令序號(hào)的hash表,即QHashm_labelHash, 實(shí)現(xiàn)運(yùn)行shi跳轉(zhuǎn)指令快速跳轉(zhuǎn)到對(duì)應(yīng)的指令區(qū)域。

    1.6 運(yùn)行時(shí)設(shè)計(jì)

    根據(jù)ST語言的基本指令碼索引其函數(shù)指針數(shù)組,獲得對(duì)應(yīng)功能函數(shù)指針,傳入形參地址,進(jìn)行解釋執(zhí)行。對(duì)于系統(tǒng)庫函數(shù)指令碼的解釋執(zhí)行,首先定位scall指令,再根據(jù)其第一個(gè)形參值(系統(tǒng)庫函數(shù)的指令碼值)索引定位系統(tǒng)庫函數(shù)指令碼函數(shù)指針數(shù)組,獲取對(duì)應(yīng)功能函數(shù)指針,傳入在系統(tǒng)庫變量區(qū)的功能塊結(jié)構(gòu)體首地址,進(jìn)行解釋執(zhí)行。當(dāng)執(zhí)行到JZ、JMP等跳轉(zhuǎn)指令時(shí),將當(dāng)前執(zhí)行的指令數(shù)組下標(biāo)修改為跳轉(zhuǎn)指令記錄的跳轉(zhuǎn)目的標(biāo)號(hào),之后順序執(zhí)行從新下標(biāo)起始對(duì)應(yīng)的指令。由于初始化過程中已經(jīng)根據(jù)指令類型設(shè)置了對(duì)應(yīng)的執(zhí)行函數(shù)指針,故運(yùn)行過程中不需要進(jìn)行指令類型判斷,順次執(zhí)行即可:

    void CInterpreter:::execIRList(){

    readInput(); //刷新外部輸入

    m_curpos = 0;

    m_it =m_IRList.begin();

    while(m_curpos

    IRItem* pitem =*m_it;

    if(pitem->irfunc ) pitem->irfunc(pitem);

    ++m_it;

    ++m_curpos; }

    writeOutput(); //將值更新到輸出

    }

    其中跳轉(zhuǎn)指令執(zhí)行函數(shù)的作用是動(dòng)態(tài)調(diào)整當(dāng)前指令游標(biāo)m_it、m_curpos,從而間接修改主函數(shù)while循環(huán)中下次運(yùn)行的起始位置,實(shí)現(xiàn)指令數(shù)組順次執(zhí)行可跳轉(zhuǎn)的功能:

    inline exec_jmp(IRItem* p){

    ushort label = (ushort)p->arg1;

    QHash::Iterator it;

    it = m_labelHash.find(label);

    if(it!=m_labelHash.end()){

    //動(dòng)態(tài)調(diào)整當(dāng)前下標(biāo)到跳轉(zhuǎn)的標(biāo)簽處

    int labpos = (int)it.value();

    m_it += labpos-m_curpos;

    m_curpos = labpos;

    }

    }

    結(jié) 語

    猜你喜歡
    序號(hào)指令定義
    聽我指令:大催眠術(shù)
    ARINC661顯控指令快速驗(yàn)證方法
    LED照明產(chǎn)品歐盟ErP指令要求解讀
    技術(shù)指標(biāo)選股
    技術(shù)指標(biāo)選股
    技術(shù)指標(biāo)選股
    技術(shù)指標(biāo)選股
    成功的定義
    山東青年(2016年1期)2016-02-28 14:25:25
    坐標(biāo)系旋轉(zhuǎn)指令數(shù)控編程應(yīng)用
    修辭學(xué)的重大定義
    灵宝市| 澄城县| 伊宁市| 秦皇岛市| 会东县| 运城市| 诸暨市| 浦东新区| 曲沃县| 桓仁| 石台县| 龙井市| 岱山县| 会理县| 隆德县| 开封县| 颍上县| 正蓝旗| 南通市| 时尚| 海盐县| 藁城市| 康保县| 铜陵市| 烟台市| 保康县| 苏尼特左旗| 禹州市| 门头沟区| 巴楚县| 山东省| 宝鸡市| 胶州市| 江油市| 巧家县| 晋江市| 黎城县| 赤峰市| 澄迈县| 睢宁县| 治多县|