PLC地址转换_PEEK和POKE的另类用法

#使用HMI界面更改PLC中IO控制地址转换的方法#

开发背景:

       多年前,我在使用KUKA机器人控制系统时,发现他们的变量系统设计的非常巧妙,当然很多软件也支持这种功能,只是他们的软件做的更加得心应手,只需要在IO变量界面的后面修改变量地址即可,比如如$变量—1000,修改为$变量—1001(仅举例),把这种变量的本身不变,只是接口发生改变的形式,在项目场景中有很大的应用。以此类推,比如PLC的IO端口不变(物理地址),那么给IO端口附上变量地址,通过变量间的关系分别控制输入输出,当改变输入或输出端口变量的地址时,根据规定的逻辑关系,相应地址的联系保持不变,端口输入输出发生改变。这种形式类似于指针寻址的方式,只不过用的是PEEK和POKE的存储地址方式。

仿真结果如下:

       为了便于理解这种方法,我事先做了一个简单的控制界面,由于西门子的I区变量不能直接被界面访问控制,为此,程序内部我做了一个中间变量作为转换,实际效果不影响理解。

PLC地址转换

关键语句如下:

       本程序通过PEEK和POKE的用法,仅需不到50行的程序代码,其中还加入了检测代码,即完成了IO控制地址的转换,有关PEEK和POKE存储地址的讲解摘抄如下,如需详细说明,可参考官方手册。

程序分析说明:

       本次实现的假想控制关系如图:

       基于以上控制关系,假如输入I0.0(启动按钮),控制输出Q0.0(启动按钮灯),现将I0.0接线至I0.1,但输出逻辑不变。正常的操作方式是,打开PLC程序,修改IO点位控制程序。但加入自定义变量后,在界面中,修改变量的地址(默认I0.0:0,I0.1:1→修改后I0.0:1,I0.1:0),仍然输出Q0.0的值,是不是方便很多?同理可得,当项目需求由I0.1控制Q0.0,改为I0.1控制Q0.1时,改变输出区的自定义值即可。

       那么如何通过程序实现这种控制需求呢?当然有很多编程方式,只是当年在思考的时候,使用了PEEK和POKE的用法,如今在梳理文章的时候,我又进一步完善了当年的程序(自己写的差点没看懂,还好有注释^_^)。

       直接附源码了,主打的就是一个无私奉献。

//初始化赋值
IF "PublicVar".Init THEN
    FOR #i := 0 TO "MaxPoint" DO
        "PublicVar".SetSI_No[#i] := #i;//先给仿真区地址编号
        "PublicVar".SetSQ_No[#i] := #i;//先给仿真区地址编号
    END_FOR;
    "PublicVar".Init := FALSE;
END_IF;
//小提示复位
"PublicVar".InTip := '';
"PublicVar".OutTip := '';
//检测重复性
FOR #i := 0 TO "MaxPoint" DO
    IF "PublicVar".GetSI_No[#i] > "MaxPoint" THEN
        "PublicVar".InTip := 'The input address data MoreLen!';
    END_IF;
    IF "PublicVar".GetSQ_No[#i] > "MaxPoint" THEN
        "PublicVar".OutTip := 'The Output address data MoreLen!';
    END_IF;
    FOR #j := 1 TO "MaxPoint" - #i DO
        IF "PublicVar".GetSI_No[#i] = "PublicVar".GetSI_No[#i + #j] THEN
            "PublicVar".InTip := 'The input address data REPEAT!';
        END_IF;
        IF "PublicVar".GetSQ_No[#i] = "PublicVar".GetSQ_No[#i + #j] THEN
            "PublicVar".OutTip := 'The Output address data REPEAT!';
        END_IF;
    END_FOR;
END_FOR;
//循环赋值
FOR #i := 0 TO "MaxPoint" DO
    //地址赋值
    "PublicVar".GetSI_No[#i] := "PublicVar".SetSI_No[#i];
    "PublicVar".GetSQ_No[#i] := "PublicVar".SetSQ_No[#i];
    //读取仿真I区的状态,给中间变量I区;
    "PublicVar".MI_No["PublicVar".GetSI_No[#i]] := PEEK_BOOL(area := 16#84, dbNumber := 3, byteOffset := #i / 8, bitOffset := #i MOD 8);
    //将中间变量I区状态返回给物理I区;
    POKE_BOOL(area := 16#81,dbNumber := 0,byteOffset := "PublicVar".GetSI_No[#i] / 8,bitOffset := "PublicVar".GetSI_No[#i] MOD 8,value := "PublicVar".MI_No["PublicVar".GetSI_No[#i]]);
    //读取中间变量I区(物理I区),给中间变量MQ区;
    IF "PublicVar".InTip = '' AND "PublicVar".OutTip = '' THEN
        "PublicVar".MQ_No := "PublicVar".MI_No;
    END_IF;
    //将中间变量MQ区的状态,输出信号给物理Q区;
    POKE_BOOL(area := 16#82,dbNumber := 0,byteOffset := #i / 8,bitOffset := #i MOD 8,value := "PublicVar".MQ_No["PublicVar".GetSQ_No[#i]]);
END_FOR;


#写在最后# 

       刚刚已经说过I区的问题,实际上,能看懂这块程序的话,不加仿真I区还稍微简单点,直白点说,就是获取I区的物理状态,将对应的I区点位的值,给到相应的变量地址里面,整个过程还是比较简单的,当然,本程序仅是提供一个解决案例,在实际在应用的过程中,要完善检测程序,避免因交换地址出现的编程错误等控制风险。

       希望大家多多评论,支持,如有疑问,或工作中出现的疑难杂症,都可以在下方评论交流,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值