📄 modbus_00_00.st
字号:
END_IF // _no_of_points
END_IF // Start_Adresse
END_IF // Funktion = 3 und 4
//-----------------------------------------------------------------------
// Funktion No.: 5; Beschreiben der Ausg刵g
//
IF _m_function = 5 THEN
IF _start_address < 16#000 | _start_address > IOSize THEN
_exception_code := 2; // illegal data address
ELSE
//---- Ausg刵ge beschreiben ----
// _a := 0;
_set_address := _start_address;
if _rd_latch[4] = 16#ff then
SETBit(_set_address, 1);
else
SETBit(_set_address, 0);
end_if;
//---- Response --------------------------
_tx_buffer[0] := SLAVE_ADDRESS$USINT; // 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 := 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 = 5
//-----------------------------------------------------------------------
// Funktion No.: 6; Beschreiben der Datenspeicher
//
IF _m_function = 6 THEN
IF _start_address < 0 | _start_address > (DataSize-2) THEN
_exception_code := 2; // illegal data address
ELSE
//---- Datenspeicher beschreiben ----
_set_address := _start_address;
SETBYTE(_set_address+1, _rd_latch[7]); // [7] = 1.Hi-Byte
SETBYTE(_set_address+0, _rd_latch[8]); // [8] = 1.Lo-Byte
//---- Response --------------------------
_tx_buffer[0] := SLAVE_ADDRESS$USINT; // 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 := 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 // Start_Adresse
END_IF // Funktion = 6
//-----------------------------------------------------------------------
// Funktion No.: 15; Beschreiben der Ausg刵ge
//
IF _m_function = 15 THEN
IF _start_address < 00 | _start_address > IOSize 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 := GETBYTE(_set_address); // altes Bitmuster holen
_bin_1 := 16#ff XOR _set_mask; // Maske invertieren
_old_byte := _old_byte AND _bin_1; // neuen Teil loschen
_bin_1 := _rd_latch[7+_a] AND _set_mask;// neuen Teil vorbereiten
_bin_1 := _bin_1 OR _old_byte; // Alten dazu
SETBYTE(_set_address, _bin_1); // raus
ELSE
SETBYTE(_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$USINT; // 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 := 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 = 15
//-----------------------------------------------------------------------
// Funktion No.: 16; Beschreiben der Datenspeicher
//
IF (_m_function = 16) | (_m_function = 17) THEN
IF _start_address < 000 | _start_address > DataSize 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
SETBYTE(_set_address+1, _rd_latch[2*_a + 7]); // [7] = 1.Hi-Byte
SETBYTE(_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$USINT; // 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 := 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 = 16
//-----------------------------------------------------------------------
// Fehler (Exception Response); sendet Fehlermeldung
//
IF _exception_code > 0 THEN
_tx_buffer[0] := SLAVE_ADDRESS$USINT; // Header aufbauen
_tx_buffer[1] := _m_function OR 16#80;
_tx_buffer[2] := _exception_code;
_n_bytes := 3;
_crc_result := CALKCRC(TO_UINT(_n_bytes), _poi_tx_buff); // CRC..
(_poi_tx_buff$^HINT + _n_bytes)^ := _crc_result; // hinten dran
_n_bytes += 2;
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
END_IF // Exception Code
END_FUNCTION // Modbus::Send
FUNCTION TAB Modbus::CRCTab
//
//
// Tabelle, aus der sich die jeweilige Checksumme geholt wird
//
16#0000,16#C0C1,16#C181,16#0140,16#C301,16#03C0,16#0280,16#C241
16#C601,16#06C0,16#0780,16#C741,16#0500,16#C5C1,16#C481,16#0440
16#CC01,16#0CC0,16#0D80,16#CD41,16#0F00,16#CFC1,16#CE81,16#0E40
16#0A00,16#CAC1,16#CB81,16#0B40,16#C901,16#09C0,16#0880,16#C841
16#D801,16#18C0,16#1980,16#D941,16#1B00,16#DBC1,16#DA81,16#1A40
16#1E00,16#DEC1,16#DF81,16#1F40,16#DD01,16#1DC0,16#1C80,16#DC41
16#1400,16#D4C1,16#D581,16#1540,16#D701,16#17C0,16#1680,16#D641
16#D201,16#12C0,16#1380,16#D341,16#1100,16#D1C1,16#D081,16#1040
16#F001,16#30C0,16#3180,16#F141,16#3300,16#F3C1,16#F281,16#3240
16#3600,16#F6C1,16#F781,16#3740,16#F501,16#35C0,16#3480,16#F441
16#3C00,16#FCC1,16#FD81,16#3D40,16#FF01,16#3FC0,16#3E80,16#FE41
16#FA01,16#3AC0,16#3B80,16#FB41,16#3900,16#F9C1,16#F881,16#3840
16#2800,16#E8C1,16#E981,16#2940,16#EB01,16#2BC0,16#2A80,16#EA41
16#EE01,16#2EC0,16#2F80,16#EF41,16#2D00,16#EDC1,16#EC81,16#2C40
16#E401,16#24C0,16#2580,16#E541,16#2700,16#E7C1,16#E681,16#2640
16#2200,16#E2C1,16#E381,16#2340,16#E101,16#21C0,16#2080,16#E041
16#A001,16#60C0,16#6180,16#A141,16#6300,16#A3C1,16#A281,16#6240
16#6600,16#A6C1,16#A781,16#6740,16#A501,16#65C0,16#6480,16#A441
16#6C00,16#ACC1,16#AD81,16#6D40,16#AF01,16#6FC0,16#6E80,16#AE41
16#AA01,16#6AC0,16#6B80,16#AB41,16#6900,16#A9C1,16#A881,16#6840
16#7800,16#B8C1,16#B981,16#7940,16#BB01,16#7BC0,16#7A80,16#BA41
16#BE01,16#7EC0,16#7F80,16#BF41,16#7D00,16#BDC1,16#BC81,16#7C40
16#B401,16#74C0,16#7580,16#B541,16#7700,16#B7C1,16#B681,16#7640
16#7200,16#B2C1,16#B381,16#7340,16#B101,16#71C0,16#7080,16#B041
16#5000,16#90C1,16#9181,16#5140,16#9301,16#53C0,16#5280,16#9241
16#9601,16#56C0,16#5780,16#9741,16#5500,16#95C1,16#9481,16#5440
16#9C01,16#5CC0,16#5D80,16#9D41,16#5F00,16#9FC1,16#9E81,16#5E40
16#5A00,16#9AC1,16#9B81,16#5B40,16#9901,16#59C0,16#5880,16#9841
16#8801,16#48C0,16#4980,16#8941,16#4B00,16#8BC1,16#8A81,16#4A40
16#4E00,16#8EC1,16#8F81,16#4F40,16#8D01,16#4DC0,16#4C80,16#8C41
16#4400,16#84C1,16#8581,16#4540,16#8701,16#47C0,16#4680,16#8641
16#8201,16#42C0,16#4380,16#8341,16#4100,16#81C1,16#8081,16#4040
//
//
END_FUNCTION //TAB Modbus::CRCTab
FUNCTION AWL Modbus::GetBit
VAR_INPUT
Adresse : UINT;
END_VAR
VAR_OUTPUT
Inhalt : hsINT;
END_VAR
l.edi IOPtr
ADD.DI adresse
L.AL (EDI)
S.AL inhalt
END_FUNCTION // Modbus::GetBit
FUNCTION AWL Modbus::SetBit
VAR_INPUT
Adresse : uINT;
Wert : hsiNT;
END_VAR
l.edi IOPtr
ADD.DI adresse
L.AL Wert
S.AL (EDI)
END_FUNCTION // Modbus::SetBit
//[#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
l.edi DataPtr
ADD.DI adresse
L.AL (EDI)
S.AL inhalt
END_FUNCTION // Modbus::GetByte
//[#ENGLISH]
//
//Schreibt den Inhalt von WERT an die ADRESSE.
FUNCTION AWL Modbus::SetByte
VAR_INPUT
Adresse : uint;
Wert : hsint;
END_VAR
l.edi DataPtr
ADD.DI adresse
L.AL Wert
S.AL (EDI)
END_FUNCTION // Modbus::SetByte
//[#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 esi
PUSHF
CLD
clr ecx
L.CX anzahl
L.EDI desti
L.ESI source
REP
MOVSB
POPF
pop esi
END_FUNCTION // Modbus::CopyBuff
//[#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 : ^Hsint;
END_VAR
VAR_OUTPUT
Ergebn : hint;
END_VAR
L.DX 16#FFFF
clr ecx
L.CX anzahl
L.EDI source
CRC_LP
L (EDI)
CALL CRC16
INC EDI
LOOP CRC_LP
S.DX ergebn
END_FUNCTION // Modbus::CalkCRC
//[#ENGLISH]
//
//Unterfunktion zur CRC-Berechnung
//
FUNCTION AWL Modbus::CRC16
push Ecx
clr ebx
CLR AH
L.BX DX
XOR.BX AX
CLR BH
SHL.BX 00001
L.ESI #CRCTAB()
L.AX (EBX+ESI+003)
XCH.DH DL
CLR DH
XOR.DX AX
pop Ecx
END_FUNCTION // Modbus::CRC16
//[#ENGLISH]
//
//Buffer l攕chen.
//
//ANZAHL von Bytes ab Datenspeicher DESTI auf $00 setzen.
//
FUNCTION AWL Modbus::ClrBuffer
VAR_INPUT
Anzahl : uint;
Desti : ^Hsint;
END_VAR
Clr ECX
L.CX anzahl
L.AL 16#00
L.EDI desti
CLD
REP
STOSB
END_FUNCTION // Modbus::ClrBuffer
FUNCTION awl Modbus::ENABLE_ME
L.DX 16#F8FC
inb
and.al 16#FE
outb
END_FUNCTION // Modbus::ENABLE_ME
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -