Вот, что получилось в итоге у меня.
Устранил замечания по теме. Убрал запись повторяющихся статусов ошибок, чтобы не разрастался лог. Добавил разовую запись лога 'RESPONSE_SUCCESS' для определения времени конца ошибки.
Покритикуйте ...
Код:
// отлавливаем статус ошибки UNDEFINED
IF (Modbus_TCP_Slave.byModbusError <> 16#FF) THEN
MbState:= Modbus_TCP_Slave.byModbusError;
END_IF
// обработка ошибки
IF Modbus_TCP_Slave.xError THEN
// преобразовать код ошибки в строку
CASE MbState OF
16#1: sMbLogError := 'ILLEGAL_FUNCTION';
16#2: sMbLogError := 'ILLEGAL_DATA_ADDRESS';
16#3: sMbLogError := 'ILLEGAL_DATA_VALUE';
16#4: sMbLogError := 'SLAVE_DEVICE_FAILURE';
16#5: sMbLogError := 'ACKNOWLEDGE';
16#6: sMbLogError := 'SLAVE_DEVICE_BUSY';
16#8: sMbLogError := 'MEMORY_PARITY_ERROR';
16#A: sMbLogError := 'GATEWAY_PATH_UNAVAILABLE';
16#B: sMbLogError := 'GATEWAY_DEVICE_FAILED_TO_RESPOND';
16#A1:sMbLogError := 'RESPONSE_TIMEOUT';
16#A2:sMbLogError := 'RESPONSE_CRC_FAIL';
16#A3:sMbLogError := 'RESPONSE_WRONG_SLAVE';
16#A4:sMbLogError := 'RESPONSE_WRONG_FUNCTIONCODE';
16#A5:sMbLogError := 'TCP_COMMUNICATION_ERROR';
16#A6:sMbLogError := 'RESPONSE_INVALID_DATA';
16#A7:sMbLogError := 'RESPONSE_INVALID_PROTOCOL';
16#A8:sMbLogError := 'RESPONSE_INVALID_HEADER';
END_CASE
// если статус ошибки поменялся, то в лог
IF MbState <> MbStatePREV THEN
sMbLog := CONCAT(TSandCYCLES, sMbLogError);
sMbLog := CONCAT(sMbLog, '$N');
FB_FIFO_64_STRING_0 (StrIn:=sMbLog, E:=TRUE, RD:=FALSE, WD:=TRUE, RST:=FALSE);
END_IF
END_IF
// для разового лога RESPONSE_SUCCESS
IF (MbState = 16#0) AND (MbStatePREV <> 16#0) THEN
sMbLog := CONCAT(TSandCYCLES, 'MODBUS OK: RESPONSE_SUCCESS');
sMbLog := CONCAT(sMbLog, '$N');
FB_FIFO_64_STRING_0 (StrIn:=sMbLog, E:=TRUE, RD:=FALSE, WD:=TRUE, RST:=FALSE);
END_IF
// индикация ошибки
IF (MbState <> 16#0) THEN xLedError:= TRUE;
ELSE xLedError:= FALSE;
END_IF
// сохраняем текущий статус ошибки
MbStatePREV := MbState;