📄 modbus_00_00.st
字号:
#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 + -