G120XA与S7-1200的Modubus通信实战(三)

4. 通信原理详解

关于Modbus通信,网上能搜出一堆教程,我也查阅参考了很多,说实话,大多数都只是把自己的成功案例亮了出来,至于为什么能够成功,通信是否稳定,是否具备可改造性,没什么说明。
这个是官方提供的一个例程,包含PDF教程和项目文件,都是英文版,有兴趣的可以下载下来看一看,本次教程就是以它为基础的。
《如何使用 STEP 7 ( TIA Portal ) 为 SIMATIC S7-1200 建立 MODBUS - RTU 通信?》
47756141_Description.pdf (526,2 KB)
Registrierung notwendig 47756141_Sample_project_for_STEP_7_TIA_Portal_V15.zip (2,2 MB)

4.1 Modbus_Comm_Load

Modbus_Comm_Load 的组态更改将保存在 CM 中,而不是 CPU 中。恢复电压和插拔时,将使用保存在设备配置中的数据组态 CM。必须在这些情况下调用 Modbus_Comm_Load 指令。

大家知道,Modbus_Comm_Load只需要在PLC上电时运行一次即可,所以我在Startup OB100里面对"modbusCommLoad_REQ"进行置位,当调用 Modbus_Comm_Load 指令成功后复位。
Startup OB100
"modbusCommLoad_REQ" := TRUE;
Modbus FC7
在这里插入图片描述
这里的Done_Stored变量也是用作下面"Modbus_Master_DB"里面REQ启动的必要条件。

4.2 Modbus_Master的运行机制

Modbus_Master 前面已经组态好了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lr1kH5jr-1649257778882)(:/2ed891e2111046fcb91c7fc290f07993)]
上一节里面有Modbus_Master每个参数的含义表,编程之前需要很熟悉它。

这里先重点给大家讲一下Modbus_Master这个指令的运行机制
首先给"MB_ADDR"、“MODE”、DATA_ADDR"赋值,确定从站号、读/写、要访问数据的地址,然后REQ接通,开始发送命令,执行过程中"BUSY"会变为TRUE,当数据传输成功完成时"BUSY"变为FALSE、随之"DONE"变为 TRUE 并保持一个周期。如果通信不成功,会再次发送指令,如果在响应超时时间(“Modbus_Comm_Load"的RESP_TO”,默认1000ms)内始终无法成功通信,则 ERROR 位将变为 TRUE ,并保持一个周期。在这期间STATUS会显示错误代码,建议将其保存。
不难看出,一次通信,是以”REQ“置位TRUE为开始,以”BUSY“输出TRUE为运行中,以”DONE“或者”ERROR“输出TRUE为结束
这里要及其注意的是,在REQ置位TRUE后到DONE或ERROR输出TRUE前这段时间内,MODE、DATA_ADDR 和 DATA_LEN 参数是不允许发生改变的,否则该次通信将以将以 ERROR = 1 和 STATUS = 8200 终止。

5. 单个变频器的数据读写

版本1 单个变频器单个数据的读写

//版本1 单个变频器单个数据的读写
CASE "INV".Master_Step OF
    1:  //写开始
        "modbusMaster_MODE" := 1;
        "modbusMaster_DATA_ADDR" := 40101;  //主设定值 40101,频率0~50Hz转换为主设定值0~16384
        "modbusMaster_DATA_PTR" := INT_TO_WORD(REAL_TO_INT(16384 * "INV".M101_FREQ_Set / 50));
        "modbusMaster_REQ" := TRUE;
        IF "modbusMaster_BUSY" THEN
            "INV".Master_Step := 2;
        END_IF;
    2:  //写结束
        IF "modbusMaster_DONE" OR "modbusMaster_ERROR" THEN
            "modbusMaster_REQ" := FALSE;
            "INV".Master_Step := 3;
        END_IF;
    3:  //读开始
        "modbusMaster_MODE" := 0;
        "modbusMaster_DATA_ADDR" := 40110;  //状态字 40110
        "modbusMaster_REQ" := TRUE;
        IF "modbusMaster_BUSY" THEN
            "INV".Master_Step := 4;
        END_IF;
    4:  //读结束
        IF "modbusMaster_DONE" OR "modbusMaster_ERROR" THEN
            IF "modbusMaster_ERROR" THEN
                "INV".M10[1].状态字 := 0;
            ELSE
                "INV".M10[1].状态字 := "modbusMaster_DATA_PTR";
            END_IF;
        "modbusMaster_REQ" := FALSE;
        "INV".Master_Step := 1;
        END_IF;
    ELSE
        "modbusMaster_REQ" := FALSE;
        "INV".Master_Step := 1;
END_CASE;

在Modbus_Comm_Load已激活组态,Modbus_Master使能的情况下,你发现程序起作用了,给"INV".M101_FREQ_Set设定一个频率25Hz,变频器操作面板上显示了对应的设定转速。同时"INV".M10[1].状态字也收到了数值。然而你通过开关/中间继电器接通DI0,发现变频器完全没有动作……这就对了。回顾一下上一节,是不是少了点什么东西。
请添加图片描述
再看一看状态字,发现位0的值为0,未接通就绪。
在这里插入图片描述
于是我将Step1修改了一下,成了这样:
版本2 增加变频器就绪使能

    1:  //写开始
        "modbusMaster_MODE" := 1;
        IF %DB9.DBX77.0 THEN	//状态字第0位,变频器接通就绪
            "modbusMaster_DATA_ADDR" := 40101;  //主设定值 40101,频率0~50Hz转换为主设定值0~16384
            "modbusMaster_DATA_PTR" := INT_TO_WORD(REAL_TO_INT(16384 * "INV".M101_FREQ_Set / 50));
        ELSE
            "modbusMaster_DATA_ADDR" := 40100;            //控制字40100
            "modbusMaster_DATA_PTR" := 16#047E;
        END_IF;
        "modbusMaster_REQ" := TRUE;
        IF "modbusMaster_BUSY" THEN
            "INV".Master_Step := 2;
        END_IF;

这会儿我们发现,一启动通信,状态字变了。
在这里插入图片描述
然后接通DI0,变频器顺利启动。
在这里插入图片描述
这时候,控制字、主设定值、状态字我们都读写了,那就顺便把主实际值40111也读了吧。
版本3 增加读主实际值
这里我们增加了一个Bool变量”Read_DATA_ADDR_Change“,每次读数据结束取反一次,实现40110和40111的轮流读数据。

    3:  //读开始
        "modbusMaster_MODE" := 0;
        IF "Read_DATA_ADDR_Change" THEN
            "modbusMaster_DATA_ADDR" := 40110;  //状态字
        ELSE
            "modbusMaster_DATA_ADDR" := 40111;  //主实际值
        END_IF;
        "modbusMaster_REQ" := TRUE;
        IF "modbusMaster_BUSY" THEN
            "INV".Master_Step := 4;
        END_IF;
    4:  //读结束
        IF "modbusMaster_DONE" OR "modbusMaster_ERROR" THEN
            IF "modbusMaster_DATA_ADDR" = 40110 THEN
                IF "modbusMaster_ERROR" THEN
                    "INV".M10[1].状态字 := 0;
                ELSE
                    "INV".M10[1].状态字 := "modbusMaster_DATA_PTR";
                END_IF;
            ELSIF "modbusMaster_DATA_ADDR" = 40111 THEN
                IF "modbusMaster_ERROR" THEN
                    "INV".M10[1].主实际值 := 0;
                ELSE
                    "INV".M10[1].主实际值 := "modbusMaster_DATA_PTR";
                END_IF;
                "INV".M101_FREQ_Back := INT_TO_REAL(WORD_TO_INT("modbusMaster_DATA_PTR")) * 50 / 16384;
                "modbusMaster_REQ" := FALSE;
                "INV".Master_Step := 1;
                "Read_DATA_ADDR_Change" := NOT "Read_DATA_ADDR_Change";
            END_IF;
        END_IF;
    ELSE

至此,单个变频器的Modbus通信就基本上实现了,如果需要读写其他数据,记得再读写的最开始更改DATA_ADDR即可。
下一节,我以手头的五个变频器为例,讲一下多个从站轮询这块。

  • 10
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值