Examples - RS485 Network - Slave (Advanced)

Top  Previous  Next

//-----------------------------------------------------------------------------
// Slave.vpl, created 2003-04-07 15:44
//
// This is a small demonstration program, that shows how to communicate using 
// the serial routines (via RS485) in the RTCU units. Two projects are involved,
// Master and Slave.
//
//
// Format:
// To Slave FROM Master:
// <STX> <SRC> <DST> <DO Data-LSB> <DO Data-MSB> 
//                   <AO-1-LSB> <AO-1-MSB> 
//                   <AO-2-LSB> <AO-2-MSB> 
//                   <AO-3-LSB> <AO-3-MSB> 
//                   <AO-4-LSB> <AO-4-MSB> <ETX>
//
//
// To Master FROM Slave:
// <STX> <SRC> <DST> <DI Data-LSB> <DI Data-MSB> 
//                   <AI-1-LSB> <AI-1-MSB> 
//                   <AI-2-LSB> <AI-2-MSB> 
//                   <AI-3-LSB> <AI-3-MSB> 
//                   <AI-4-LSB> <AI-4-MSB> <ETX>
//
//
// STX = 0xFF
// ETX = 0xFE
// STUFF = 0x1B
// <DO-Data-LSB>/<DO-Data-MSB> = New status for digital outputs
// <AO-n-LSB>/<AO-n-MSB> = New data for analog output n
//
// <DI-Data-LSB>/<DI-Data-MSB> = New status for digital inputs
// <AI-n-LSB>/<AI-n-MSB> = New data for analog input n
//
//-----------------------------------------------------------------------------
INCLUDE rtcu.inc
 
//  Input variables that can be configured via the configuration dialog (These are global)
VAR_INPUT
   SerialPort  : SINT;                 | Serial port to communicate on (0=service port, 1=port 2)
   Din         : ARRAY[1..12] OF BOOL; | Digital inputs
   Ain         : ARRAY[1..4] OF INT;   | Analog inputs
   NodeSW      : ARRAY[1..3] OF BOOL;  | Dipswitches for node id (binary, SW1=LSB, SW3=MSB)
END_VAR;
 
//  Output variables that can be configured via the configuration dialog (These are global)
VAR_OUTPUT
   Dout        : ARRAY[1..12] OF BOOL; | Digital outputs
   Aout        : ARRAY[1..4] OF INT;   | Analog outputs
   RXLed       : BOOL;                 | changes state after each receive (with correct nodeid)
END_VAR;
 
//----------------------------------------------------------------------------
// Misc. helper functions
// Pack/Unpack INT and DINT's from an array of SINT
//----------------------------------------------------------------------------
function getINT:int;
var_input
   adr : ptr;
end_var;
memcpy(dst:=addr(getInt),src:=adr,len:=sizeof(getINT));
end_function;
 
function setINT;
var_input
   adr : ptr;
   v   : int;
end_var;
memcpy(dst:=adr,src:=addr(v),len:=sizeof(v));
end_function;
//----------------------------------------------------------------------------
 
 
PROGRAM Slave;
VAR
   MyNodeID    : SINT;
   RX          : serFrameReceiver;
   Len         : SINT;
   RxBuffer    : ARRAY[0..63] of SINT;
   TxBuffer    : ARRAY[0..63] of SINT;
   Index       : SINT; // Temporary variable/counter
END_VAR;
 
  MyNodeID:=SINT(NodeSW[3])*4 + SINT(NodeSW[2])*2 + SINT(NodeSW[1]);
  DebugFmt(message:="Slave running, nodeid=\1", v1:=MyNodeID);  
  
  serOpen(Port:=SerialPort, Baud:=57600, bit:=8, Parity:=0, RS485:=true);
  RX(port:=SerialPort, enable:=true, frame:=addr(rxbuffer), maxsize:=sint(sizeof(rxbuffer)), stuffch:=16#10, sof:=16#02, eof:=16#03);
 
BEGIN
  RX();
  // If a frame is received 
  IF RX.Ready THEN
    // and it is for this node...
    IF (MyNodeID = RXBuffer[1] AND RX.Size=12) THEN
       // Set the digital outputs
       FOR index:=0 TO 7 DO
          DOut[index+1]:=(RXBuffer[2] AND shl8(in:=1, n:=index)) <> 0;
       END_FOR;
       FOR index:=0 TO 3 DO
          DOut[index+9]:=(RXBuffer[3] AND shl8(in:=1, n:=index)) <> 0;
       END_FOR;
       // Set the analog outputs
       AOut[1]:=getINT(adr:=addr(RXBuffer[4]));
       AOut[2]:=getINT(adr:=addr(RXBuffer[6]));
       AOut[3]:=getINT(adr:=addr(RXBuffer[8]));
       AOut[4]:=getINT(adr:=addr(RXBuffer[10]));
       RXLed:=NOT RXLed;
       
       // Build response  
       TXBuffer[0]:=MyNodeID;
       TXBuffer[1]:=RXBuffer[0];
       // Build 2 bytes with status of digital inputs
       TXBuffer[2]:=0;
       TXBuffer[3]:=0;
       FOR index:=0 TO 7 DO
          IF DIn[index+1] THEN
             TXBuffer[2]:=TXBuffer[2] OR shl8(in:=1, n:=index);
          END_IF;   
       END_FOR;
       FOR index:=0 TO 3 DO
          IF DIn[index+9] THEN
             TXBuffer[3]:=TXBuffer[3] OR shl8(in:=1, n:=index);
          END_IF;   
       END_FOR;
       // Set analog values in response         
       setInt(adr:=addr(TXBuffer[4]), v:=Ain[1]);
       setInt(adr:=addr(TXBuffer[6]), v:=Ain[2]);
       setInt(adr:=addr(TXBuffer[8]), v:=Ain[3]);
       setInt(adr:=addr(TXBuffer[10]),v:=Ain[4]);
       // Send the response  
       serSendData(port:=SerialPort, data:=addr(TXBuffer), size:=12, stuffch:=16#10, sof:=16#02, eof:=16#03);
    ELSE
       DebugMsg(message:="Message not for this node !");
    END_IF;
    serFrameReceiveDone(port:=SerialPort);
  END_IF;
END;
 
END_PROGRAM;