Я пользуюсь таким алгоритмом чтения:
PHP код:
PROGRAM GET_MB
VAR
(*TON*)
HavePause :TON;
(*FB*)
GetModbus : MB_RD_HOLD_REGS;
ComService : COM_SERVICE;
(*BOOL*)
ES : BOOL := TRUE;
EndSendStored : BOOL;
(*BYTE*)
ComPortState : BYTE := 0;
Addr : BYTE := 2;
RegQuant : BYTE := 24;
(*INT*)
MB110_8AC_1CH_STS : INT;
MB110_8AC_2CH_STS : INT;
MB110_8AC_3CH_STS : INT;
MB110_8AC_4CH_STS : INT;
MB110_8AC_5CH_STS : INT;
MB110_8AC_6CH_STS : INT;
MB110_8AC_7CH_STS : INT;
MB110_8AC_8CH_STS : INT;
(*WORD*)
DataSize : WORD;
RegAddr : WORD := 280;
(*REAL*)
MB110_8AC_1CH_VAL : REAL;
MB110_8AC_2CH_VAL : REAL;
MB110_8AC_3CH_VAL : REAL;
MB110_8AC_4CH_VAL : REAL;
MB110_8AC_5CH_VAL : REAL;
MB110_8AC_6CH_VAL : REAL;
MB110_8AC_7CH_VAL : REAL;
MB110_8AC_8CH_VAL : REAL;
(*TIME*)
TimeOut1 : TIME := T#50ms;
TimeOut2 : TIME := T#250ms;
(*STRUCT*)
Settings : COMSETTINGS;
(*TYPES*)
ComNum : PORTS := 0;
(*ARRAY*)
Buffer : ARRAY [0..255] OF BYTE;
(*POINTER*)
Ptb : POINTER TO BYTE;
END_VAR
(*Настройки COM-порта*)
IF ComPortState=0 THEN
Settings.Port:=ComNum; (*номер COM-порта*)
Settings.dwBaudRate:=115200; (*скорость*)
Settings.byParity:=0;
Settings.dwTimeout:=0;
Settings.byStopBits:=1;
Settings.dwBufferSize:=0;
Settings.dwScan:=0;
END_IF
(*_______________________________________________________________*)
(*Открываем COM-порт*)
ComService(ENABLE := ComPortState = 0, SETTINGS := Settings, TASK := OPEN_TSK);
(*_______________________________________________________________*)
(*Готовность COM-порта к обмену данными*)
IF ComService.Ready THEN
ComPortState := 2;
END_IF
(*_______________________________________________________________*)
(*Если COM-порт открыт, то запускаем обмен данными*)
IF ComPortState=2 THEN
GetModbus(
Enable := ES,
Mode := MB_RTU,
DevAddr := Addr,
FirstAddr := RegAddr,
Quantity := RegQuant,
ComHandle := Settings.Port,
TimeOut := TimeOut1,
Buffer := Buffer,
ByteCnt => DataSize);
ES := FALSE;
(*Если прием данных завершен*)
IF GetModbus.Complete THEN
(*и без ошибок,*)
IF GetModbus.Exception = 0 THEN
(*то читаем их из Buffer в соответствующие переменные*)
(*Статусы результатов измерений модулей MB110 8AC*)
(*Первый канал*)
Ptb := ADR(MB110_8AC_1CH_STS);
Ptb^ := Buffer[1];
Ptb := Ptb + 1;
Ptb^ := Buffer[0];
(*Второй канал*)
Ptb := ADR(MB110_8AC_2CH_STS);
Ptb^ := Buffer[3];
Ptb := Ptb + 1;
Ptb^ := Buffer[2];
(*Третий канал*)
Ptb := ADR(MB110_8AC_3CH_STS);
Ptb^ := Buffer[5];
Ptb := Ptb + 1;
Ptb^ := Buffer[4];
(*Четвертый канал*)
Ptb := ADR(MB110_8AC_4CH_STS);
Ptb^ := Buffer[7];
Ptb := Ptb + 1;
Ptb^ := Buffer[6];
(*Пятый канал*)
Ptb := ADR(MB110_8AC_5CH_STS);
Ptb^ := Buffer[9];
Ptb := Ptb + 1;
Ptb^ := Buffer[8];
(*Шестой канал*)
Ptb := ADR(MB110_8AC_6CH_STS);
Ptb^ := Buffer[11];
Ptb := Ptb + 1;
Ptb^ := Buffer[10];
(*Седьмой канал*)
Ptb := ADR(MB110_8AC_7CH_STS);
Ptb^ := Buffer[13];
Ptb := Ptb + 1;
Ptb^ := Buffer[12];
(*Восьмой канал*)
Ptb := ADR(MB110_8AC_8CH_STS);
Ptb^ := Buffer[15];
Ptb := Ptb + 1;
Ptb^ := Buffer[14];
(*Измеренные значения модуля MB110 8AC*)
(*Первый канал*)
Ptb := ADR(MB110_8AC_1CH_VAL);
Ptb^ := Buffer[19];
Ptb := Ptb + 1;
Ptb^ := Buffer[18];
Ptb := Ptb + 1;
Ptb^ := Buffer[17];
Ptb := Ptb + 1;
Ptb^ := Buffer[16];
(*Второй канал*)
Ptb := ADR(MB110_8AC_2CH_VAL);
Ptb^ := Buffer[25];
Ptb := Ptb + 1;
Ptb^ := Buffer[24];
Ptb := Ptb + 1;
Ptb^ := Buffer[23];
Ptb := Ptb + 1;
Ptb^ := Buffer[22];
(*Третий канал*)
Ptb := ADR(MB110_8AC_3CH_VAL);
Ptb^ := Buffer[31];
Ptb := Ptb + 1;
Ptb^ := Buffer[30];
Ptb := Ptb + 1;
Ptb^ := Buffer[29];
Ptb := Ptb + 1;
Ptb^ := Buffer[28];
(*Четвертый канал*)
Ptb := ADR(MB110_8AC_4CH_VAL);
Ptb^ := Buffer[37];
Ptb := Ptb + 1;
Ptb^ := Buffer[36];
Ptb := Ptb + 1;
Ptb^ := Buffer[35];
Ptb := Ptb + 1;
Ptb^ := Buffer[34];
(*Пятый канал*)
Ptb := ADR(MB110_8AC_5CH_VAL);
Ptb^ := Buffer[43];
Ptb := Ptb + 1;
Ptb^ := Buffer[42];
Ptb := Ptb + 1;
Ptb^ := Buffer[41];
Ptb := Ptb + 1;
Ptb^ := Buffer[40];
(*Шестой канал*)
Ptb := ADR(MB110_8AC_6CH_VAL);
Ptb^ := Buffer[49];
Ptb := Ptb + 1;
Ptb^ := Buffer[48];
Ptb := Ptb + 1;
Ptb^ := Buffer[47];
Ptb := Ptb + 1;
Ptb^ := Buffer[46];
(*Седьмой канал*)
Ptb := ADR(MB110_8AC_7CH_VAL);
Ptb^ := Buffer[55];
Ptb := Ptb + 1;
Ptb^ := Buffer[54];
Ptb := Ptb + 1;
Ptb^ := Buffer[53];
Ptb := Ptb + 1;
Ptb^ := Buffer[52];
(*Восьмой канал*)
Ptb := ADR(MB110_8AC_8CH_VAL);
Ptb^ := Buffer[61];
Ptb := Ptb + 1;
Ptb^ := Buffer[60];
Ptb := Ptb + 1;
Ptb^ := Buffer[59];
Ptb := Ptb + 1;
Ptb^ := Buffer[58];
END_IF
EndSendStored := TRUE;
END_IF
(*Временная задержка*)
HavePause(IN := EndSendStored, PT := TimeOut2);
IF HavePause.Q THEN
ES := TRUE;
EndSendStored := FALSE;
END_IF
END_IF
Можно "поиграться" с таймаутами. Никаких ошибок, при условии правильной настройки мастера и слэйва.