⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modbus_00_00.st

📁 moudbus通讯协议, moudbus通讯协议, moudbus通讯协议,
💻 ST
📖 第 1 页 / 共 2 页
字号:
#ifdef LASAL_VERSION
#if LASAL_VERSION > 57
//LASAL_INCLUDES
 #include "..\Header Files\Needs\Modbus.h"
 
#endif//LASALVERSION > 57
#endif//LASAL_VERSION


#include <.\lsl_st_serial.h>


FUNCTION VIRTUAL GLOBAL Modbus::CyWork
VAR_INPUT
	EAX		: UDINT;
END_VAR
VAR_OUTPUT
	state		: UDINT;
END_VAR
(*


MODBUS RTU Protokoll          18.06.97 Ch. Kalleitner

1. Die COM1 wird als Modbus-Schnittstelle initialisiert.
   Die privaten Konstanten sind eventuell anzupassen:
          BAUDRATE        = V.24 Baudrate
          FORMAT          = V.24 Format
          SLAVE_ADDRESS   = Modbus Slave-Address

2. Der Empfang wird 歜erwacht.

3. Wird eine verwertbare Funktion erkannt, so wird
   Ausgewertet und eine Antwort gesendet. Folgende
   Funktionen sind m攇lich:
          1,2 : Ein-Ausg刵ge lesen
          3,4 : Datenspeicher lesen
		  5,6 : Datenpeicher schreiben 	
          15  : Ausg刵ge schreiben
          16  : Datenspeicher schreiben

   Falls eine falsche Funktionsnummer oder ein Adressbereich
   kommt, wird eine Fehlermeldung (Exception Code) gesendet.

4. Das Modul liefert einen Fehlercode.
   Die Bits im FEHLER haben folgende Bedeutung:
       $00   = kein Fehler

   Bit 7 MSB = -
   Bit 6     = -
   Bit 5     = V.24 Sendefehler
   Bit 4     = Daten falsch
   Bit 3     = Adressbereich falsch
   Bit 2     = Funktion ist falsch
   Bit 1     = CRC Fehler
   Bit 0 LSB = Slave - Adresse falsch


*)

// **********************************************************************************
// *************     Serial COM S_Init      *****************************************
// **********************************************************************************
// **																				*
// ** initializes a COM with the Clientsettings										*
// **																				*
// ** --> NEEDED SERVER's:															*
// **																				*
// ** -ComNr:  SERUSERCOM_1 ~ f黵 COM1 ..1  -Baudrate: SERUSERBAUD_300    .. 0		*
// **          SERUSERCOM_2 ~ f黵 COM2 ..2             SERUSERBAUD_600    .. 1		*
// **          SERUSERCOM_3 ~ f黵 COM3 ..3             SERUSERBAUD_1200   .. 2		*
// **          SERUSERCOM_4 ~ f黵 COM4 ..4             SERUSERBAUD_2400   .. 3		*
// **                                                  SERUSERBAUD_4800   .. 4		*
// ** -SerParity (Parity-Bits):                        SERUSERBAUD_9600   .. 5		*
// **          SERUSERPARITY_NONE ..0                  SERUSERBAUD_14400  .. 6		*
// **          SERUSERPARITY_ODD  ..1                  SERUSERBAUD_19200  .. 7		*
// **          SERUSERPARITY_EVEN ..2                  SERUSERBAUD_38400  .. 8		*
// **          SERUSERPARITY_MARK ..3(HIGH Parity)     SERUSERBAUD_56000  .. 9		*
// **          SERUSERPARITY_SPACE..4(LOW Parity)      SERUSERBAUD_115200 ..10		*
// **																				*
// ** -StopBit   : 1 or 2 															*
// ** -wordlength: 5, 6, 7 or 8														*
// **																				*
// *** ---------------------------------------------------------------------------- *
// **  <-- OUTPUT's:																*
// **  - Handle of COM																*
// *** ---------------------------------------------------------------------------- *
// **																				*
// **  !!!ATTENTION: Handle will be needed for other functions of SERIAL interface  *
// ** ----------------------------------------------------------------------------- *
// ** created  : RM :  KW 50/01													    *
// **********************************************************************************

//   SEND();
 REC();           // Empfang uberwachen
 COMP();          // prufen und senden.
 fehler := _mb_error;



	state := READY$UDINT;
END_FUNCTION //VIRTUAL GLOBAL Modbus::CyWork

FUNCTION VIRTUAL GLOBAL Modbus::Init

 if firstscan = 0 then 

  _poi_rxbuff      := #_rx_buffer[0];
  CLRBUFFer(256, _poi_rxbuff);

	DataSize:=DataMemory.GetSize();

	if DataSize = 0 then 
		
		DataSize:=1000;
		DataMemory.SetSize(udSize:=DataSize);

	end_if;
	DataPtr:=DataMemory.GetDataPtr();


	IOSize:=I_O_Memory.GetSize();

	if IOSize = 0 then 
		
		IOSize:=1000;
		I_O_Memory.SetSize(udSize:=IOSize);

	end_if;
	IOPtr:=I_O_Memory.GetDataPtr();

	Slave_Address:=Slave_Address.read();
	ComNr:=ComNr.read();
	Baudrate:=Baudrate.read();
	StopBit:=StopBit.read();
	Wordlength:=Wordlength.read();
	SerParity:=SerParity.read();
	Timeout_preset:=Timeout_preset.read();

	system.GetObjectInfo(thisobj0:=this, tasktype0:=OBJ_CT, objinfo:=#ObjInformation);
	if ObjInformation.orgperiod = 0 then
		ObjInformation.orgperiod:=1;
	end_if;

	  pHandle := SERUSER_Init(ComNr$UINT,Baudrate$UINT,SerParity$UINT,StopBit$UINT,wordlength$UINT);


	  Error_S := SERUSER_GetError(pHandle);

	
	if Error_S = 0 then
		Status:=ok;
	else
		Status:=ErrorModbus;
	end_if;
		ENABLE_ME();
		firstscan:=1;
	end_if;

// *********************************************************************************************
// ****************************     Serial COM GetError    *************************************
// *********************************************************************************************
// ** Wird der Funktion SERUSER_GetError()-NIL 黚ergeben. Wird 黚er allgemein anstehenden Error 黚erpr黤t.      ***
// ** Wird ein g黮tiges Handle 黚ergeben, wird speziell f黵 die Einstellungen des            ***
// ** Handles 黚erpr黤t. 																	 ***
// ** <-- Error_Nr = Error Code                                                              ***
// ** ---------------------------------------------------------------------------------------***
// ****																						 ***
// **            !!!!    ERROR CODE TABELLE   !!!!											 ***
// **																						 ***
// **   0 .. SERERROR_NONE																	 ***
// ** - 1 .. SERERROR_COMNUM     -> ComNr <> 1-4											 ***
// ** - 2 .. SERERROR_BAUDTABLE  -> OS Error												 ***
// ** - 3 .. SERERROR_BAUDRATE   -> Baudrate <> 0-10										 ***
// ** - 4 .. SERERROR_PARITY     -> Parity <> 0-4											 ***
// ** - 5 .. SERERROR_STOPBIT    -> Stopbits <> 1-2											 ***
// ** - 6 .. SERERROR_WORDLEN																 ***
// ** -10 .. SERERROR_INUSE      -> Com bereits in Verwendung								 ***
// ** -11 .. SERERROR_OSINUSE    -> Com wird bereits vom OS verwendet 						 ***
// ** -12 .. SERERROR_NOTAVAIL   -> CPU verf黦t 黚er die angegebene COM nicht				 ***
// ** -13 .. SERERROR_NOMEM      -> OS Error												 ***
// ** -14 .. SERERROR_NOHANDLE																 ***
// ** -15 .. SERERROR_PARAMETER  -> einer der angegebenen Funktionen wurde einfalscher Pointer 黚erg. (z.B:NIL)
// ** -16 .. SERERROR_RECVBUF    -> SetBuffer erhielt einen zukleinen Wert f黵 Empf.buffergr鲞e: muss >= 128 sein
// ** -17 .. SERERROR_SENDBUF    -> der Sendefunktion wurde NIL 黚ergeben					 ***
// ** -19 .. SERERROR_RECVERROR  -> RecvChar od. RecvBlock wurden aufgerufen, es befinden sich aber KEINE Daten im Empf.buffer
// ** -20 .. SERERROR_SENDERROR  -> Sendevorgang konnte nicht abgeschlossen werden. (Unterbr., Sendbuffer voll, ...)
// ** ---------------------------------------------------------------------------------------***
// *********************************************************************************************

END_FUNCTION //VIRTUAL GLOBAL Modbus::Init
//[#ENGLISH]
//Empfang uberwachen
FUNCTION  Modbus::Rec
//
// Empfang uberwachen.
//
//

//---- COM1 Zeiger holen ----
 _rx_zeiger_old := _rx_zeiger_akt;         // Alten merken


ret0:=0;

while Ret0 = 0 do

	
		 ret0 := SERUSER_RecvChar(pHandle, #RXBuffer);

		 if ret0 = 0 then
			_rx_buffer[_rx_zeiger_akt]:=RXBuffer;
			_rx_zeiger_akt+=1;

		 end_if;

End_while;

//---- _timeout reset ----
 IF _rx_zeiger_akt <> _rx_zeiger_old THEN  // falls ein Zeichen kommt...
  IF _timeout = 1 THEN
   _timeout := 0;
   _rd_zeiger := _rx_zeiger_old;
   _delta_rd_zeiger := 0;
  END_IF;
  _timeout_ctr := 0;                      // Time-Out reset.
 END_IF;

//---- uberlauf ----
 IF _timeout_ctr > TIMEOUT_PRESET THEN    // Time-Out uberlauf ???
  _timeout := 1;
 ELSE
  _timeout := 0;
 END_IF;

//---- _timeout mitzahlen ----
  _timeout_ctr += ObjInformation.orgperiod$UINT;


END_FUNCTION // Modbus::Rec


//[#ENGLISH]
//
//Die empfangenen Daten werden gepruft.
//
//1. Die Anzahl der empfangenen Zeichen richtig ?
//2. Slave-Address ?
//3. Funktionscode ?
//4. CRC berechnen und vergleichen
//5. Alles ok ?, dann SEND aufrufen
//6. Fehlercode berechnen
//
FUNCTION  Modbus::Comp
//-----------------------------------------------------------------------
//
// Empfangenes Objekt prufen
//
//-----------------------------------------------------------------------

//---- wieviel Zeichen sind schon da ??? ----
 _delta_rd_zeiger := _rx_zeiger_akt;

//---- Header schon empfangen ----
 IF _delta_rd_zeiger < 8 THEN
  RETURN;
 END_IF;

//---- Header holen ----
 _rd_scan := _rd_zeiger;
 FOR _a := 0 TO 7 DO
  _rd_latch[_a] := _rx_buffer[_rd_scan];
  _rd_scan   += 1;
 END_FOR;


//---- Adresse pr乫en ----
 IF _rd_latch[0] <> SLAVE_ADDRESS THEN
  _mb_error        := _mb_error OR 1;
  RETURN;
 ELSE // Slave Address ok

//---- wieviel werden es ??? ----
 _m_function := _rd_latch[1];
   CASE _m_function OF
    1,2,3,4,5       : _rx_size := 6;
    6,15,16,17      : _rx_size := 7 + _rd_latch[6];
    ELSE            _rx_size := 6;
                    _exception_code := 1;
   END_CASE;

//---- alle empfangen, auch CRC (2 Bytes) ??? ----
 IF _delta_rd_zeiger < _rx_size + 2 THEN
  RETURN;
 END_IF;

//---- jetzt alle kopieren ----
  _rd_scan := _rd_zeiger;
  FOR _a := 0 TO _rx_size + 1 DO
   _rd_latch[_a] := _rx_buffer[_rd_scan];
   _rd_scan   += 1;
  END_FOR;

//---- CRC berechnen ----
   IF (_rx_size > 0) & (_rx_size < 254) THEN
    _poi_latch     := #_rd_latch[0];
    _crc_calk      := CALKCRC(_rx_size, _poi_latch);  // Der Berechnete
    _crc_rx        := ((_poi_latch + _rx_size)$^HINT)^; // Der Empfangene
   ELSE
    _crc_rx        := 0;
    _crc_calk      := 1;
   END_IF; // CRC berechnen

//---- CRC vergleichen ----
   IF _crc_rx = _crc_calk THEN
    _start_address := _rd_latch[2];
    _start_address := _start_address SHL 8 OR _rd_latch[3];
    _no_of_points  := _rd_latch[4];
    _no_of_points  := _no_of_points SHL 8 OR _rd_latch[5];
    _no_of_rxobjkts  += 1;
    _mb_error      := 0;

//---- senden ----
    SEND();
    _crc_rx        := 0;
    _crc_calk      := 1;
   ELSE                                               // CRC ist falsch
    _start_address := 0;
    _no_of_points  := 0;
    _mb_error      := _mb_error OR 2;
   END_IF;

//---- ok, Zeiger nachziehen ---
  _rd_zeiger       := _rx_zeiger_akt:=0;
  _delta_rd_zeiger := 0;
 END_IF; // Slave Adresse ok


//---- Fehler-Code berechnen ----
  CASE _exception_code OF
    1: _mb_error := _mb_error OR 2#00000100;
    2: _mb_error := _mb_error OR 2#00001000;
    3: _mb_error := _mb_error OR 2#00010000;
  END_CASE;

  IF _tx_back = 1 THEN
   _mb_error := _mb_error  OR 2#00100000;
  ELSE
   _mb_error := _mb_error AND 2#11011111;
  END_IF;




END_FUNCTION // Modbus::Comp
//[#ENGLISH]
//
//Funktion auswerten und Senden.
//
//Die Funktion SEND wertet den Funktionscode aus,
//f乭rt die entsprechende Aktion aus und sendet eine
//Antwort. Ist die Funktion, der Adressbereich oder
//der Wertbereich falsch, so wird der EXCEPTION CODE
//gesendet.
//
//Ausgef乭rte Funktionen:   1:  Ein-Ausg刵ge lesen
//                          2:  -''-
//                          3:  Datenregister lesen
//                          4:  -''-
//                         15:  Ausg刵ge schreiben
//                         16:  Datenspeicher schreiben
//
//
//
//
//
FUNCTION  Modbus::Send
//
//-----------------------------------------------------------------------
// Funktion 1         ( Read Coil Status.      )
// Funktion 2         ( Read Input Status.     )
// Funktion 3         ( Read Holding Register. )
// Funktion 4         ( Read Input Register.   )
// Funktion 5         ( Force single Coil.     )
// Funktion 6         ( Preset single Regs.    )
// Funktion 15        ( Force Multiple Coils.  )
// Funktion 16        ( Preset Multiple Regs.  )
// Fehler R乧kmeldung ( Exception Response     )
//-----------------------------------------------------------------------


//---- Sende - Puffer l攕chen ----
 _poi_tx_buff := #_tx_buffer[0];
 CLRBUFFer(256, _poi_tx_buff);


//-----------------------------------------------------------------------
// Funktion No.: 1 und 2;   Lesen der Ein- und Ausg刵ge.
//
IF _m_function = 1 | _m_function = 2 THEN
 IF _start_address < 16#00 | _start_address > (IOSize-((_no_of_points shr 8)+1)) THEN
  _exception_code := 2;                          // illegal data address
 ELSE
  IF _no_of_points < 0 | _no_of_points > 127 THEN
   _exception_code := 3;                           // illegal data value
  ELSE
   _tx_buffer[0] := SLAVE_ADDRESS$USINT;                    // Header aufbauen
   _tx_buffer[1] := _m_function;
   _tx_buffer[2] := 1+((_rd_latch[5]-1) SHR 3);    // von Bits nach Bytes
   _a := 0;
   WHILE _a < _tx_buffer[2] DO
    _tx_buffer[_a + 3] := GETBiT(_a + _start_address);  // Dat
    _a += 1;
   END_WHILE;
   _n_bytes := 3 + _tx_buffer[2];                    // Header plus Daten
   _crc_result := CALKCRC(TO_UINT(_n_bytes), _poi_tx_buff);    // CRC..
   (_poi_tx_buff$^HINT + _n_bytes)^ := _crc_result;        // hinten dran
   _n_bytes += 2;                                    // sind 2 Byte mehr

	ret1 := SERUSER_Send(pHandle, _poi_tx_buff, _n_bytes, #WrLen1);

   IF ret1 THEN
    _tx_back := 1;                                             // Fehler
   ELSE
    _tx_back := 0;                                         // in Ordnung
   END_IF; // CF
   _exception_code  := 0;
   _mb_error        := 0;
  END_IF // _no_of_points
 END_IF // Start_Adresse
END_IF // Funktion = 1 und 2


//-----------------------------------------------------------------------
// Funktion No.: 3 und 4;   Lesen der Datenspeicher
//
IF _m_function = 3 | _m_function = 4 THEN
 IF _start_address < 000 | _start_address > (DataSize-(_no_of_points shl 1)) THEN
  _exception_code := 2;                          // illegal data address
 ELSE
  IF _no_of_points < 0 | _no_of_points > 15 THEN
   _exception_code := 3;                           // illegal data value
  ELSE
   _tx_buffer[0] := SLAVE_ADDRESS$USINT;                    // Header aufbauen
   _tx_buffer[1] := _m_function;
   _tx_buffer[2] := _rd_latch[5] * 2;                       // Byte Count
   _a := 0;
   WHILE _a < _rd_latch[5] DO                       // [5] = No of Points
    _tx_buffer[2*_a + 3] := GETBYTE(2*_a + _start_address+1); // Data H
    _tx_buffer[2*_a + 4] := GETBYTE(2*_a + _start_address+0); // Data L
    _a += 1;
   END_WHILE
   _n_bytes := 3 + _tx_buffer[2];                    // Header plus Daten
   _crc_result := CALKCRC(TO_UINT(_n_bytes), _poi_tx_buff);   // CRC..
   (_poi_tx_buff$^HINT + _n_bytes)^ := _crc_result;      // hinten dran
   _n_bytes += 2;                                    // sind 2 Byte mehr

	ret1 := SERUSER_Send(pHandle, _poi_tx_buff, _n_bytes, #WrLen1);

   IF ret1 THEN
    _tx_back := 1;                                             // Fehler
   ELSE
    _tx_back := 0;                                         // in Ordnung
   END_IF // CF
   _exception_code  := 0;
   _mb_error        := 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -