在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块,取消优化后通过地址指针可实现)。