FB_IEC870_5_101TBufferCtrl

FB_IEC870_5_101TBufferCtrl 1:

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:

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_INPUT

VAR_INPUT
    putObj  : ST_IEC870_5_101AOGen;
END_VAR

putObj: Data unit (ASDU) to be sent.

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):

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)
Tc2_SerialCom (Communication->Serial)
Tc2_TcpIp (Communication->TcpIp)
Tc2_Utilities (System)