📄 modbus_00_00.st~
字号:
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
Adressbereich: M0F00 bis M0FFF
3,4 : Datenspeicher lesen
Adressbereich: M1000 bis M5E1D
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
*)
// _MOBU_INIT(); // initialisieren
REC(); // Empfang 乥erwachen
COMP(); // pr乫en und senden.
fehler := _mb_error;
state := READY$UDINT;
END_FUNCTION //VIRTUAL GLOBAL Modbus::CyWork
FUNCTION VIRTUAL GLOBAL Modbus::Init
IF _FirstScan = 1 THEN
_rd_zeiger := 0;
_delta_rd_zeiger := 0;
_poi_rxbuff := #_rx_buffer[0];
CLRBUFFer(256, _poi_rxbuff);
_INIT_COM1(BAUDRATE, FORMAT, _poi_rxbuff, RX_BSIZE); // COM1 init
SYS(130, AL:=5); // RX-Puffer l攕chen
_mb_error := 0;
_exception_code := 0;
_no_of_rxobjkts := 0;
END_IF;
END_FUNCTION //VIRTUAL GLOBAL Modbus::Init
FUNCTION Modbus::AddRoll
VAR_INPUT
Suma_512 : UINT;
Suma_d : uint;
END_VAR
VAR_OUTPUT
Summe : uint;
END_VAR
IF suma_512 < 512 - suma_d THEN
summe := suma_512 + suma_d;
ELSE
summe := suma_d - (512 - suma_512);
END_IF;
END_FUNCTION // Modbus::AddRoll
//[#ENGLISH]
//
//Diese Funktion berechnet den CRC16.
//
//ANZAHL : Anzahl der Bytes
//SOURCE : Pointer auf den Datenbereich
//ERGEBN : CRC-Ergebnis
//
FUNCTION AWL Modbus::CalkCRC
VAR_INPUT
Anzahl : UINT;
Source : ^DINT;
END_VAR
VAR_OUTPUT
Ergebn : hint;
END_VAR
L.DX 16#FFFF
L.CX anzahl
LES.DI source
CRC_LP
L E (DI)
CALL CRC16
INC DI
LOOP CRC_LP
S.DX ergebn
END_FUNCTION // Modbus::CalkCRC
//[#ENGLISH]
//
//Buffer l攕chen.
//
//ANZAHL von Bytes ab Datenspeicher DESTI auf $00 setzen.
//
FUNCTION AWL Modbus::ClrBuffer
VAR_INPUT
Anzahl : uint;
Desti : ^DINT;
END_VAR
PUSH ES
PUSH SI
L.CX anzahl
L.AL 16#00
LES.DI desti
REP
STOSB
POP SI
POP ES
END_FUNCTION // Modbus::ClrBuffer
//[#ENGLISH]
//
//Die empfangenen Daten werden gepr乫t.
//
//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 pr乫en
//
//-----------------------------------------------------------------------
//---- wieviel Zeichen sind schon da ??? ----
_delta_rd_zeiger := SUBBROLL(_rx_zeiger_akt, _rd_zeiger);
//---- 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 := ADDROLL(_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 : _rx_size := 6;
15,16 : _rx_size := 6 + 1 + _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 := _ADD_ROLL(_rd_scan, 1);
END_FOR;
//---- CRC berechnen ----
IF (_rx_size > 0) & (_rx_size < 254) THEN
_poi_latch := #_rd_latch[0];
_crc_calk := _CALK_CRC(_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;
_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]
//
//Daten kopieren.
//
//ANZAHL von Bytes werden von SOURCE nach DESTI kopiert.
//
//
FUNCTION AWL Modbus::CopyBuff
VAR_INPUT
Anzahl : uint;
Desti : ^DINT;
Source : ^DINT;
END_VAR
PUSH DS
PUSHF
CLD
L.CX anzahl
LES.DI desti
LDS.SI source
REP
MOVSB
POPF
POP DS
END_FUNCTION // Modbus::CopyBuff
//[#ENGLISH]
//
//Unterfunktion zur CRC-Berechnung
//
FUNCTION AWL Modbus::CRC16
VAR_INPUT
Zeich : sint;
END_VAR
VAR_OUTPUT
ergebn : int;
END_VAR
CLR AH
L.BX DX
XOR.BX AX
CLR BH
SHL.BX 00001
L.SI #CRCTAB()
L.AX C (BX+SI+002)
XCH.DH DL
CLR DH
XOR.DX AX
END_FUNCTION // Modbus::CRC16
//[#ENGLISH]
//
//Ein Byte lesen.
//
//In INHALT steht der Wert der von ADRESSE gelesen wird.
//
FUNCTION AWL Modbus::GetByte
VAR_INPUT
Adresse : uint;
END_VAR
VAR_OUTPUT
inhalt : hsint;
END_VAR
PUSH ES
PUSH SI
PUSH AX
L.AX 00000
L.ES AX
L.SI adresse
L.AL E (SI)
S.AL inhalt
POP AX
POP SI
POP ES
END_FUNCTION // Modbus::GetByte
//[#ENGLISH]
//
//V.24 ( COM1 ) Initialisierung.
//
//b_rate: Baudrate 0: 9600 Baud
// 1: 4800
// 2: 2400
// 3: 1200
// 4: 600
// 5: 300
// 6: 115200
// 7: 57600
// 8: 38400
// 9: 19200
//
//form: Datenformat 0: 8 Bit, 1 Stop, no Parity
// 1: 8 Bit, 2 Stop, no Parity
// 2: 8 Bit, 1 Stop, Parity even
// 3: 8 Bit, 2 Stop, Parity even
// 4: 8 Bit, 1 Stop, Parity odd
// 5: 8 Bit, 2 Stop, Parity odd
//
//dest: Far-Pointer auf Empfangspuffer
//
//p_size: Gr斸e des Puffers in Byte ( 256 )
//
//
//
//
FUNCTION Modbus::InitCom1
VAR_INPUT
b_rate : sint;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -