技术论坛

 回复:编写一个MODBUS-RTU通信的功能块,当连续读取多个寄存器时,其中的DATA_PTR 数据指针应怎么定义?

返回主题列表
作者 主题
努力前行
奇侠

经验值:7578
发帖数:823
精华帖:5
楼主    2016-09-02 14:36:55
主题:编写一个MODBUS-RTU通信的功能块,当连续读取多个寄存器时,其中的DATA_PTR 数据指针应怎么定义?

     在S7-1200一个项目中,PLC与多台变频器485总线连接,通过MODBUS-RTU协议轮询通信。需读出每台变频器的工作状态、频率、电流值,并可给出起停控制及修改频率值。编程思路如下:

     编写一个FB块,在块中顺序读取变频器的状态字、工作频率、工作电流。如果有起停或频率修改则继续执行写操作,如无需写入,则跳转至下一变频。每次读写时,只对一个寄存器地址操作。如第一步初始化端口,第二步待机,第三步读状态字,第四步读频率,第五步读电流,结束后变频号加1,并返回到待机状态。这期间如果有起停或频率给定,则优先执行,完成后仍返回到待机状态。在FB块中定义了一个结构体数据类型的静态变量:drive.ZSW  drive.HIW  drive.CURRENT,作为读取寄存器值的缓冲区域,读取完成后并将此值赋给声明的"OUT"形参。部分代码如下:

CASE STEP OF 

0:                      //INIT

;

1:                     //IDLE

;     

2:                      // Read ZSW from drive: Cal MB_MASTER  

REQ:=TRUE;

#MB_MASTER_Instance(REQ:=#REQ,

                        MB_ADDR:=#drive_index,

                        MODE:=0,

                        DATA_ADDR:=40004,

                        DATA_LEN:=1,

                        DONE=>#_DONE,

                        ERROR=>#_ERROR,

                        STATUS=>#_STATUS,

                        DATA_PTR:=#Drive.ZSW_internal);


          IF #_DONE THEN

             REQ:=FALSE;

            STEP:=STEP+1;

          END_IF;

3:                      // Read HIW from drive: Cal MB_MASTER  

REQ:=TRUE;

#MB_MASTER_Instance(REQ:=#REQ,

                        MB_ADDR:=#drive_index,

                        MODE:=0,

                        DATA_ADDR:=40005,

                        DATA_LEN:=1,

                        DONE=>#_DONE,

                        ERROR=>#_ERROR,

                        STATUS=>#_STATUS,

                        DATA_PTR:=#Drive.HIW_internal);


             IF #_DONE THEN

                 REQ:=FALSE;

                 STEP:=STEP+1;

              END_IF;

;

END_CASE

    (上述程序段仅用于帮助理解问题,并不是实际的程序。)

    主程序中调用此FB块,运行可实现上述功能。但是,如果其中有个别从站通信错误,由于每读一次寄存器无响应后都要延迟1秒(MODUBS_LOAD中设定的延时值),使用此程序在轮巡每台设备时需要读多次寄存器,因而要延迟多秒,导致整个采集的轮巡周期过长。设想,状态字、频率、电流寄存器地址是连续的,如果设置读取数据长度为3,只需一次通信即可将这三个连续数据读出,则可成倍减少轮巡时间。

     如果读取的是多个数据,则要使用地址指针。但地址指针的使用必须是绝对地址,而背景数据块中无法取消“优化访问”,因此不知此处应如何写了。

      不知我的描述是否便于理解,简单的说就是在FB块中调用MODBUS-MASTER库,读取多个连续寄存器时,其缓冲区地址应如何写?(不在FB块中的引用是通过建一个DB块,取消优化后通过地址指针可实现)。

办法总比困难多
努力前行
奇侠

经验值:7578
发帖数:823
精华帖:5
3楼    2016-09-05 10:05:32
精华帖  主题:回复:编写一个MODBUS-RTU通信的功能块,当连续读取多个寄存器时,其中的DATA_PTR 数据指针应怎么定义?

    感谢Zane的提示,参照了 N侠 的例程,做了如下整理,并通过在线实验,希望对大家的应用有所参考。

1、  在原声明的结构体数据类型的静态变量中增加了一个数组,用于存放连续读取的数值,见截图;

2、  将编辑的FB块的“优化的块访问”取消,否则出现”818C”错误,(DATA_PTR 的指针无效或 Blocked_Proc_Timeout 无效)见截图;

2、修改程序,在MODBUS-MASTER库的DATA_PTR管脚填入已声明的数组变量,见截图;

3、程序下载运行,在线监测,正常,见截图;

      至此,解决了轮询多台变频器的多组数据采集及指定变频器的起、停、初始化。通过上述程序的调整,缩短了轮巡的时间,便于某一台变频器的状态发生改变后能更早的时间发现。另外应用中还应尽可能的将从站地址连续。减少通信判断的延时。


   应注意的是:

    DATA_PTR 参数指向要写入或读取的 DB地址,应取消“优化的块访问”,否则无法支持绝对寻址。在前期编程过程中也声明了数组变量,但由于没有取消“优化”,因此无法实现功能,参照了N侠的分享后此问题解决。


程序运行在线监图1.jpg

程序运行在线监图2.jpg

程序运行在线监图3.jpg

程序运行在线监图4.jpg


办法总比困难多
您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。