Здравствуйте господа и дамы, прошу поделится рабочим примером работы с библиотекой ModBus. Пытаюсь осуществить связь с ТРМ201 по протоколу ModBusRtu. Первый раз мне повезло и соединение было установлено, но затем снова появилась ошибка 255, увеличение таймаута не помогло. Может быть кто-нибудь укажет мне на ошибку, которую я найти не могу.
Код программы следующий:
PROGRAM PLC_PRG
VAR
GetTemp: ModBus.MB_RD_HOLD_REGS; (*функция 03 - чтение параметра типа INT*)
Connection1: ComConn; (*Функциональные блок открытия порта*)
Buffer: ARRAY[0..255] OF BYTE; (*байтовый буфер данных *)
ConnectionClose: ComClose; (*Функциональный блок закрытия последовательного порта*)
cmpl: BOOL;
DataSize: WORD;
x: WORD;
TimeOut: ModBus.SysCom.COM_Timeout;
Err: INT;
Timer1:ton;
b:BOOL;
name: DWORD;
h: SysFile.RTS_IEC_RESULT;
FileHandle : SysFile.RTS_IEC_HANDLE;
TextTest: STRING:='';
TextTest1: STRING:='/mnt/usb1/';
TextTest2: STRING:='ar1';
t: INT:=1;
END_VAR
VAR_INPUT
END_VAR
//Если порт закрыт, то откроем его
IF Connection1.done = FALSE THEN
Connection1(enable:=TRUE, PortNum:=2);
//Открываем первый физический порт
//Все остальные настройки порта оставляем по умолчанию
IF Connection1.Done=TRUE THEN
ModBus.SysCom.SysComPurge (Connection1.Handle); //очищаем буфер порта
TimeOut:=0; // Время для функций read write
END_IF
END_IF
//blinker.TIMEHIGH:=T#5S;
//blinker.TIMELOW:=T#1S;
//blinker(ENABLE:=TRUE);
//rtrig(CLK:=blinker.OUT);
IF (Connection1.Done=TRUE) THEN
GetTemp(
Enable:=1 , (*разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=1 , (*адрес*)
FirstAddr:=1 , (*номер регистра*)
Quantity:=1, (*количество регистров*)
ComHandle:=Connection1.Handle, (*номер COM-порта*)
TimeOut:=T#50MS , (*Таймаут T#50ms*)
Buffer:=Buffer , (*буфер данных *)
Complete=>cmpl , (*скопировать признак завершения операции *)
Exception=>err , (*скопировать регистр ошибок *)
ByteCnt=>DataSize ); (*кол-во считанных байтов *)
END_IF;
//если установлен признак завершения операции, то
IF cmpl THEN
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа INT*)
x:=BYTE_TO_WORD(BUFFER[1]) OR SHL(BYTE_TO_WORD(BUFFER[0]),8);
test:=x/INT_TO_REAL(10);
END_IF
END_IF
Функциональный блок ComConn:
FUNCTION_BLOCK ComConn
VAR_INPUT
Enable: BOOL; (*Разрешение работы блока*)
PortNum: ModBus.SysCom.COM_Ports:=2; (*Номер порта на ПЛК, на ПЛК 304 это порт 2*)
PortBaudrate: ModBus.SysCom.COM_Baudrate:=19200; (*Скорость работы порта, по умолчанию 19.2 кбод*)
PortParity: ModBus.SysCom.COM_Parity:=0; (*Режим проверки на четнось: 0-нет; 1- нечет; 2- чет,
по умолчанию нет проверки на четность*)
PortStopBits: ModBus.SysCom.COM_StopBits:=0; (*Количество стоп-бит: 1- 1 бит; 2- 1.5 бита; 3- 2 бита,
по умолчанию 1 стоп-бит*)
PortByteSyze: BYTE:=8; (*Размер посылки в байтах*)
END_VAR
VAR_OUTPUT
Handle: ModBus.SysCom.RTS_IEC_HANDLE; (*Идентификатор открытого порта, если ошибка, то все F*)
Done: BOOL:=FALSE; (*Флаг завершения операции*)
ErrCode: ModBus.SysCom.RTS_IEC_RESULT; (*Код ошибок*)
END_VAR
VAR
Settings: ModBus.SysCom.COM_Settings; (*Настройки порта*)
SettingsEX: Modbus.SysCom.COM_SettingsEx; (*Расширенные настройки порта*)
Result: ModBus.SysCom.RTS_IEC_RESULT; (**)
Rtrig: ModBus.R_TRIG;
Trig: rs;
END_VAR
Rtrig(clk:=(Enable AND NOT done));
Trig(set:=Rtrig.q, RESET1:=FALSE);
IF Trig.Q1 THEN
Settings.sPort:= PortNum; (*Инициализируем номер порта*)
Settings.ulBaudrate:= PortBaudrate; (*Инициализируем скорость работы порта*)
Settings.byParity:= PortParity; (*Настройка проверки четности порта*)
Settings.ulTimeout:=0;
Settings.byParity:= PortStopBits; (*Настройка количества стоп-бит*)
Settings.ulBufferSize:= 0; (*Размер буфера*)
SettingsEx.byByteSize:= PortByteSyze; (*Размер посылки данных*)
SettingsEx.bBinary := TRUE;
SettingsEx.bDtrControl := FALSE;
SettingsEx.bRtsControl := FALSE;
SettingsEx.bOutxCtsFlow := FALSE;
SettingsEx.bOutxDsrFlow := FALSE;
SettingsEx.bDsrSensitivity := FALSE;
//Переходим непосредственно к открытию порта
Handle:=ModBus.SysCom.SysComOpen2(ADR(Settings),AD R(SettingsEx),ADR(ErrCode));
//Если порт открыт, то переходим к приему передачи данных
IF (Handle<>16#FFFFFFFF) THEN
//Если условие не выполняется, то порт занят
Done:= TRUE;
Trig(RESET1:=TRUE);
ELSE
Done:=FALSE;
END_IF
END_IF
P.S. Пример, приложенный на диске с контроллером, не работает .