FB_IEC870_5_101TBufferCtrl
This function block can be used to manipulate the content of the TX/RX data buffer, which is used for the communication via the IEC 60870-5-101/104 low-level interface.
The function block features the following tasks:
- RxRemoveObj (removes the oldest FIFO entry from the RX FIFO);
- RxReset (clears all the RX FIFO entries, resets the RX FIFO);
- TxAddObj (inserts a new FIFO entry into the TX FIFO);
- TxReset (clears all the TX FIFO entries, resets the TX FIFO)
The content of the TX/RX data buffer can be changed by calling the actions listed above.
VAR_IN_OUT
VAR_IN_OUT
buffer : ST_IEC870_5_101TBuffer;
END_VAR
buffer: TX/RX data buffer. The TX/RX buffer parameters (like e.g. asduSize ) have to be configured before using.
VAR_OUTPUT
VAR_OUTPUT
getObj : ST_IEC870_5_101AOGen;
bOk : BOOL;
END_VAR
getObj: Received data unit (ASDU).
bOk: This variable becomes TRUE if a new entry was successfully added to or removed from the FIFO. This variable becomes FALSE if the buffer overflows and if it is not possible to remove an entry because the FIFO is already empty.
Examples (low-level interface):
- IEC 60870-5-101 central station (master, unbalanced mode);
- IEC 60870-5-101 substation (slave, unbalanced mode);
- IEC 60870-5-101 central station (master, balanced mode);
- IEC 60870-5-101 substation (slave, balanced mode);
Further examples:
The following fragment of example code demonstrates the use of the function block actions. Approximately every 100 ms (tCycle) a new ASDU (M_BO_TB_1) is generated with "spontaneous" as the transmission cause and with a timestamp, and is placed in the TX FIFO.
The test command (C_TS_TA_1) and clock synchronization command (C_CS_NA_1) received are removed from the RX FIFO, and replied to with reflected ASDUs.
PROGRAM P_SAMPLE_1ms
VAR
(* TX/RX data buffer *)
fbBuffer : FB_IEC870_5_101TBufferCtrl;
buffer : ST_IEC870_5_101TBuffer := ( asduSize := 253 );
tCycle : TIME := T#100ms;
timer : TON;
dtStart : DT := DT#2006-07-05-12:34:56;
txAsdu : ST_IEC870_5_101AOGen;
rxAsdu : ST_IEC870_5_101AOGen;
txBSI : DWORD := 1;
txQDS : BYTE;
txTT : T_CP56Time2a;
rxTT : T_CP56Time2a;
END_VAR
timer( IN := TRUE, PT := tCycle );
IF timer.Q THEN
timer( IN := FALSE );
txAsdu.ident.eType := M_BO_TB_1; (* Bit string with time tag *)
txAsdu.ident.bSQ := FALSE;
txAsdu.ident.nObj := 1;
txAsdu.ident.eCOT := eIEC870_COT_SPONTAN;
txAsdu.ident.nORG := 1;
txAsdu.ident.bPN := FALSE;
txAsdu.ident.bT := FALSE;
txAsdu.ident.eClass := eIEC870_Class_1;
txAsdu.ident.asduAddr := 7;
txAsdu.info.objAddr := 100;
txBSI := ROL( txBSI, 1); (* Modify bit string value *)
txQDS.7 := NOT txQDS.7; (* Toggle IV quality flag *)(* create dummy time tag *)
dtStart := dtStart + tCycle;
txTT := SYSTEMTIME_TO_CP56Time2a( DT_TO_SYSTEMTIME( dtStart ), TRUE );
F_iecResetStream( 0, txAsdu.info.stream ); (* clear previous data (this sets the stream length = 0 *)
F_iecCopyBufferToStream( ADR( txBSI ), SIZEOF( txBSI ), txAsdu.info.stream ); (* put BSI to stream *)
F_iecCopyBufferToStream( ADR( txQDS ), SIZEOF( txQDS ), txAsdu.info.stream ); (* put QDS to stream *)
F_iecCopyBufferToStream( ADR( txTT ), SIZEOF( txTT ), txAsdu.info.stream ); (* put time tag to stream *)
fbBuffer.TxAddObj( putObj := txAsdu, buffer := buffer ); (* put asdu to the TX fifo *)
IF NOT fbBuffer.bOk THEN
;(* Report send buffer overflow error *)
END_IF
END_IF
REPEAT
fbBuffer.RxRemoveObj( getObj=>rxAsdu, buffer := buffer ); (* Try to remove asdu from RX fifo *)
IF fbBuffer.bOk THEN (* success *)
CASE rxAsdu.ident.eType OF
C_TS_TA_1: (* Test command *)
txAsdu := rxAsdu;
txAsdu.ident.eCOT := eIEC870_COT_ACT_CON; (* send activation confirmation *)
fbBuffer.TxAddObj( putObj := txAsdu, buffer := buffer ); (* put asdu to the TX fifo *)
IF NOT fbBuffer.bOk THEN
;(* Report send buffer overflow error *)
END_IF
C_CS_NA_1: (* clock synchronisation *)
F_iecCopyStreamToBuffer( ADR( rxTT ), SIZEOF( rxTT ), rxAsdu.info.stream );
(*... *)
txAsdu := rxAsdu; (* dummy old time value *)
txAsdu.ident.eCOT := eIEC870_COT_ACT_CON; (* send activation confirmation *)
fbBuffer.TxAddObj( putObj := txAsdu, buffer := buffer ); (* put asdu to the TX fifo *)
IF NOT fbBuffer.bOk THEN
;(* Report send buffer overflow error *)
END_IF
END_CASE
END_IF
UNTIL NOT fbBuffer.bOk (* RX fifo is empty *)
END_REPEAT
Requirements
Development environment |
Target system type |
PLC libraries to be linked (category group) |
---|---|---|
TwinCAT v3.1.4012.0 |
PC oder CX (x86, x64, ARM) |
Tc2_IEC60870_5_10x (Communication->IEC60870) |