Код:
PROGRAM PLC_PRG
VAR
get1_modbus: MB_RD_HOLD_REGS; (*функция 03 - чтение параметра типа INT*)
get2_modbus: MB_RD_INP_REGS; (*функция 04 - чтение трех параметров типа INT*)
get3_modbus: MB_RD_HOLD_REGS; (*функция 03 - чтение параметра типа Float*)
Buffer: ARRAY[0..255] OF BYTE; (* байтовый буфер данных *)
cmpl: BOOL;
port_opened: BYTE := 0;
Init: BOOL; (* признак инициализации пользовательской программы *)
Settings:COMSETTINGS; (* настройки последовательного порта *)
com_num: PORTS:=0; (*0 - RS-485, 1 - RS-232*)
enabl: BOOL; (*состояние работы блока*)
err: INT; (*номер ошибки*)
TimeOut: TIME:=T#250ms; (*таймаут*)
Exception: BYTE;
DataSize: WORD;
master1: BYTE:= 2;
t: DWORD; (*переменная для организации счетчика*)
A: WORD := 0; (*счетчик*)
x:WORD; (*считанное значение*)
x1: INT; (*переменная для записи по сети*)
x2: INT; (*переменная для записи по сети*)
x3: INT; (*переменная для записи по сети*)
d: REAL; (*считанное значение*)
ptr_D:POINTER TO BYTE;
COM_SERVICE1: COM_SERVICE;
x_1: INT;
delay: TON;
END_VAR
--------------------------------------------
(*Организуем счетчик, что бы передавать эти данные по сети*)
t:=t+1;
IF (t MOD 1000)=0 THEN
A := A + 1;
IF A > 9999 THEN
A := 0;
END_IF
END_IF
delay(PT:=T#1S);
(*Устанавливаем настройки COM-порта*)
IF port_opened=0 THEN
Settings.Port:=com_num; (*номер COM-порта*)
Settings.dwBaudRate:=19200; (*скорость*)
Settings.byParity:=0;
Settings.dwTimeout:=0;
Settings.byStopBits:=0;
Settings.dwBufferSize:=0;
Settings.dwScan:=0;
END_IF
COM_SERVICE1(Enable:=(port_opened=0) , Settings:=Settings , Task:=OPEN_TSK );
(*Если COM-порт открыт, то переходим к приему и передачи данных *)
IF COM_SERVICE1.ready THEN
port_opened:=2;
END_IF
IF port_opened=2 THEN (*Удачно проинициализировали*)
CASE master1 OF
0: (* функция 03 инт - ФБ считывает значение параметра типа int из прибора с адресом 2 в регистр с номером 8 по протоколу Modbus-ASCII*)
get1_modbus(
Enable:=enabl , (* разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=2 , (*адрес*)
FirstAddr:=8 , (*номер регистра*)
Quantity:=1, (*количество регистров*)
ComHandle:=Settings.Port , (*номер COM-порта*)
TimeOut:=TimeOut , (*Таймаут T#50ms*)
Buffer:=Buffer , (* буфер данных *)
Complete=>cmpl , (* скопировать признак завершения операции *)
Exception=>err , (* скопировать регистр ошибок *)
ByteCnt=>DataSize ); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
enabl:=FALSE;
delay(IN:=TRUE);
IF cmpl THEN
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа INT*)
x:=BYTE_TO_WORD(BUFFER[1]) OR SHL(BYTE_TO_WORD(BUFFER[0]),8);
END_IF
enabl:=TRUE;
(*master1:=1; переходим к выполнению следующего ФБ*)
END_IF
1: (* функция 03 флоат - ФБ считывает значение параметра типа int из прибора с адресом 2 в регистр с номаром 10 по протоколу Modbus-ASCII *)
get3_modbus(
Enable:=enabl , (* разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=2 , (*адрес*)
FirstAddr:=10 , (*номер регистра*)
Quantity:=2, (*количество регистров*)
ComHandle:=Settings.Port ,(*номер COM-порта*)
TimeOut:=TimeOut , (*Таймаут T#50ms*)
Buffer:=Buffer , (* буфер данных *)
Complete=>cmpl , (* скопировать признак завершения операции *)
Exception=>err , (* скопировать регистр ошибок *)
ByteCnt=>DataSize ); (*кол-во считанных байтов *)
enabl:=FALSE;
delay(IN:=TRUE);
(*если установлен признак завершения операции, то *)
IF cmpl THEN
(*master1:=2; переходим к выполнению следующего ФБ*)
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа FLOAT*)
ptr_D:=ADR(d);
ptr_D^:=buffer[1];
ptr_D:=ptr_D+1;
ptr_D^:=buffer[0];
ptr_D:=ptr_D+1;
ptr_D^:=buffer[3];
ptr_D:=ptr_D+1;
ptr_D^:=buffer[2];
END_IF
enabl:=TRUE;
END_IF
2: (* функция 04 инт - ФБ считывает значения трех параметров типа Int из прибора с адресом 2 начиная с регистра с номeром 12*)
get2_modbus(
Enable:= enabl, (* разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=2 , (*адрес*)
FirstAddr:=12 , (*номер регистра*)
Quantity:=8 , (*количество регистров*)
ComHandle:= Settings.Port,(*номер COM-порта*)
TimeOut:=TimeOut , (*Таймаут T#50ms*)
Buffer:=Buffer , (* буфер данных *)
Complete=>cmpl , (* скопировать признак завершения операции *)
Exception=>err , (* скопировать регистр ошибок *)
ByteCnt=> DataSize); (*кол-во считанных байтов *)
enabl:=FALSE;
delay(IN:=TRUE);
(*если установлен признак завершения операции, то *)
IF cmpl THEN
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа INT*)
x1:=BYTE_TO_WORD(BUFFER[4]) OR SHL(BYTE_TO_WORD(BUFFER[3]),8);
x2:=BYTE_TO_WORD(BUFFER[8]) OR SHL(BYTE_TO_WORD(BUFFER[7]),8);
x3:=BYTE_TO_WORD(BUFFER[12]) OR SHL(BYTE_TO_WORD(BUFFER[11]),8);
END_IF
enabl:=TRUE;
(*master1:=0; переходим к выполнению следующего ФБ*)
END_IF
END_CASE
IF enabl = FALSE AND delay.Q THEN
enabl := TRUE;
delay(IN:=FALSE);
END_IF
IF err <> 0 THEN
enabl := FALSE;
END_IF
END_IF