📄 modbus_00_00.st~
字号:
form : sint;
dest : ^DINT;
P_size : int;
END_VAR
SYS(130, AL:=1, AH:=b_rate, CL:=form, CH:=0, BX:=SEG(dest),
DX:=OFF(dest), SI:=p_size);
END_FUNCTION // Modbus::InitCom1
//[#ENGLISH]
//Empfang uberwachen
FUNCTION Modbus::Rec
//
// Empfang 乥erwachen.
//
//
//---- COM1 Zeiger holen ----
_rx_zeiger_old := _rx_zeiger_akt; // Alten merken
SYS(130, AL:=6); // Neuen holen
_rx_zeiger_akt := BX;
//---- _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;
//---- 歜erlauf ----
IF _timeout_ctr > TIMEOUT_PRESET THEN // Time-Out 歜erlauf ???
_timeout := 1;
ELSE
_timeout := 0;
END_IF;
//---- _timeout mitz刪len ----
IF _Impuls10ms = 1 THEN
_timeout_ctr += 1;
END_IF;
END_FUNCTION // Modbus::Rec
//[#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. M0F00 ... M0FFF )
// Funktion 2 ( Read Input Status. M0F00 ... M0FFF )
// Funktion 3 ( Read Holding Register. M1000 ... M5E1D )
// Funktion 4 ( Read Input Register. M1000 ... M5E1D )
// Funktion 15 ( Force Multiple Coils. M0F00 ... M0FFF )
// Funktion 16 ( Preset Multiple Regs. M1000 ... M5E1D )
// 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#F00 | _start_address > 16#FFF THEN
_exception_code := 2; // illegal data address
ELSE
IF _no_of_points < 1 | _no_of_points > 127 THEN
_exception_code := 3; // illegal data value
ELSE
_tx_buffer[0] := SLAVE_ADDRESS; // 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[2*_a + 3] := _GET_BYTE(4*_a + _start_address+0); // Dat
_tx_buffer[2*_a + 4] := _GET_BYTE(4*_a + _start_address+1); // Dat
_a += 1;
END_WHILE
_n_bytes := 3 + _tx_buffer[2]; // Header plus Daten
_crc_result := _CALK_CRC(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
SYS(130, AL:=2, CX:=_n_bytes, BX:=SEG(_poi_tx_buff), // senden
DX:=OFF(_poi_tx_buff));
IF CF 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 < 16#1000 | _start_address > 16#5E1D THEN
_exception_code := 2; // illegal data address
ELSE
IF _no_of_points < 1 | _no_of_points > 127 THEN
_exception_code := 3; // illegal data value
ELSE
_tx_buffer[0] := SLAVE_ADDRESS; // 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] := _GET_BYTE(2*_a + _start_address+1); // Data H
_tx_buffer[2*_a + 4] := _GET_BYTE(2*_a + _start_address+0); // Data L
_a += 1;
END_WHILE
_n_bytes := 3 + _tx_buffer[2]; // Header plus Daten
_crc_result := _CALK_CRC(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
SYS(130, AL:=2, CX:=_n_bytes, BX:=SEG(_poi_tx_buff), // senden
DX:=OFF(_poi_tx_buff));
IF CF 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 = 3 und 4
//-----------------------------------------------------------------------
// Funktion No.: 15; Beschreiben der Ausg刵ge
//
IF _m_function = 15 THEN
IF _start_address < 16#0F00 | _start_address > 16#0FFF THEN
_exception_code := 2; // illegal data address
ELSE
IF _no_of_points < 1 | _no_of_points > 127 THEN
_exception_code := 3; // illegal data value
ELSE
//---- Ausg刵ge beschreiben ----
_a := 0;
_set_address := _start_address;
_set_mask := 16#ff;
_bit_ctr := _no_of_points;
WHILE _a < _rd_latch[6] DO // [6] = Byte Count
IF _bit_ctr < 8 THEN // falls kein ganzes Byte...
_shift_ctr := TO_USINT(8 - _bit_ctr);
_set_mask := _set_mask SHR _shift_ctr; // dann maskieren.
END_IF
IF (_set_address AND 2#00000011) = 2#00000010 THEN
_set_address += 1; // falls Adress-Loch, dann weiter.
END_IF
IF (_set_address AND 2#00000011) = 2#00000011 THEN
_set_address += 1;
END_IF
IF _bit_ctr < 8 THEN // falls kein ganzes Byte
_old_byte := _GET_BYTE(_set_address); // altes Bitmuster holen
_bin_1 := 16#ff XOR _set_mask; // Maske invertieren
_old_byte := _old_byte AND _bin_1; // neuen Teil l攕chen
_bin_1 := _rd_latch[7+_a] AND _set_mask;// neuen Teil vorbereiten
_bin_1 := _bin_1 OR _old_byte; // Alten dazu
_SET_BYTE(_set_address, _bin_1); // raus
ELSE
_SET_BYTE(_set_address, _rd_latch[7+_a]); // [7] = 1.Datenbyte
END_IF
_a += 1;
_set_address += 1;
_bit_ctr -= 8;
END_WHILE
//---- Response --------------------------
_tx_buffer[0] := SLAVE_ADDRESS; // Header aufbauen
_tx_buffer[1] := _m_function;
_tx_buffer[2] := _rd_latch[2]; // Coil Address Hi
_tx_buffer[3] := _rd_latch[3]; // Coil Address Lo
_tx_buffer[4] := _rd_latch[4]; // Quantity of Coils Hi
_tx_buffer[5] := _rd_latch[5]; // Quantity of Coils Lo
_n_bytes := 6; // Header = 6 Bytes
_crc_result := _CALK_CRC(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
SYS(130, AL:=2, CX:=_n_bytes, BX:=SEG(_poi_tx_buff), // senden
DX:=OFF(_poi_tx_buff));
IF CF 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 = 15
//-----------------------------------------------------------------------
// Funktion No.: 16; Beschreiben der Datenspeicher
//
IF _m_function = 16 THEN
IF _start_address < 16#1000 | _start_address > 16#5E1D THEN
_exception_code := 2; // illegal data address
ELSE
IF _no_of_points < 1 | _no_of_points > 127 THEN
_exception_code := 3; // illegal data value
ELSE
//---- Datenspeicher beschreiben ----
_a := 0;
_set_address := _start_address;
WHILE _a < _rd_latch[5] DO // [5] = No. of Registers
_SET_BYTE(_set_address+1, _rd_latch[2*_a + 7]); // [7] = 1.Hi-Byte
_SET_BYTE(_set_address+0, _rd_latch[2*_a + 8]); // [8] = 1.Lo-Byte
_a += 1;
_set_address += 2;
END_WHILE;
//---- Response --------------------------
_tx_buffer[0] := SLAVE_ADDRESS; // Header aufbauen
_tx_buffer[1] := _m_function;
_tx_buffer[2] := _rd_latch[2]; // Starting Address Hi
_tx_buffer[3] := _rd_latch[3]; // Starting Address Lo
_tx_buffer[4] := _rd_latch[4]; // No of Regs Hi
_tx_buffer[5] := _rd_latch[5]; // No of Regs Lo
_n_bytes := 6; // Header = 6 Bytes
_crc_result := _CALK_CRC(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
SYS(130, AL:=2, CX:=_n_bytes, BX:=SEG(_poi_tx_buff), // senden
DX:=OFF(_poi_tx_buff));
IF CF 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 = 16
//-----------------------------------------------------------------------
// Fehler (Exception Response); sendet Fehlermeldung
//
IF _exception_code > 0 THEN
_tx_buffer[0] := SLAVE_ADDRESS; // Header aufbauen
_tx_buffer[1] := _m_function OR 16#80;
_tx_buffer[2] := _exception_code;
_n_bytes := 3;
_crc_result := _CALK_CRC(TO_UINT(_n_bytes), _poi_tx_buff); // CRC..
(_poi_tx_buff$^HINT + _n_bytes)^ := _crc_result; // hinten dran
_n_bytes += 2;
SYS(130, AL:=2, CX:=_n_bytes, BX:=SEG(_poi_tx_buff), // senden
DX:=OFF(_poi_tx_buff));
IF CF THEN
_tx_back := 1; // Fehler
ELSE
_tx_back := 0; // in Ordnung
END_IF // CF
END_IF // Exception Code
END_FUNCTION // Modbus::Send
//[#ENGLISH]
//
//Schreibt den Inhalt von WERT an die ADRESSE.
FUNCTION AWL Modbus::SetByte
VAR_INPUT
Adresse : uint;
Wert : hsint;
END_VAR
PUSH AX
PUSH ES
PUSH DI
L.AX 00000
L.ES AX
L.AL wert
L.DI adresse
S.AL E (DI)
POP DI
POP ES
POP AX
END_FUNCTION // Modbus::SetByte
FUNCTION Modbus::SubbRoll
VAR_INPUT
subtr : uint;
subtrh : uint;
END_VAR
VAR_OUTPUT
diff : uint;
END_VAR
IF subtr >= subtrh THEN
diff := subtr - subtrh;
ELSE
diff := 512 - subtrh + subtr;
END_IF;
END_FUNCTION // Modbus::SubbRoll
FUNCTION TAB Modbus::CRCTab
////// Tabelle, aus der sich die jeweilige Checksumme geholt wird//$ 0000,$ C0C1,$ C181,$ 0140,$ C301,$ 03C0,$ 0280,$ C241$ C601,$ 06C0,$ 0780,$ C741,$ 0500,$ C5C1,$ C481,$ 0440$ CC01,$ 0CC0,$ 0D80,$ CD41,$ 0F00,$ CFC1,$ CE81,$ 0E40$ 0A00,$ CAC1,$ CB81,$ 0B40,$ C901,$ 09C0,$ 0880,$ C841$ D801,$ 18C0,$ 1980,$ D941,$ 1B00,$ DBC1,$ DA81,$ 1A40$ 1E00,$ DEC1,$ DF81,$ 1F40,$ DD01,$ 1DC0,$ 1C80,$ DC41$ 1400,$ D4C1,$ D581,$ 1540,$ D701,$ 17C0,$ 1680,$ D641$ D201,$ 12C0,$ 1380,$ D341,$ 1100,$ D1C1,$ D081,$ 1040$ F001,$ 30C0,$ 3180,$ F141,$ 3300,$ F3C1,$ F281,$ 3240$ 3600,$ F6C1,$ F781,$ 3740,$ F501,$ 35C0,$ 3480,$ F441$ 3C00,$ FCC1,$ FD81,$ 3D40,$ FF01,$ 3FC0,$ 3E80,$ FE41$ FA01,$ 3AC0,$ 3B80,$ FB41,$ 3900,$ F9C1,$ F881,$ 3840$ 2800,$ E8C1,$ E981,$ 2940,$ EB01,$ 2BC0,$ 2A80,$ EA41$ EE01,$ 2EC0,$ 2F80,$ EF41,$ 2D00,$ EDC1,$ EC81,$ 2C40$ E401,$ 24C0,$ 2580,$ E541,$ 2700,$ E7C1,$ E681,$ 2640$ 2200,$ E2C1,$ E381,$ 2340,$ E101,$ 21C0,$ 2080,$ E041$ A001,$ 60C0,$ 6180,$ A141,$ 6300,$ A3C1,$ A281,$ 6240$ 6600,$ A6C1,$ A781,$ 6740,$ A501,$ 65C0,$ 6480,$ A441$ 6C00,$ ACC1,$ AD81,$ 6D40,$ AF01,$ 6FC0,$ 6E80,$ AE41$ AA01,$ 6AC0,$ 6B80,$ AB41,$ 6900,$ A9C1,$ A881,$ 6840$ 7800,$ B8C1,$ B981,$ 7940,$ BB01,$ 7BC0,$ 7A80,$ BA41$ BE01,$ 7EC0,$ 7F80,$ BF41,$ 7D00,$ BDC1,$ BC81,$ 7C40$ B401,$ 74C0,$ 7580,$ B541,$ 7700,$ B7C1,$ B681,$ 7640$ 7200,$ B2C1,$ B381,$ 7340,$ B101,$ 71C0,$ 7080,$ B041$ 5000,$ 90C1,$ 9181,$ 5140,$ 9301,$ 53C0,$ 5280,$ 9241$ 9601,$ 56C0,$ 5780,$ 9741,$ 5500,$ 95C1,$ 9481,$ 5440$ 9C01,$ 5CC0,$ 5D80,$ 9D41,$ 5F00,$ 9FC1,$ 9E81,$ 5E40$ 5A00,$ 9AC1,$ 9B81,$ 5B40,$ 9901,$ 59C0,$ 5880,$ 9841$ 8801,$ 48C0,$ 4980,$ 8941,$ 4B00,$ 8BC1,$ 8A81,$ 4A40$ 4E00,$ 8EC1,$ 8F81,$ 4F40,$ 8D01,$ 4DC0,$ 4C80,$ 8C41$ 4400,$ 84C1,$ 8581,$ 4540,$ 8701,$ 47C0,$ 4680,$ 8641$ 8201,$ 42C0,$ 4380,$ 8341,$ 4100,$ 81C1,$ 8081,$ 4040////
END_FUNCTION //TAB Modbus::CRCTab
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -