Esempio n. 1
0
        /// <summary>
        /// 根据指令文本构造指令结构,并加入列表中
        /// </summary>
        /// <param name="insts">指令列表</param>
        /// <param name="inst">指令文本</param>
        static public void AddInst(List <PLCInstruction> insts, string text, int id = -1)
        {
            PLCInstruction inst = new PLCInstruction(text);

            inst.PrototypeID = id;
            insts.Add(inst);
        }
Esempio n. 2
0
 /// <summary>
 /// 将指令转换为表达式
 /// </summary>
 /// <param name="inst">指令结构</param>
 /// <returns>表达式</returns>
 static public string ToExpr(PLCInstruction inst)
 {
     throw new NotImplementedException();
 }
Esempio n. 3
0
        static public void InstToCCode(StreamWriter sw, PLCInstruction inst, bool simumode = false)
        {
            int bp = 0;

            // 如果是仿真模式
            if (simumode)
            {
                // 断点循环
                if (inst.ProtoType != null)
                {
                    BreakPointManager.Register(inst.ProtoType);
                    bp = inst.ProtoType.BPAddress;
                    sw.Write("bpcycle({0});\n", bp);
                }
                // 需要由写入使能作为条件
                if (inst.EnBit != null && inst.EnBit.Length > 0)
                {
                    sw.Write("if (!({0:s})) \n{{\n", inst.EnBit);
                }
            }
            // 当前指令为LD类指令,记录栈内当前位置的合并方式
            if (inst.StackCalc != null)
            {
                stackcalcs[stackTop] = inst.StackCalc;
            }
            // 第一次判断指令类型
            switch (inst.Type)
            {
            // 一般的入栈和逻算
            case "LD":
            case "LDIM":     sw.Write("_stack_{0:d} = {1:s};\n", ++stackTop, inst[1]); break;

            case "AND":
            case "ANDIM":   sw.Write("_stack_{0:d} &= {1:s};\n", stackTop, inst[1]); break;

            case "OR":
            case "ORIM":     sw.Write("_stack_{0:d} |= {1:s};\n", stackTop, inst[1]); break;

            case "LDI":
            case "LDIIM":   sw.Write("_stack_{0:d} = !{1:s};\n", ++stackTop, inst[1]); break;

            case "ANDI":
            case "ANDIIM": sw.Write("_stack_{0:d} &= !{1:s};\n", stackTop, inst[1]); break;

            case "ORI":
            case "ORIIM":   sw.Write("_stack_{0:d} |= !{1:s};\n", stackTop, inst[1]); break;

            // 上升沿和下降沿

            /*
             * 这里需要将上一次扫描的当前值记录下来,保存到全局变量中
             * 上次扫描的值为0,而这次扫描的值为1,代表上升沿的跳变
             * 上次扫描的值为1,而这次扫描的值为0,代表下降沿的跳变
             */
            case "LDP":
                sw.Write("_stack_{0:d} = (_global[{1:d}]==0&&{2:s}==1);\n", ++stackTop, globalCount, inst[1]);
                sw.Write("_global[{0:d}] = {1:s};\n", globalCount++, inst[1]);
                break;

            case "LDF":
                sw.Write("_stack_{0:d} = (_global[{1:d}]==1&&{2:s}==0);\n", ++stackTop, globalCount, inst[1]);
                sw.Write("_global[{0:d}] = {1:s};\n", globalCount++, inst[1]);
                break;

            case "ANDP":
                sw.Write("_stack_{0:d} &= (_global[{1:d}]==0&&{2:s}==1);\n", stackTop, globalCount, inst[1]);
                sw.Write("_global[{0:d}] = {1:s};\n", globalCount++, inst[1]);
                break;

            case "ANDF":
                sw.Write("_stack_{0:d} &= (_global[{1:d}]==1&&{2:s}==0);\n", stackTop, globalCount, inst[1]);
                sw.Write("_global[{0:d}] = {1:s};\n", globalCount++, inst[1]);
                break;

            case "ORP":
                sw.Write("_stack_{0:d} &= (_global[{1:d}]==0&&{2:s}==1);\n", stackTop, globalCount, inst[1]);
                sw.Write("_global[{0:d}] = {1:s};\n", globalCount++, inst[1]);
                break;

            case "ORF":
                sw.Write("_stack_{0:d} &= (_global[{1:d}]==1&&{2:s}==0);\n", stackTop, globalCount, inst[1]);
                sw.Write("_global[{0:d}] = {1:s};\n", globalCount++, inst[1]);
                break;

            case "INV":
                _CalcSignal(sw);
                sw.Write("_stack_{0:d} = _global[{1:d}]^1;\n", stackTop, globalCount - 1);
                break;

            case "MEP":
                _CalcSignal(sw);
                sw.Write("_stack_{0:d} = (_global[{1:d}]==0&&_global[{2:d}]==1);\n", stackTop, globalCount, globalCount - 1);
                sw.Write("_global[{0:d}] = _global[{1:d}];\n", globalCount, globalCount - 1);
                globalCount++;
                break;

            case "MEF":
                _CalcSignal(sw);
                sw.Write("_stack_{0:d} = (_global[{1:d}]==1&&_global[{2:d}]==0);\n", stackTop, globalCount, globalCount - 1);
                sw.Write("_global[{0:d}] = _global[{1:d}];\n", globalCount, globalCount - 1);
                globalCount++;
                break;

            // 出栈
            case "POP": stackTop--; break;

            // 栈合并
            case "ANDB":
                sw.Write("_stack_{0:d} &= _stack_{1:d};\n", stackTop - 1, stackTop);
                stackTop--;
                break;

            case "ORB":
                sw.Write("_stack_{0:d} |= _stack_{1:d};\n", stackTop - 1, stackTop);
                stackTop--;
                break;

            // 比较两个数是否相等
            case "LDWEQ":
            case "LDDEQ":
            case "LDFEQ":
                sw.Write("_stack_{0:d} = ({1:s}=={2:s});\n", ++stackTop, inst[1], inst[2]); break;

            case "AWEQ":
            case "ADEQ":
            case "AFEQ":
                sw.Write("_stack_{0:d} &= ({1:s}=={2:s});\n", stackTop, inst[1], inst[2]); break;

            case "ORWEQ":
            case "ORDEQ":
            case "ORFEQ":
                sw.Write("_stack_{0:d} |= ({1:s}=={2:s});\n", stackTop, inst[1], inst[2]); break;

            // 比较两个数是否不相等
            case "LDWNE":
            case "LDDNE":
            case "LDFNE":
                sw.Write("_stack_{0:d} = ({1:s}!={2:s});\n", ++stackTop, inst[1], inst[2]); break;

            case "AWNE":
            case "ADNE":
            case "AFNE":
                sw.Write("_stack_{0:d} &= ({1:s}!={2:s});\n", stackTop, inst[1], inst[2]); break;

            case "ORWNE":
            case "ORDNE":
            case "ORFNE":
                sw.Write("_stack_{0:d} |= ({1:s}!={2:s});\n", stackTop, inst[1], inst[2]); break;

            // 比较前数是否大等后数
            case "LDWGE":
            case "LDDGE":
            case "LDFGE":
                sw.Write("_stack_{0:d} = ({1:s}>={2:s});\n", ++stackTop, inst[1], inst[2]); break;

            case "AWGE":
            case "ADGE":
            case "AFGE":
                sw.Write("_stack_{0:d} &= ({1:s}>={2:s});\n", stackTop, inst[1], inst[2]); break;

            case "ORWGE":
            case "ORDGE":
            case "ORFGE":
                sw.Write("_stack_{0:d} |= ({1:s}>={2:s});\n", stackTop, inst[1], inst[2]); break;

            // 比较前数是否小等后数
            case "LDWLE":
            case "LDDLE":
            case "LDFLE":
                sw.Write("_stack_{0:d} = ({1:s}<={2:s});\n", ++stackTop, inst[1], inst[2]); break;

            case "AWLE":
            case "ADLE":
            case "AFLE":
                sw.Write("_stack_{0:d} &= ({1:s}<={2:s});\n", stackTop, inst[1], inst[2]); break;

            case "ORWLE":
            case "ORDLE":
            case "ORFLE":
                sw.Write("_stack_{0:d} |= ({1:s}<={2:s});\n", stackTop, inst[1], inst[2]); break;

            // 比较前数是否大于后数
            case "LDWG":
            case "LDDG":
            case "LDFG":
                sw.Write("_stack_{0:d} = ({1:s}>{2:s});\n", ++stackTop, inst[1], inst[2]); break;

            case "AWG":
            case "ADG":
            case "AFG":
                sw.Write("_stack_{0:d} &= ({1:s}>{2:s});\n", stackTop, inst[1], inst[2]); break;

            case "ORWG":
            case "ORDG":
            case "ORFG":
                sw.Write("_stack_{0:d} |= ({1:s}>{2:s});\n", stackTop, inst[1], inst[2]); break;

            // 比较前数是否小于后数
            case "LDWL":
            case "LDDL":
            case "LDFL":
                sw.Write("_stack_{0:d} = ({1:s}<{2:s});\n", ++stackTop, inst[1], inst[2]); break;

            case "AWL":
            case "ADL":
            case "AFL":
                sw.Write("_stack_{0:d} &= ({1:s}<{2:s});\n", stackTop, inst[1], inst[2]); break;

            case "ORWL":
            case "ORDL":
            case "ORFL":
                sw.Write("_stack_{0:d} |= ({1:s}<{2:s});\n", stackTop, inst[1], inst[2]); break;

            // 输出线圈

            /*
             * 将当前栈顶的值赋值给线圈
             */
            case "OUT":
            case "OUTIM":
                sw.Write("{0:s} = _stack_{1:d};\n", inst[1], stackTop); break;

            // 置位和复位

            /*
             * 需要用if来判断栈顶是否为1
             */
            case "SET":
            case "SETIM":
                if (simumode)
                {
                    sw.Write("if (_stack_{0:d}) _bitset(&{1:s}, &{3:s}, {2:s});\n",
                             stackTop, inst[1], inst[2], inst.EnBit);
                }
                else
                {
                    sw.Write("if (_stack_{0:d}) _bitset(&{1:s}, {2:s});\n",
                             stackTop, inst[1], inst[2]);
                }
                break;

            case "RST":
            case "RSTIM":
                if (simumode)
                {
                    sw.Write("if (_stack_{0:d}) {{\n_bitrst(&{1:s}, &{3:s}, {2:s});\n",
                             stackTop, inst[1], inst[2], inst.EnBit);
                }
                else
                {
                    sw.Write("if (_stack_{0:d}) {{\n_bitrst(&{1:s}, {2:s});\n",
                             stackTop, inst[1], inst[2]);
                }

                /*
                 * 注意如果复位的是计数器位,那么计数器值也要跟着复原
                 * 考虑到向下计数器(CTD)复原时需要载入预设值
                 * 所以每个计数器预设值都要存起来便于访问
                 * 预设值需要在外部先初始化
                 */
                if (inst[1][0] == 'C')
                {
                    int begin = int.Parse(inst[3]);
                    int end   = begin + int.Parse(inst[4]);
                    for (int i = begin; i < end; i++)
                    {
                        sw.Write("CVWord[{0:d}] = {1:d};", i, ctsv[i]);
                    }
                }
                sw.Write("}\n");
                break;

            // 交替
            case "ALT": sw.Write("if (_stack_{0:d}) {1:s}=({1:s} ? 0 : 1);\n", stackTop, inst[1]); break;

            // 上升沿交替
            case "ALTP":
                sw.Write("if (_global[{0:d}]==0 && _stack_{1:d}==1) {2:s}=({2:s} ? 0 : 1);\n", globalCount, stackTop, inst[1]);
                sw.Write("_global[{0:d}] = _stack_{1:d};\n", globalCount++, stackTop);
                break;

            // 当栈顶为1时运行的计时器
            case "TON":
                if (simumode)
                {
                    sw.Write("_ton(_stack_{0:d}, {1:s}, {2:s}, &_global[{3:d}]);\n",
                             stackTop, inst[1], inst[2], globalCount);
                }
                else
                {
                    sw.Write("CI_TON(_stack_{0:d}, {1:s}, {2:s});\n",
                             stackTop, inst[1], inst[2]);
                }
                globalCount += 1;
                break;

            // 当栈顶为0时运行的计时器
            case "TOF":
                if (simumode)
                {
                    sw.Write("_ton(!_stack_{0:d}, {1:s}, {2:s}, &_global[{3:d}]);\n",
                             stackTop, inst[1], inst[2], globalCount);
                }
                else
                {
                    sw.Write("CI_TON(!_stack_{0:d}, {1:s}, {2:s});\n",
                             stackTop, inst[1], inst[2]);
                }
                globalCount += 1;
                break;

            // 当栈顶为1时运行,为0时保留当前计时的计时器
            case "TONR":
                if (simumode)
                {
                    sw.Write("_tonr(_stack_{0:d}, {1:s}, {2:s}, &_global[{3:d}]);\n",
                             stackTop, inst[1], inst[2], globalCount);
                }
                else
                {
                    sw.Write("CI_TON(_stack_{0:d}, {1:s}, {2:s});\n",
                             stackTop, inst[1], inst[2]);
                }
                globalCount += 1;
                break;

            // 向上计数器,每次栈顶上升跳变时加1
            // 当计数到达目标后计数开关设为1
            case "CTU":
                sw.Write("if (_global[{0:d}]==0 && _stack_{1:d}==1 && !{2:s})\n", globalCount, stackTop, inst[3]);
                sw.Write("if (++{0:s}>={1:s}) {2:s} = 1;\n", inst[1], inst[2], inst[3]);
                sw.Write("_global[{0:d}] = _stack_{1:d};\n", globalCount++, stackTop);
                break;

            // 向下计数器
            case "CTD":
                sw.Write("if (_global[{0:d}]==0 && _stack_{1:d}==1 && !{2:s})\n", globalCount, stackTop, inst[3]);
                sw.Write("if (--{0:s}<={1:s}) {2:s} = 1;\n", inst[1], inst[2], inst[3]);
                sw.Write("_global[{0:d}] = _stack_{1:d};\n", globalCount++, stackTop);
                break;

            // 向上向下计数器,当当前计数小于目标则加1,大于目标则减1
            case "CTUD":
                sw.Write("if (_global[{0:d}]==0 && _stack_{1:d}==1 && !{2:s})\n", globalCount, stackTop, inst[3]);
                sw.Write("if (({0:s}<{1:s}?++{0:s}:--{0:s})=={1:s}) {2:s} = 1;\n", inst[1], inst[2], inst[3]);
                sw.Write("_global[{0:d}] = _stack_{1:d};\n", globalCount++, stackTop);
                break;

            // FOR循环指令,和c的for循环保持一致

            /*
             * 之前需要保证FOR和NEXT之间的NETWORK已经合并到了一起
             * 这样才能符合c语言的括号逻辑
             * 不难发现,这里的for后面多了一个左括号,这是专门为了后面的NEXT指令准备的
             */
            case "FOR":
                sw.Write("if (_stack_{0:d}) \n", stackTop);
                sw.Write("for (_global[{0:d}]=0;_global[{0:d}]<{1:s};_global[{0:d}]++) {{\n", globalCount++, inst[1]);
                break;

            // NEXT指令,结束前面的FOR循环
            case "NEXT":
                sw.Write("}\n");
                break;

            // JMP指令,跳转到指定的标签处

            /*
             * 这里和FOR一样,要保证跳转到的标签在同一函数中
             * 因为这里跳转是用c语言对应的goto功能来实现的
             */
            case "JMP":
                sw.Write("if (_stack_{0:d}) \n", stackTop);
                sw.Write("goto LABEL_{0:s};\n", globalCount++, inst[1]);
                break;

            // LBL指令,设置跳转标签
            case "LBL":
                sw.Write("LABEL_{0:s} : \n", inst[1]);
                break;

            // 辅助栈操作
            case "MPS": sw.Write("_mstack_{0:d} = _stack_{1:d};\n", ++mstackTop, stackTop); break;

            case "MRD": sw.Write("_stack_{0:d} = _mstack_{1:d};\n", stackTop, mstackTop); break;

            case "MPP": sw.Write("_stack_{0:d} = _mstack_{1:d};\n", stackTop, mstackTop--); break;

            // 可能会调用到下位接口的指令
            case "PLSF":
            case "DPLSF":
                if (!simumode)
                {
                    sw.Write("CI_DPLSF((uint8_t)(_stack_{0:d}),(uint32_t)({1:s}),{2:s}, {3:d});\n",
                             stackTop, inst[1], inst[2], user_id);
                }
                break;

            case "PWM":
            case "DPWM":
                if (!simumode)
                {
                    sw.Write("CI_DPWM((uint8_t)(_stack_{0:d}),(uint32_t)({1:s}),(uint32_t)({2:s}),{3:s},{4:d});\n",
                             stackTop, inst[1], inst[2], inst[3], user_id);
                }
                break;

            case "PLSY":
            case "DPLSY":
                if (!simumode)
                {
                    sw.Write("CI_DPLSY((uint8_t)(_stack_{0:d}),(uint32_t)({1:s}),(uint32_t)({2:s}),{3:s},{4:d});\n",
                             stackTop, inst[1], inst[2], inst[3], user_id);
                }
                break;

            case "HCNT":
                if (!simumode)
                {
                    sw.Write("CI_HCNT((uint8_t)(_stack_{0:d}),{1:s},{2:s});\n",
                             stackTop, inst[1], inst[2]);
                }
                break;

            // 默认的其他情况,一般之前要先判断栈顶
            default:
                sw.Write("if (_stack_{0:d}) {{\n", stackTop);
                // 第二回指令判断
                switch (inst.Type)
                {
                // 数据格式的转化指令
                case "WTOD": sw.Write("{1:s} = _WORD_to_DWORD({0:s});\n", inst[1], inst[2]); break;

                case "DTOW": sw.Write("{1:s} = _DWORD_to_WORD({0:s});\n", inst[1], inst[2]); break;

                case "DTOF": sw.Write("{1:s} = _DWORD_to_FLOAT({0:s});\n", inst[1], inst[2]); break;

                case "BIN": sw.Write("{1:s} = _BCD_to_WORD({0:s});\n", inst[1], inst[2]); break;

                case "BCD": sw.Write("{1:s} = _WORD_to_BCD({0:s});\n", inst[1], inst[2]); break;

                case "ROUND": sw.Write("{1:s} = _FLOAT_to_ROUND({0:s});\n", inst[1], inst[2]); break;

                case "TRUNC": sw.Write("{1:s} = _FLOAT_to_TRUNC({0:s});\n", inst[1], inst[2]); break;

                // 位运算指令
                case "INVW":
                case "INVD": sw.Write("{1:s} = ~{0:s};\n", inst[1], inst[2]); break;

                case "ANDW":
                case "ANDD": sw.Write("{2:s} = {0:s}&{1:s}", inst[1], inst[2], inst[3]); break;

                case "ORW":
                case "ORD": sw.Write("{2:s} = {0:s}|{1:s}", inst[1], inst[2], inst[3]); break;

                case "XORW":
                case "XORD": sw.Write("{2:s} = {0:s}^{1:s}", inst[1], inst[2], inst[3]); break;

                // 寄存器移动指令
                case "MOV":
                case "MOVD":
                case "MOVF": sw.Write("{1:s} = {0:s};\n", inst[1], inst[2]); break;

                case "MVBLK":
                    if (simumode)
                    {
                        sw.Write("_mvwblk(&{0:s}, &{1:s}, &{3:s}, {2:s});\n", inst[1], inst[2], inst[3], inst.EnBit);
                    }
                    else
                    {
                        sw.Write("_mvwblk(&{0:s}, &{1:s}, {2:s});\n", inst[1], inst[2], inst[3]);
                    }
                    break;

                case "MVDBLK":
                    if (simumode)
                    {
                        sw.Write("_mvdblk(&{0:s}, &{1:s}, &{3:s}, {2:s});\n", inst[1], inst[2], inst[3], inst.EnBit);
                    }
                    else
                    {
                        sw.Write("_mvdblk(&{0:s}, &{1:s}, {2:s});\n", inst[1], inst[2], inst[3]);
                    }
                    break;

                // 数学运算指令
                case "ADD": sw.Write("{2:s} = _addw({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "ADDD": sw.Write("{2:s} = _addd({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "ADDF": sw.Write("{2:s} = _addf({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "SUB": sw.Write("{2:s} = _subw({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "SUBD": sw.Write("{2:s} = _subd({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "SUBF": sw.Write("{2:s} = _subf({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "MUL": sw.Write("{2:s} = _mulwd({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "MULW": sw.Write("{2:s} = _mulww({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "MULD": sw.Write("{2:s} = _muldd({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "MULF": sw.Write("{2:s} = _mulff({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "DIV": sw.Write("{2:s} = _divwd({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "DIVW": sw.Write("{2:s} = _divww({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "DIVD": sw.Write("{2:s} = _divdd({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "DIVF": sw.Write("{2:s} = _divff({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "INC": sw.Write("{1:s} = _incw({0:s});\n", inst[1], inst[2]); break;

                case "INCD": sw.Write("{1:s} = _incd({0:s});\n", inst[1], inst[2]); break;

                case "DEC": sw.Write("{1:s} = _decw({0:s});\n", inst[1], inst[2]); break;

                case "DECD": sw.Write("{1:s} = _decw({0:s});\n", inst[1], inst[2]); break;

                case "SIN": sw.Write("{1:s} = _sin({0:s});\n", inst[1], inst[2]); break;

                case "COS": sw.Write("{1:s} = _cos({0:s});\n", inst[1], inst[2]); break;

                case "TAN": sw.Write("{1:s} = _tan({0:s});\n", inst[1], inst[2]); break;

                case "LN": sw.Write("{1:s} = _ln({0:s});\n", inst[1], inst[2]); break;

                case "EXP": sw.Write("{1:s} = _exp({0:s});\n", inst[1], inst[2]); break;

                // 移位指令
                case "SHL": sw.Write("{2:s} = _shlw({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "SHLD": sw.Write("{2:s} = _shld({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "SHR": sw.Write("{2:s} = _shrw({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "SHRD": sw.Write("{2:s} = _shrd({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "ROL": sw.Write("{2:s} = _rolw({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "ROR": sw.Write("{2:s} = _rorw({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "ROLD": sw.Write("{2:s} = _rold({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "RORD": sw.Write("{2:s} = _rord({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "SHLB":
                    if (simumode)
                    {
                        sw.Write("_bitshl(&{0:s}, &{1:s}, &{4:s}, {2:s}, {3:s});\n", inst[1], inst[2], inst[3], inst[4], inst.EnBit);
                    }
                    else
                    {
                        sw.Write("_bitshl(&{0:s}, &{1:s}, {2:s}, {3:s});\n", inst[1], inst[2], inst[3], inst[4]);
                    }
                    break;

                case "SHRB":
                    if (simumode)
                    {
                        sw.Write("_bitshr(&{0:s}, &{1:s}, &{4:s}, {2:s}, {3:s});\n", inst[1], inst[2], inst[3], inst[4], inst.EnBit);
                    }
                    else
                    {
                        sw.Write("_bitshr(&{0:s}, &{1:s}, {2:s}, {3:s});\n", inst[1], inst[2], inst[3], inst[4]);
                    }
                    break;

                // 辅助功能
                case "LOG": sw.Write("{1:s} = _log({0:s});\n", inst[1], inst[2]); break;

                case "POW": sw.Write("{2:s} = _pow({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "FACT": sw.Write("{1:s} = _fact({0:s});\n", inst[1], inst[2]); break;

                case "SQRT": sw.Write("{1:s} = _sqrt({0:s});\n", inst[1], inst[2]); break;

                case "CMP":  sw.Write("{2:s} = _cmpw({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "CMPD": sw.Write("{2:s} = _cmpd({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "CMPF": sw.Write("{2:s} = _cmpf({0:s}, {1:s});\n", inst[1], inst[2], inst[3]); break;

                case "ZCP": sw.Write("{3:s} = _zcpw({0:s}, {1:s}, {2:s});\n", inst[1], inst[2], inst[3], inst[4]); break;

                case "ZCPD": sw.Write("{3:s} = _zcpd({0:s}, {1:s}, {2:s});\n", inst[1], inst[2], inst[3], inst[4]); break;

                case "ZCPF": sw.Write("{3:s} = _zcpf({0:s}, {1:s}, {2:s});\n", inst[1], inst[2], inst[3], inst[4]); break;

                case "NEG": sw.Write("{1:s} = _negw({0:s});\n", inst[1], inst[2]); break;

                case "NEGD": sw.Write("{1:s} = _negd({0:s});\n", inst[1], inst[2]); break;

                case "XCH": sw.Write("_xch(&{0:s}, &{1:s});\n", inst[1], inst[2]); break;

                case "XCHD": sw.Write("_xchd(&{0:s}, &{1:s});\n", inst[1], inst[2]); break;

                case "XCHF": sw.Write("_xchf(&{0:s}, &{1:s});\n", inst[1], inst[2]); break;

                case "CML": sw.Write("{1:s} = _cmlw({0:s});\n", inst[1], inst[2]); break;

                case "CMLD": sw.Write("{1:s} = _cmld({0:s});\n", inst[1], inst[2]); break;

                case "FMOV":
                    if (simumode)
                    {
                        sw.Write("_fmovw({0:s}, &{1:s}, &{3:s}, {2:s});\n", inst[1], inst[2], inst[3], inst.EnBit);
                    }
                    else
                    {
                        sw.Write("_fmovw({0:s}, &{1:s}, {2:s});\n", inst[1], inst[2], inst[3]);
                    }
                    break;

                case "FMOVD":
                    if (simumode)
                    {
                        sw.Write("_fmovd({0:s}, &{1:s}, &{3:s}, {2:s});\n", inst[1], inst[2], inst[3], inst.EnBit);
                    }
                    else
                    {
                        sw.Write("_fmovd({0:s}, &{1:s}, {2:s});\n", inst[1], inst[2], inst[3]);
                    }
                    break;

                case "SMOV": sw.Write("_smov({0:s}, {1:s}, {2:s}, &{3:s}, {4:s});\n", inst[1], inst[2], inst[3], inst[4], inst[5]); break;

                // CALL指令,调用子函数
                case "CALL":
                    sw.Write("_SBR_{0:s}();\n", inst[1]);
                    break;

                // CALLM指令,调用用户实现的c语言宏指令,根据参数数量的不同表现为不同的格式
                case "CALLM":
                    // 无参数的函数
                    if (inst[2].Equals(String.Empty))
                    {
                        sw.Write("{0:s}();", inst[1]);
                    }
                    // 至少存在一个参数
                    else
                    {
                        sw.Write("{0:s}({1:s}", inst[1], inst[2]);
                        for (int i = 3; i < 6; i++)
                        {
                            if (inst[i].Equals(String.Empty))
                            {
                                break;
                            }
                            sw.Write(",{0:s}", inst[i]);
                        }
                        sw.Write(");\n");
                    }
                    break;

                // 中断
                case "ATCH":
                    sw.Write("_atch({0:s}, _SBR_{1:s});\n", inst[1], inst[2]);
                    break;

                case "DTCH":
                    sw.Write("_dtch({0:s}, _SBR_{1:s});\n", inst[1], inst[2]);
                    break;

                case "EI":
                    sw.Write("_ei();\n");
                    break;

                case "DI":
                    sw.Write("_di();\n");
                    break;

                // 实时时钟
                case "TRD":
                    sw.Write("_trd(&{0:s});\n", inst[1]);
                    break;

                case "TWR":
                    sw.Write("_twr(&{0:s});\n", inst[1]);
                    break;

                // 通信
                case "MBUS":
                    sw.Write("_mbus({0:s}, NULL, 0, &{1:s});\n", inst[1], inst[3]);
                    break;

                case "SEND":
                    sw.Write("_send({0:s}, {1:s}, {2:s});\n", inst[1], inst[2], inst[3]);
                    break;

                case "REV":
                    sw.Write("_rev({0:s}, {1:s}, {2:s});\n", inst[1], inst[2], inst[3]);
                    break;

                // 脉冲
                case "PLSF":
                    sw.Write("_plsf({0:s}, &{1:s});\n", inst[1], inst[2]);
                    break;

                case "DPLSF":
                    sw.Write("_dplsf({0:s}, &{1:s});\n", inst[1], inst[2]);
                    break;

                case "PWM":
                    sw.Write("_pwm({0:s}, {1:s}, &{2:s});\n", inst[1], inst[2], inst[3]);
                    break;

                case "DPWM":
                    sw.Write("_dpwm({0:s}, {1:s}, &{2:s});\n", inst[1], inst[2], inst[3]);
                    break;

                case "PLSY":
                    sw.Write("_plsy({0:s}, &{1:s}, &{2:s});\n", inst[1], inst[2], inst[3]);
                    break;

                case "DPLSY":
                    sw.Write("_dplsy({0:s}, &{1:s}, &{2:s};\n", inst[1], inst[2], inst[3]);
                    break;

                case "PLSR":
                    sw.Write("_plsr(&{0:s}, {1:s}, &{2:s});\n", inst[1], inst[2], inst[3]);
                    break;

                case "DPLSR":
                    sw.Write("_dplsr(&{0:s}, {1:s}, &{2:s});\n", inst[1], inst[2], inst[3]);
                    break;

                case "PLSRD":
                    sw.Write("_plsrd(&{0:s}, {1:s}, &{2:s});\n", inst[1], inst[2], inst[3]);
                    break;

                case "DPLSRD":
                    sw.Write("_dplsrd(&{0:s}, {1:s}, &{2:s});\n", inst[1], inst[2], inst[3]);
                    break;

                case "PLSNEXT":
                    sw.Write("_plsnext(&{0:s});\n", inst[1]);
                    break;

                case "PLSSTOP":
                    sw.Write("_plsstop(&{0:s});\n", inst[1]);
                    break;

                case "ZRN":
                    sw.Write("_zrn({0:s}, {1:s}, {2:s}, &{3:s});\n", inst[1], inst[2], inst[3], inst[4]);
                    break;

                case "DZRN":
                    sw.Write("_dzrn({0:s}, {1:s}, {2:s}, &{3:s});\n", inst[1], inst[2], inst[3], inst[4]);
                    break;

                case "PTO":
                    sw.Write("_pto(&{0:s}, &{1:s}, &{2:s});\n", inst[1], inst[2], inst[3]);
                    break;

                case "DRVI":
                    sw.Write("_drvi({0:s}, {1:s}, &{2:s});\n", inst[1], inst[2], inst[3]);
                    break;

                case "DDRVI":
                    sw.Write("_ddrvi({0:s}, {1:s}, &{2:s});\n", inst[1], inst[2], inst[3]);
                    break;

                case "HCNT":
                    sw.Write("_hcnt(&{0:s}, {1:s});\n", inst[1], inst[2]);
                    break;

                // 移位操作
                default: throw new ArgumentException(String.Format("unidentified PLC command : {0:s}", inst.Type));
                }
                sw.Write("}\n");
                // 注意栈顶为0时重置一般的计时器
                if (inst.Type.Equals("TON"))
                {
                    sw.Write("else\n{{\n{0:s}=0;\n}}\n", inst[1]);
                }
                // 注意部分脉冲指令当栈顶为0时需要立即停止
                switch (inst.Type)
                {
                case "PLSF":
                case "DPLSF":
                    sw.Write("else\n{{\n_plsstop(&{0:s});\n}}\n", inst[2]);
                    break;

                case "PWM":
                case "DPWM":
                case "PLSY":
                case "DPLSY":
                case "PLSR":
                case "DPLSR":
                case "PLSRD":
                case "DPLSRD":
                case "PTO":
                case "DRVI":
                case "DDRVI":
                    sw.Write("else\n{{\n_plsstop(&{0:s});\n}}\n", inst[3]);
                    break;

                case "ZRN":
                case "DZRN":
                    sw.Write("else\n{{\n_plsstop(&{0:s});\n}}\n", inst[4]);
                    break;
                }
                break;
            }
            // 如果是仿真模式需要对写入使能条件判断语句结尾
            if (simumode && inst.EnBit != null && inst.EnBit.Length > 0)
            {
                sw.Write("}\n");
            }
            // 进入条件断点的循环
            if (simumode && inst.ProtoType != null)
            {
                _CalcSignal(sw, true);
                sw.Write("cpcycle({0}, _signal);\n", bp);
            }
        }
Esempio n. 4
0
        /// <summary>
        /// 将给定的PLC代码转换为C语言代码并输出到文件
        /// </summary>
        /// <param name="sw">文件输出流</param>
        /// <param name="networks">PLC代码的NETWORK集</param>
        static private void _InstToCCode(StreamWriter sw, PLCInstNetwork[] networks, bool simumode = false)
        {
            // 构建指令结构的列表
            List <PLCInstruction> insts = new List <PLCInstruction>();
            // NETWORK合并
            PLCInstNetwork net1 = null;
            PLCInstNetwork net2 = null;

            for (int i = 0; i < networks.Length; i++)
            {
                net2 = networks[i];
                // 当前网络的组名和前一个不同,则设为函数名的声明
                if (net1 != null && !net1.Name.Equals(net2.Name))
                {
                    insts.Add(new PLCInstruction("FUNC " + net2.Name));
                }
                // 将NETWORK的代码合并
                foreach (PLCInstruction inst in net2.Insts)
                {
                    insts.Add(inst);
                }
                // 每个NETWORK结束后弹出最后的栈内容
                //if (net2.Insts.Count() > 1)
                //    insts.Add(new PLCInstruction("POP"));
                net1 = net2;
            }
            stackTop    = 0;
            mstackTop   = 0;
            globalCount = 0;
            int stackTotal  = 0;
            int mstackTotal = 0;
            int globalTotal = 0;
            Stack <PLCInstruction> stackinsts = new Stack <PLCInstruction>();

            foreach (PLCInstruction inst in insts)
            {
                // 计算普通栈和辅助栈的栈顶
                if (inst.Type.Length > 1 && inst.Type.Substring(0, 2) == "LD")
                {
                    stackTop++;
                    stackinsts.Push(inst);
                }
                if (inst.Type.Equals("ANDB") || inst.Type.Equals("ORB") || inst.Type.Equals("POP"))
                {
                    stackTop--;
                    PLCInstruction topinst = stackinsts.Pop();
                    topinst.StackCalc = inst.Type;
                }
                if (inst.Type.Equals("MPS"))
                {
                    mstackTop++;
                }
                if (inst.Type.Equals("MPP"))
                {
                    mstackTop--;
                }
                // 记录两个栈到达的最大高度
                if (stackTop > stackTotal)
                {
                    stackTotal = stackTop;
                }
                if (mstackTop > mstackTotal)
                {
                    mstackTotal = mstackTop;
                }
                // 统计所有需要全局变量的指令的总数
                switch (inst.Type)
                {
                case "LDP":
                case "LDF":
                case "ANDP":
                case "ANDF":
                case "ORP":
                case "ORF":
                case "ALTP":
                case "CTU":
                case "CTD":
                case "CTUD":
                case "FOR":
                case "INV":
                case "TON":
                case "TOF":
                case "TONR":
                    globalTotal++;
                    break;

                case "MEP":
                case "MEF":
                    globalTotal += 2;
                    break;
                }
                // 找到所有计数器的预设值
                if (inst.Type.Length >= 2 && inst.Type.Substring(0, 2).Equals("CT"))
                {
                    ctsv[int.Parse(inst[4])] = int.Parse(inst[2]);
                }
            }
            // 建立C代码的全局环境
            //sw.Write("#include \"lib.h\"\n");
            //sw.Write("#include \"main.h\"\n\n");
            //sw.Write("static uint16_t _stack[256];\n");         // 数据栈
            //sw.Write("static uint16_t _stacktop;\n");           // 数据栈的栈顶
            //sw.Write("static uint16_t _mstack[256];\n");        // 辅助栈
            //sw.Write("static uint16_t _mstacktop;\n");          // 辅助栈的栈顶
            user_id = 0;
            sw.Write("static int32_t _global[{0:d}];\n", globalTotal); // 全局变量
            if (simumode)
            {
                sw.Write("static int32_t _signal;\n");
            }
            // 先声明所有的子函数
            foreach (PLCInstruction inst in insts)
            {
                if (inst.Type.Equals("FUNC"))
                {
                    sw.Write("void _SBR_{0:s}();\n", inst[1]);
                }
            }
            // 建立扫描的主函数
            sw.Write("void RunLadder()\n{\n");
            if (simumode)
            {
                sw.Write("callinto();\n");
            }
            sw.Write("_itr_invoke();\n");
            // 建立局部的栈和辅助栈
            for (int i = 1; i <= stackTotal; i++)
            {
                sw.Write("uint32_t _stack_{0:d};\n", i);
            }
            for (int i = 1; i <= mstackTotal; i++)
            {
                sw.Write("uint32_t _mstack_{0:d};\n", i);
            }
            // 生成PLC对应的内容
            // 初始化栈顶
            stackTop  = 0;
            mstackTop = 0;
            foreach (PLCInstruction inst in insts)
            {
                switch (inst.Type)
                {
                // 函数头部
                case "FUNC":
                    if (simumode)
                    {
                        sw.Write("callleave();\n");
                    }
                    sw.Write("}\n\n");
                    sw.Write("void _SBR_{0:s}()", inst[1]);
                    sw.Write("{\n");
                    if (simumode)
                    {
                        sw.Write("callinto();\n");
                    }
                    // 建立局部的栈和辅助栈
                    for (int i = 1; i <= stackTotal; i++)
                    {
                        sw.Write("uint16_t _stack_{0:d};\n", i);
                    }
                    for (int i = 1; i <= mstackTotal; i++)
                    {
                        sw.Write("uint16_t _mstack_{0:d};\n", i);
                    }
                    // 初始化栈顶
                    stackTop  = 0;
                    mstackTop = 0;
                    break;

                default:
                    InstToCCode(sw, inst, simumode);
                    break;
                }
            }
            if (simumode)
            {
                sw.Write("callleave();\n");
            }
            sw.Write("}\n");
        }