diff --git a/Modbus-CAPL/MakeConfig.cfg b/Modbus-CAPL/MakeConfig.cfg
index c3ea76a..859bc73 100644
--- a/Modbus-CAPL/MakeConfig.cfg
+++ b/Modbus-CAPL/MakeConfig.cfg
@@ -1,4 +1,4 @@
-;CANoe Version |4|7|1|35745 MakeConfig
+;CANoe Version |4|7|1|52148 MakeConfig
Version: 8.2.40 Build 40
32 PRO
5
@@ -13,10 +13,10 @@ VGlobalParameters 2 Begin_Of_Object
20
0
3,100,200,500
-1000000 1.000000 1 1000 1 1 0 0 1 1 1 0 0 0 1 0 0 0
+1000000 1.000000 0 1000 1 1 0 0 1 1 1 0 0 0 1 0 0 0
1
0
-0 1
+0 0
ResetSignalsOnMeasurementStart=1
VDatabaseContainerStreamer 3 Begin_Of_Object
5
@@ -642,7 +642,7 @@ Begin_Of_Multi_Line_String
Copyright (c) 2001-2006 Actipro Software LLC. All rights reserved.
http://www.ActiproSoftware.com/Products/DotNet/
--->
+-->
End_Of_Serialized_Data 3
End_Of_Object VDesktop 3
0
@@ -659,7 +659,7 @@ VUniqueBox 4 Begin_Of_Object
VBoxRoot 5 Begin_Of_Object
1
3
-0 2 0 1 -1 -1 -1 -1 22 22 1522 983
+0 2 0 1 -1 -1 -1 -1 -227 39 1073 1000
1
@@ -678,7 +678,7 @@ END_OF_DOCK_INFO
1582 856
END_OF_DESKTOP_DATA
6
-0 1 -1 -1 -1 -1 22 22 1522 983
+0 1 -1 -1 -1 -1 -227 39 1073 1000
6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 -1 32767 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 0
END_OF_DOCK_INFO
0
@@ -686,7 +686,7 @@ END_OF_DOCK_INFO
0
0
1
-999 592
+1188 696
END_OF_DESKTOP_DATA
END_OF_DESKTOP_DATA_COLLECTION
0
@@ -2516,7 +2516,7 @@ VUniqueBox 16 Begin_Of_Object
VBoxRoot 17 Begin_Of_Object
1
1
-1 1 0 1 -1 -1 -1 -1 0 339 1188 688
+1 1 0 1 -1 -1 -1 -1 0 285 1188 634
1
@@ -2535,7 +2535,7 @@ END_OF_DOCK_INFO
999 591
END_OF_DESKTOP_DATA
6
-0 1 -1 -1 -1 -1 0 339 1188 688
+0 1 -1 -1 -1 -1 0 285 1188 634
6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 -1 32767 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 0
END_OF_DOCK_INFO
1
@@ -2543,7 +2543,7 @@ END_OF_DOCK_INFO
0
0
1
-1188 696
+1188 634
END_OF_DESKTOP_DATA
END_OF_DESKTOP_DATA_COLLECTION
0
@@ -2894,7 +2894,7 @@ VUniqueBox 4 Begin_Of_Object
VBoxRoot 5 Begin_Of_Object
1
3
-0 0 0 1 -1 -1 -1 -1 0 0 1188 338
+0 0 0 1 -1 -1 -1 -1 0 0 1188 284
1
@@ -2913,7 +2913,7 @@ END_OF_DOCK_INFO
803 901
END_OF_DESKTOP_DATA
6
-0 1 -1 -1 -1 -1 0 0 1188 338
+0 1 -1 -1 -1 -1 0 0 1188 284
6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 -1 32767 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 0
END_OF_DOCK_INFO
1
@@ -2921,7 +2921,7 @@ END_OF_DOCK_INFO
0
0
1
-1188 696
+1188 634
END_OF_DESKTOP_DATA
END_OF_DESKTOP_DATA_COLLECTION
0
@@ -2961,7 +2961,7 @@ End_Of_Object VGrMnBox 3
VDOLocalInfoStruct 3 Begin_Of_Object
3
1
-83
+92
VDAOBus 4 Begin_Of_Object
1
1
@@ -3024,7 +3024,7 @@ EOF_ASSEMBLYDATA
1 "include\CAPL\MakeConfig.cbf"
VIPBStackSetting 8 Begin_Of_Object
3
-0
+1
1
VIPBAdapterSetting 9 Begin_Of_Object
4
@@ -3075,7 +3075,7 @@ End_Of_Serialized_Data 7
End_Of_Object VProgrammedNode 7
0
0
-Startdelay 0 0 0
+Startdelay 1 0 10
Jitter 0 0 1 0 0 0 0
1
1 ETHERNET_IL.DLL
@@ -3091,7 +3091,7 @@ VSimulinkModelViewerConfiguration 7 Begin_Of_Object
End_Of_Object VSimulinkModelViewerConfiguration 7
1
0
-3530245935
+2517525802
0
NodeSignalPanelBustypeCount 0
End_Of_Object VSimulationNode 6
@@ -3129,7 +3129,7 @@ NULL
End_Of_Object VDOLocalInfoStruct 3
0.000000
0 0
-1 1 0 59420 1 233 1 2882400001 98 331 309 611 2882400002 0 0 0 0 0 0 1 2882400001 1270 1270 311 311 2882400002 0 0 0 1664573080 0 0 3
+1 1 0 59420 1 233 1 2882400001 98 331 371 619 2882400002 0 0 0 0 0 0 1 2882400001 1270 1270 373 373 2882400002 0 0 0 339969840 0 409869284 3
SS_BEGIN_COMMON_INFO
1
0
@@ -3141,7 +3141,7 @@ Ethernet
11
1
1
-7573328 1 0 1 0 0 1 0 0 0 2000 1
+340356552 1 0 1 0 0 1 0 0 71 2000 1
SS_BEGIN_COMMON_INFO
1
3
@@ -3190,7 +3190,7 @@ END_OF_DOCK_INFO
END_OF_DESKTOP_DATA
6
0 1 -1 -1 0 0 0 700 662 1043
-6 1 1010 180 0 0 300 180 300 180 0 61440 1 12180 1904 0 0 0 0 260 0 0 0 -1 -1 32767 0 59422 0 0 0 0 0 0 0 1 10 0 0 1 201 0 59419 1
+6 1 1010 180 0 0 300 180 300 180 0 61440 1 12180 1904 0 0 0 0 260 0 0 0 -1 -1 32767 0 59422 0 0 0 0 0 0 0 1 10 0 0 1 263 0 59419 1
END_OF_DOCK_INFO
1
1
@@ -3564,6 +3564,9 @@ End
FiltersEnd
0 0
+
+
+
END_OF_WORKSPACE_MEMBER_DATA
END_OF_WORKSPACE_MEMBER
1
@@ -3684,7 +3687,7 @@ VIPBGlobalSettings 2 Begin_Of_Object
1
VIPBStackSetting 3 Begin_Of_Object
3
-0
+1
1
VIPBAdapterSetting 4 Begin_Of_Object
4
diff --git a/Modbus-CAPL/ModbusNet.cfg b/Modbus-CAPL/ModbusNet.cfg
index 5be2b34..4e806df 100644
--- a/Modbus-CAPL/ModbusNet.cfg
+++ b/Modbus-CAPL/ModbusNet.cfg
@@ -1,4 +1,4 @@
-;CANoe Version |4|7|1|55201 ModbusNet
+;CANoe Version |4|7|1|38816 ModbusNet
Version: 8.2.40 Build 40
32 PRO
10
@@ -67,6 +67,7 @@ DialogBegin
1
285 569 816 1103
SymbolExplorerDialogBegin
+
1
HistoryBegin
1 0
@@ -745,9 +746,11 @@ Begin_Of_Multi_Line_String
kPersistNoLineBreak
ey="{28077F35-C142-4ACC-B040-1BF0AB026C11}" Guid="ac9be154-bd12-4ff9-b255-03e05277dbe2" DockedSize="201, 281" FloatingLocation="111, 442" FloatingSize="1192, 514" HasOptions="False" ImageIndex="-1" Text="Trace" TitleBarText="Trace">
+Window Key="{49714911-9568-49CC-A9CE-3B0905658C4A}" Guid="db27ffca-d17e-40f0-a70b-be70fe5eb4ec" State="DockableInsideHost" DockedSize="381, 0" FloatingLocation="1151, 79" FloatingSize="300, 180">
End_Of_Serialized_Data 3
End_Of_Object VDesktop 3
VDesktop 3 Begin_Of_Object
@@ -1192,7 +1195,7 @@ End_Of_Serialized_Data 15
End_Of_Object VPredefinedSignalObject 15
[MeasurementObject]
Eth 1::Rx Bus load
-"%" 1 800080 0. 100. -100. 100. 10 -5 0 0 36000000 0 1 0 0
+"%" 1 800080 0. 100. -100. 100. 10 -5 0 0 36000000 1 1 0 0
VPredefinedSignalObject 15 Begin_Of_Object
1
VHostSignal 16 Begin_Of_Object
@@ -1243,7 +1246,7 @@ End_Of_Serialized_Data 15
End_Of_Object VPredefinedSignalObject 15
[MeasurementObject]
Eth 1::Tx Bus load
-"%" 1 80 0. 100. -100. 100. 10 -5 0 0 36000000 0 1 0 0
+"%" 1 80 0. 100. -100. 100. 10 -5 0 0 36000000 1 1 0 0
VPredefinedSignalObject 15 Begin_Of_Object
1
VHostSignal 16 Begin_Of_Object
@@ -1379,7 +1382,7 @@ End_Of_Serialized_Data 15
End_Of_Object VSysVarObject 15
[MeasurementObject]
Client_2::InputBits_[0]
-"" 223 b86b8 -1. 1. -100. 100. 1 0 0 0 36000000 1 1 0 0
+"" 223 b86b8 -1. 1. -100. 100. 1 0 0 0 36000000 0 1 0 0
VSysVarObject 15 Begin_Of_Object
1
VHostSignal 16 Begin_Of_Object
@@ -1413,7 +1416,7 @@ End_Of_Serialized_Data 15
End_Of_Object VSysVarObject 15
[MeasurementObject]
Client_2::InputBits_[1]
-"" 223 d7ff -1. 1. -100. 100. 1 0 0 0 36000000 1 1 0 0
+"" 223 d7ff -1. 1. -100. 100. 1 0 0 0 36000000 0 1 0 0
VSysVarObject 15 Begin_Of_Object
1
VHostSignal 16 Begin_Of_Object
@@ -1447,7 +1450,7 @@ End_Of_Serialized_Data 15
End_Of_Object VSysVarObject 15
[MeasurementObject]
Client_3::InputBits_[5]
-"" 223 9314ff 0. 1. -100. 100. 1 0 0 0 36000000 1 1 0 0
+"" 223 9314ff 0. 1. -100. 100. 1 0 0 0 36000000 0 1 0 0
VSysVarObject 15 Begin_Of_Object
1
VHostSignal 16 Begin_Of_Object
@@ -1481,7 +1484,7 @@ End_Of_Serialized_Data 15
End_Of_Object VSysVarObject 15
[MeasurementObject]
Client_2::InputRegisters_[0]
-"" 223 ff00 2746. 6071. -100. 100. 500 0 0 0 36000000 1 1 0 0
+"" 223 ff00 2746. 6071. -100. 100. 500 0 0 0 36000000 0 1 0 0
VSysVarObject 15 Begin_Of_Object
1
VHostSignal 16 Begin_Of_Object
@@ -1515,9 +1518,9 @@ End_Of_Serialized_Data 15
End_Of_Object VSysVarObject 15
[MeasurementObject]
Client_3::InputRegisters_[3]
-"" 223 228b22 8987. 19894. -100. 100. 1000 0 0 0 36000000 1 1 0 0
+"" 223 228b22 8987. 19894. -100. 100. 1000 0 0 0 36000000 0 1 0 0
[GraphWindow:x_x_x_x_x_x_WindowBk_Grid_AxisBk_XAxisFr_YAxisFr_x_x_x_x_x_x]
-5210346.6428800002 5634098.14585 240215.71337000001 200000 36000000 1 ffffff b2b2b2 ffffff 0 0 0 0 1 1 1 0
+0 423751.50296999997 423751.50296999997 200000 36000000 1 ffffff b2b2b2 ffffff 0 0 0 0 1 1 1 0
0 30 5000
0
0 100
@@ -1528,7 +1531,7 @@ Client_3::InputRegisters_[3]
0
1
41943040
-8
+1
1416 25200245
Grafik-Fenster
1 ""
@@ -1773,7 +1776,7 @@ End_Of_Object VTraceAnalysisSingleFilter 17
1
End_Of_Object VTraceAnalysisFilterGroup 16
End_Of_Object VTraceFilterCfg 15
-1
+0
1
0
0
@@ -1796,7 +1799,7 @@ End_Of_Serialized_Data 14
6
1
14
-ver=2: FT TF TF FF FT FF;F T Config;F T Ethernet1;F T GLLogger;T F _Statistics
+ver=2: FT TF TF FT FT FT;F T Config;F T Ethernet1;F T GLLogger;T F _Statistics
End_Of_Serialized_Data 14
7
0
@@ -1837,29 +1840,29 @@ End_Of_Serialized_Data 14
22
1
14
-ver=2: FF
+ver=2: FT
End_Of_Serialized_Data 14
23
1
14
-ver=2: FF
+ver=2: FT
End_Of_Serialized_Data 14
24
1
14
-ver=2: FF
+ver=2: FT
End_Of_Serialized_Data 14
25
0
26
1
14
-ver=2: FF
+ver=2: FT
End_Of_Serialized_Data 14
27
1
14
-ver=2: FF
+ver=2: FT
End_Of_Serialized_Data 14
0
2
@@ -3734,7 +3737,7 @@ End_Of_Serialized_Data 14
0
0
290
-1
+0
160
1 ""
End_Of_Object VTraceControlCfg 14
@@ -4471,7 +4474,7 @@ End_Of_Serialized_Data 14
End_Of_Object VSysVarObject 14
[Begin_of_Item]
2 18
-1 1 10 0 0 16777215
+1 1 3 0 0 16777215
0 1000 0 0
[End_of_Item]
VSysVarObject 14 Begin_Of_Object
@@ -4543,7 +4546,7 @@ End_Of_Serialized_Data 14
End_Of_Object VSysVarObject 14
[Begin_of_Item]
2 17
-1 1 2 0 0 16777215
+1 1 3 0 0 16777215
0 1000 0 0
[End_of_Item]
VSysVarObject 14 Begin_Of_Object
@@ -4879,7 +4882,7 @@ END_OF_DOCK_INFO
0
0
1
-0 1 -32088 -32000 -1 -1 147 402 1041 893
+0 1 -1 -1 -1 -1 -117 402 777 893
0
1
776 389
@@ -4933,7 +4936,7 @@ End_Of_Object VGrMnBox 3
VDOLocalInfoStruct 3 Begin_Of_Object
3
1
-218
+228
VDAOBus 4 Begin_Of_Object
1
1
@@ -5045,7 +5048,7 @@ End_Of_Object VIPBStackSetting 8
NDebugger::VDebuggerHost 8 Begin_Of_Object
2
0
-26
+27
NDebugger::VFile 9 Begin_Of_Object
1
1 "ModbusTcpCommon.cin"
@@ -5176,6 +5179,11 @@ NDebugger::VFile 9 Begin_Of_Object
1 "include\CAPL\include\ModbusStructs.cin"
42
End_Of_Object NDebugger::VFile 9
+NDebugger::VFile 9 Begin_Of_Object
+1
+ 1 "include\CAPL\include\DeviceInformation.cin"
+43
+End_Of_Object NDebugger::VFile 9
VNETStandaloneComponent 9 Begin_Of_Object
1
VNETControlBox 10 Begin_Of_Object
@@ -5409,7 +5417,7 @@ VSimulinkModelViewerConfiguration 7 Begin_Of_Object
End_Of_Object VSimulinkModelViewerConfiguration 7
1
0
-3569770309
+2097296340
0
NodeSignalPanelBustypeCount 0
End_Of_Object VSimulationNode 6
@@ -5544,7 +5552,7 @@ VSimulinkModelViewerConfiguration 7 Begin_Of_Object
End_Of_Object VSimulinkModelViewerConfiguration 7
1
0
-3569770309
+2097296340
0
NodeSignalPanelBustypeCount 0
End_Of_Object VSimulationNode 6
@@ -5803,7 +5811,7 @@ NULL
End_Of_Object VDOLocalInfoStruct 3
0.000000
0 0
-1 1 0 59420 1 176 1 2882400001 243 443 430 885 2882400002 0 0 0 0 0 20 1 2882400001 1121 1321 432 632 2882400002 0 0 0 0 0 0 3
+1 1 0 59420 1 176 1 2882400001 -21 179 430 885 2882400002 0 0 0 0 0 20 1 2882400001 857 1057 432 632 2882400002 0 0 0 0 0 0 3
SS_BEGIN_COMMON_INFO
1
0
@@ -6217,14 +6225,14 @@ SymbSelHeaderMgrBegin
SymbSelHeaderMgrEnd
End
Begin
-3 0 -1
+3 8 16
3
Modbus
modbus
Systemvariablen
- ( 3 ( 0 ) 0 )
+ ( 3 ( 1 ( 3 ( 0 ) 0 ) 0 ) 0 )
SymbSelHeaderMgrBegin
1 4
0 1 200 0 0
diff --git a/Modbus-CAPL/include/CAPL/MakeConfig.can b/Modbus-CAPL/include/CAPL/MakeConfig.can
index 5987596..de2422b 100644
--- a/Modbus-CAPL/include/CAPL/MakeConfig.can
+++ b/Modbus-CAPL/include/CAPL/MakeConfig.can
@@ -1,23 +1,12 @@
/*@!Encoding:1252*/
includes
{
+ #include "include/DeviceInformation.cin"
#include "include/ModbusUdpClientCommon.cin"
- #include "include/ModbusFunctions.cin"
}
variables
{
- struct device // A structure that contains information about an Modbus device
- {
- char Ip[16]; // String: The IP address
- char IpLsb[4]; // String: The last byte of the IP address. Used as index of node name
- char IpNet[4]; // String: The second last byte of the IP. Used as index of net
- enum Vendor Vendor; // The Vendor (Wago / B&R)
- word SerialCode; // Serial Code
- word DeviceCode; // Device Code
- struct deviceIOs DeviceIOs; // A structure with more information about IOs
- };
-
char[16] gIps[long]; // List IP addresses. These will be analysed
char gScanFirstIp[16]; // The first IP address that will be scanned
char gScanLastIp[16]; // The first IP address that will not be scanned anymore.
@@ -46,10 +35,10 @@ on preStart
strncpy(gIps[3], "192.168.1.8", 16);
*/
- // Scan a range of IPs for devices. Start and Stop go here
- // Please note: Currently .255 will be skipped! Don't use it for devices and as stop address
+ // Scan a range of IPs for devices (if nothing was set above). Start and Stop go here
+ // Please note: Currently .255 will be skipped! Don't use it for devices
strncpy(gScanFirstIp, "192.168.1.2", 16);
- strncpy(gScanLastIp, "192.168.1.10", 16);
+ strncpy(gScanLastIp, "192.168.1.20", 16);
// Name of the project
strncpy(name, "Modbus", elCount(name));
@@ -58,7 +47,7 @@ on preStart
strncpy(fnSysvar, "include/SysVars/generated.vsysvar", elCount(fnSysvar));
strncpy(fnDbc, "include/DBC/generated.dbc", elCount(fnDbc));
- OutputDebugLevel = Mute;
+ OutputDebugLevel = Error;
}
on start
@@ -99,10 +88,10 @@ void DetectDevices()
{
write("Scanning from %s to %s with timeout of %d ms", gScanFirstIp, gScanLastIp, @sysvar::Config::Modbus::RequestTimeout);
- gScanFirst = ipGetAddressAsNumber(gScanFirstIp);
- gScanLast = ipGetAddressAsNumber(gScanLastIp);
+ gScanFirst = ipGetAddressAsNumber(gScanFirstIp); // We have to use big endian here
+ gScanLast = swapDWord(ipGetAddressAsNumber(gScanLastIp)); // But not here :)
- write("%d.%d.%d.%d ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24);
+ writeLineEx(0, 0, "%d.%d.%d.%d ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24);
ModbusConnectTo(gScanFirst, @sysvar::Config::Modbus::Port); // Open socket and set variables
ModbusReadBits(0, 1); // Start device detection
}
@@ -110,52 +99,36 @@ void DetectDevices()
///
void DetectDevicesNext()
{
- // next IP
- // Note: IP address is stored as big endian, comments are notated as little endian :)
- // 0xFE...... --> Skip xxx.xxx.xxx.255 which is broadcast address in 192.168.xxx.0 nets
-
- // If first three bytes are full (123.255.255.255), set those to 0 and increment the first byte (124.0.0.0)
- if ((gScanFirst & 0xFFFFFF00) == 0xFEFFFF00)
+ gScanFirst = swapDWord(gScanFirst);
+ gScanFirst++;
+ if ((gScanFirst & 0xFF) == 0xFF) // .255
{
- gScanFirst &= 0x000000FF;
- gScanFirst += 0x00000001;
- write("%d.%d.%d.%d ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24);
- }
- // If first two bytes are full (124.111.255.255), set those to 0 and increment the second byte (124.112.0.0)
- else if ((gScanFirst & 0xFFFF0000) == 0xFEFF0000)
- {
- gScanFirst &= 0x0000FFF;
- gScanFirst += 0x00000100;
- write("%d.%d.%d.%d ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24);
- }
- // If first last byte is full (124.112.222.255), set it to 0 and increment the third byte (124.112.223.0)
- else if ((gScanFirst & 0xFF000000) == 0xFE000000)
- {
- gScanFirst &= 0x00FFFFFF;
- gScanFirst += 0x00010000;
- write("%d.%d.%d.%d ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24);
- }
- // Else simply increment the LSB
- else
- {
- gScanFirst += 0x01000000;
+ gScanFirst++;
+ writeLineEx(0, 0, "%d.%d.%d.%d ", gScanFirst >> 24, (gScanFirst >> 16) & 0xFF, (gScanFirst >> 8) & 0xFF, gScanFirst & 0xFF);
}
- if (gScanFirst == gScanLast) // If this is the last address we stop the detection
+ if (gScanFirst > gScanLast)
{
@sysvar::Config::Modbus::MaxTransmissionCount = gMaxTransmissionCount;
MakeIpNets();
return;
}
- writeEx(1, 1, "."); // Write something so the user knows something is happening
+ gScanFirst = swapDWord(gScanFirst);
+
+ writeEx(0, 0, "."); // Write something so the user knows something is happening
gRemoteIP = gScanFirst; // Don't open new socket, it takes too much time. This means we should use UDP here!
ModbusReadBits(0, 1); // Scan the next device
}
///
void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
{
- DetectDevicesNext(); // Timeout! We will go to the next device
+ switch (error)
+ {
+ case FinalTimeout:
+ case Exception:
+ DetectDevicesNext(); // Timeout! We will go to the next device
+ }
}
///
void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq)
@@ -250,21 +223,11 @@ void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusExcep
case Exception:
memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer);
- if (mbreq.Address == 0x1000 && ex == IllegalDataAddress) // We requested Wago SerialCode and it didn't work --> Not Wago --> B&R
+ if (mbreq.Address == 0x1000 && ex == IllegalDataAddress) // We requested Wago SerialCode and it didn't work --> Not Wago --> B&R. Not future proof
{
gIpsSorted[ips[ADi]].Vendor = Wago;
// request information
- ADn = 10;
- ModbusReadRegisters(0x2011, 1); // Serial Code
- ModbusReadRegisters(0x2012, 1); // Device Code
- ModbusReadRegisters(0x1022, 1); // Number of AOs (= size in bits)
- ModbusReadRegisters(0x1023, 1); // Number of AIs (= size in bits)
- ModbusReadRegisters(0x1024, 1); // Number of DOs
- ModbusReadRegisters(0x1025, 1); // Number of DIs
- ModbusReadRegisters(0x2030, 65); // Connected IO 1
- ModbusReadRegisters(0x2031, 64); // Connected IO 2
- ModbusReadRegisters(0x2032, 64); // Connected IO 3
- ModbusReadRegisters(0x2033, 63); // Connected IO 4
+ ADn = DeviceGetInformation(Wago);
return;
}
@@ -283,83 +246,16 @@ void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusExcep
///
void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct ModbusReqRead mbreq)
{
- byte i;
-
if (mbreq.Address == 0x1000) // We detected a B&R device
{
gIpsSorted[ips[ADi]].Vendor = BuR;
// request further information
- ADn = 5;
- ModbusReadRegisters(0x1083, 1); // Product Code
- ModbusReadRegisters(0x1101, 1); // Number of AIs
- ModbusReadRegisters(0x1103, 1); // Number of AOs
- ModbusReadRegisters(0x1105, 1); // Number of DIs
- ModbusReadRegisters(0x1107, 1); // Number of DOs
+ ADn = DeviceGetInformation(BuR);
return;
}
- switch (gIpsSorted[ips[ADi]].Vendor)
- {
- case Wago:
- // Parse the received data
- switch (mbreq.Address)
- {
- case 0x2011:
- gIpsSorted[ips[ADi]].serialCode = mbres.Data[0];
- break;
- case 0x2012:
- gIpsSorted[ips[ADi]].deviceCode = mbres.Data[0];
- break;
- case 0x1022:
- gIpsSorted[ips[ADi]].DeviceIOs.OutputRegisters = mbres.Data[0] / 16;
- break;
- case 0x1023:
- gIpsSorted[ips[ADi]].DeviceIOs.InputRegisters = mbres.Data[0] / 16;
- break;
- case 0x1024:
- gIpsSorted[ips[ADi]].DeviceIOs.OutputBits = mbres.Data[0];
- break;
- case 0x1025:
- gIpsSorted[ips[ADi]].DeviceIOs.InputBits = mbres.Data[0];
- break;
- case 0x2030:
- case 0x2031:
- case 0x2032:
- case 0x2033:
- for (i = 0; i < mbreq.Count; i++)
- {
- if (mbres.Data[i] == 0x0000) // No more devices --> end
- break;
- ParseDeviceCode(mbres.Data[i], gIpsSorted[ips[ADi]].Vendor, gIpsSorted[ips[ADi]].DeviceIOs);
- }
- break;
- }
- break;
- case BuR:
- // Parse the received data
- switch (mbreq.Address)
- {
- case 0x1083:
- gIpsSorted[ips[ADi]].serialCode = mbres.Data[0];
- break;
- case 0x1101:
- gIpsSorted[ips[ADi]].DeviceIOs.InputRegisters = mbres.Data[0] - 3; // X20BC0087 has 3 AIs when no module is connected... hö?
- break;
- case 0x1103:
- gIpsSorted[ips[ADi]].DeviceIOs.OutputRegisters = mbres.Data[0];
- break;
- case 0x1105:
- gIpsSorted[ips[ADi]].DeviceIOs.InputBits = mbres.Data[0] * 8; // Unfortunately this is quite imprecise:
- // in the process image one module will always fill a whole number of bytes.
- // So 4 12DI modules not allocate not 4*12 bit = 6 byte, but 4*16 bit = 64 bit = 8 byte
- break;
- case 0x1107:
- gIpsSorted[ips[ADi]].DeviceIOs.OutputBits = mbres.Data[0] * 8;
- break;
- }
- break;
- }
+ DeviceParseRegister(gIpsSorted[ips[ADi]], mbreq.Address, mbres.Data, mbreq.Count);
if (--ADn == 0) // If we received all registers
AnalyzeDevicesNext();
@@ -414,9 +310,9 @@ void GenSysvars()
for (long ipN : gIpsSorted)
{
-
if (((ipN >> 16) & 0xFF) != net)
continue;
+ DeviceInit(gIpsSorted[ipN].Vendor);
PutString(" \n");
- }
- else
- {
- PutString((word)2048);
- PutString("\" maxValuePhys=\"");
- PutString((word)2048);
- PutString("\" />\n");
- }
+ PutString((word)gDevRegMaxCount);
+ PutString("\" maxValuePhys=\"");
+ PutString((word)gDevRegMaxCount);
+ PutString("\" />\n");
// InputBits
PutString(" \n");
- }
- else
- {
- PutString((word)16384);
- PutString("\" maxValuePhys=\"");
- PutString((word)16384);
- PutString("\" />\n");
- }
+ PutString((word)gDevBitMaxCount);
+ PutString("\" maxValuePhys=\"");
+ PutString((word)gDevBitMaxCount);
+ PutString("\" />\n");
// OutputRegisters
PutString(" \n");
- }
- else
- {
- PutString((word)2048);
- PutString("\" maxValuePhys=\"");
- PutString((word)2048);
- PutString("\" />\n");
- }
+ PutString((word)gDevRegMaxCount);
+ PutString("\" maxValuePhys=\"");
+ PutString((word)gDevRegMaxCount);
+ PutString("\" />\n");
// OutputBits
PutString(" \n");
- }
- else
- {
- PutString((word)16384);
- PutString("\" maxValuePhys=\"");
- PutString((word)16384);
- PutString("\" />\n");
- }
+ PutString((word)gDevBitMaxCount);
+ PutString("\" maxValuePhys=\"");
+ PutString((word)gDevBitMaxCount);
+ PutString("\" />\n");
PutString(" \n");
// Namespace Data
diff --git a/Modbus-CAPL/include/CAPL/ModbusClient.can b/Modbus-CAPL/include/CAPL/ModbusClient.can
index 881e738..078d912 100644
--- a/Modbus-CAPL/include/CAPL/ModbusClient.can
+++ b/Modbus-CAPL/include/CAPL/ModbusClient.can
@@ -3,6 +3,7 @@
includes
{
#include "include\ModbusUdpClientCommon.cin"
+ #include "include\DeviceInformation.cin"
}
variables
@@ -10,51 +11,20 @@ variables
msTimer gtRead;
}
-// Get information of local network interface such like ip address
-
on preStart
{
writeClear(0);
setStartdelay(10);
- OutputDebugLevel = Warning;
+ OutputDebugLevel = MbDebug;
}
on start
{
- word outputBits, outputRegs, outputBitAddr, outputRegAddr;
-
- outputBits = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits;
- outputRegs = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputRegisters;
-
- switch ((enum Vendor)@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::Vendor)
- {
- case Wago:
- outputBitAddr = 0x200;
- outputRegAddr = 0x200;
- break;
- case BuR:
- outputBitAddr = 0x000;
- outputRegAddr = 0x800;
- break;
- }
-
+ DeviceInit(@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::Vendor);
ModbusInit();
- while (outputBits > 0)
- {
- ModbusReadOutBits(outputBitAddr, 2000);
- outputBits -= 2000;
- }
- if (outputBits > 0)
- ModbusReadOutBits(outputBitAddr, outputBits);
-
- while (outputRegs > 0)
- {
- ModbusReadRegisters(outputRegAddr, 123);
- outputRegs -= 123;
- }
- if (outputRegs > 0)
- ModbusReadRegisters(outputRegAddr, outputRegs);
+ ModbusReadOutBits(gDevOutputBitAddr, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits);
+ ModbusReadOutRegisters(gDevOutputRegAddr, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputRegisters);
setTimerCyclic(gtRead, 1, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config::Interval);
}
@@ -121,20 +91,28 @@ void OnModbusWriteRegistersFailed(enum ModbusRequestError error, enum ModbusExce
void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq)
{
- word i;
+ word i, offset;
- switch(mbreq.Address)
+ switch (mbres.Header.FuncCode) // We assume that we separate between 0x01 and 0x02 even though the address space may be the same
{
- case 0x200: // set output bits
+ case 0x01: // Read output bits
sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputBits");
- for (i = 0; i < @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits; i++)
- @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits[i] = bitStatus[i];
+
+ offset = mbreq.Address - gDevOutputBitAddr; // Get the offset to the base output bit address
+ for (i = 0; i < mbreq.Count; i++)
+ @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits[i + offset] = bitStatus[i];
+
sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputBits");
break;
- default: // set input bits
+
+
+ case 0x02: // Read input bits
sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputBits");
- for (i = 0; i < @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputBits; i++)
- @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::InputBits[i] = bitStatus[i];
+
+ offset = mbreq.Address - gDevInputBitAddr; // Get the offset to the base input bit address
+ for (i = 0; i < mbreq.Count; i++)
+ @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::InputBits[i + offset] = bitStatus[i];
+
sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputBits");
break;
}
@@ -142,29 +120,30 @@ void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[]
void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct ModbusReqRead mbreq)
{
- char str[20*5];
- long fehler;
- byte i;
+ word i, offset;
- switch (mbreq.Address)
+ switch (mbres.Header.FuncCode) // We assume that we separate between 0x03 and 0x04 even though the address space may be the same
{
- case 0x200: // set output registers
+ case 0x03: // Read output registers
sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputRegisters");
- for (i = 0; i < @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputRegisters; i++)
- @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputRegisters[i] = mbres.Data[i];
+
+ offset = mbreq.Address - gDevOutputRegAddr; // Get the offset to the base output register address
+ for (i = 0; i < mbreq.Count; i++)
+ @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputRegisters[i + offset] = mbres.Data[i];
+
sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputRegisters");
break;
- case 0x000: // set input registers
+
+
+ case 0x04: // Read input registers
sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputRegisters");
- for (i = 0; i < @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputRegisters; i++)
- @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::InputRegisters[i] = mbres.Data[i];
+
+ offset = mbreq.Address - gDevInputRegAddr; // Get the offset to the base input bit address
+ for (i = 0; i < mbreq.Count; i++)
+ @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::InputRegisters[i + offset] = mbres.Data[i];
+
sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputRegisters");
break;
- default:
- // Not recognized
- dbin_to_strhex(mbres.Data, str);
- writeLineEx(0, 1, "<%NODE_NAME%> OnModbusReceiveRegisters: Received %d bytes at 0x%04X: %s", mbres.ByteCount, mbreq.Address, str);
- break;
}
}
@@ -204,10 +183,9 @@ void OnModbusClientPanics(enum FatalErrors reason)
// Key events -------------------------------------------------------------------------
on timer gtRead
{
- if (@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputRegisters > 0)
- ModbusReadRegisters(0x0000, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputRegisters);
- if (@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputBits > 0)
- ModbusReadBits(0x0000, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputBits);
+ ModbusReadRegisters(0x0000, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputRegisters);
+ ModbusReadBits(0x0000, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputBits);
+ this.Cancel();
}
on sysvar %BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits
diff --git a/Modbus-CAPL/include/CAPL/include/DeviceInformation.cin b/Modbus-CAPL/include/CAPL/include/DeviceInformation.cin
new file mode 100644
index 0000000..019694e
--- /dev/null
+++ b/Modbus-CAPL/include/CAPL/include/DeviceInformation.cin
@@ -0,0 +1,285 @@
+/*@!Encoding:1252*/
+variables
+{
+ word gDevOutputBitAddr, gDevOutputRegAddr;
+ word gDevInputBitAddr, gDevInputRegAddr;
+ word gDevBitMaxCount, gDevRegMaxCount;
+ word gDevReceiveWindow;
+
+ enum Vendor
+ {
+ Wago = 23,
+ BuR = 2
+ };
+ struct deviceIOs
+ {
+ byte InputRegisters;
+ word InputBits;
+ byte OutputRegisters;
+ word OutputBits;
+ char Modules[1024];
+ };
+ struct device // A structure that contains information about an Modbus device
+ {
+ char Ip[16]; // String: The IP address
+ char IpLsb[4]; // String: The last byte of the IP address. Used as index of node name
+ char IpNet[4]; // String: The second last byte of the IP. Used as index of net
+ enum Vendor Vendor; // The Vendor (Wago / B&R)
+ word SerialCode; // Serial Code
+ word DeviceCode; // Device Code
+ struct deviceIOs DeviceIOs; // A structure with more information about IOs
+ };
+}
+
+// This is for the normal client and for making the sysvars
+///
+void DeviceInit(byte vendor)
+{
+ switch ((enum Vendor) vendor)
+ {
+ case Wago:
+ gDevInputBitAddr = 0x0000; // Wago inputs start at 0x000
+ gDevInputRegAddr = 0x0000;
+ gDevOutputBitAddr = 0x0200; // Wago outputs start at 0x200
+ gDevOutputRegAddr = 0x0200;
+ gDevBitMaxCount = 0x0100; // Wago allows up to 256 inputs
+ gDevRegMaxCount = 0x0100;
+ gDevReceiveWindow = 5; // Wago can handle 5 requests simultaneously
+ break;
+ case BuR:
+ gDevInputBitAddr = 0x0000; // B&R inputs start at 0x000
+ gDevInputRegAddr = 0x0000;
+ gDevOutputBitAddr = 0x0000; // B&R digital outputs start at 0x000
+ gDevOutputRegAddr = 0x0800; // B&R analog outputs start at 0x800
+ gDevBitMaxCount = 0x4000; // B&R allows up to 16348 digital inputs
+ gDevRegMaxCount = 0x0800; // B&R allows up to 2048 analog inputs
+ gDevReceiveWindow = 1; // B&R can only handle 1 request at a time
+ break;
+ }
+}
+
+
+
+// This is for making the sysvars (MakeConfig)
+///
+void DeviceParseCode(word dev, enum Vendor vendor, struct deviceIOs dios)
+{
+ byte input;
+ byte numChannels;
+ char module[10];
+
+ switch(vendor)
+ {
+ case Wago: // if this is a Wago device
+ if (dev & 0x8000) // Digital Module
+ {
+ numChannels = (dev >> 8) & 0x007F;
+
+ if (dev & 0x0001) // Input Module
+ {
+ input = 1;
+ strncpy(module, "DI%d,", elCount(module));
+ }
+ else if (dev & 0x0002) // Output Module
+ {
+ input = 0;
+ strncpy(module, "DO%d,", elCount(module));
+ }
+ else // mhm. What is it?
+ {
+ writeDbg(AlgoError, "ParseDeviceCode: Device code 0x%X cannot be decoded", dev);
+ OnModbusClientPanics(DeviceCodeUnknown);
+ }
+ }
+ else
+ {
+ // http://www.wago.com/wagoweb/documentation/navigate/nm0dx__d.htm
+ // http://www.wago.com/wagoweb/documentation/navigate/nm0dy__d.htm
+ switch (dev)
+ {
+ case 881: // devices that have no inputs/outputs
+ return;
+ case 491: // devices that have 1 inputs
+ input = 1;
+ numChannels = 1;
+ break;
+ case 452: // devices that have 2 inputs
+ case 465:
+ case 470:
+ case 472:
+ case 480:
+ case 454:
+ case 473:
+ case 474:
+ case 466:
+ case 484:
+ case 485:
+ case 492:
+ case 482:
+ case 475:
+ case 467:
+ case 477:
+ case 478:
+ case 456:
+ case 479:
+ case 476:
+ case 483:
+ case 461:
+ case 481:
+ case 462:
+ case 469:
+ case 487:
+ input = 1;
+ numChannels = 2;
+ break;
+ case 493: // devices that have 3 inputs
+ case 494:
+ case 495:
+ input = 1;
+ numChannels = 3;
+ break;
+ case 459: // devices that have 4 inputs
+ case 453:
+ case 455:
+ case 468:
+ case 457:
+ case 464:
+ case 460:
+ case 463:
+ input = 1;
+ numChannels = 4;
+ break;
+ case 552: // devices that have 2 inputs
+ case 585:
+ case 563:
+ case 554:
+ case 550:
+ case 560:
+ case 562:
+ case 556:
+ input = 0;
+ numChannels = 2;
+ case 555: // devices that have 4 inputs
+ case 553:
+ case 557:
+ case 559:
+ input = 0;
+ numChannels = 4;
+ default: // unknown device. Ouch!
+ writeDbg(AlgoInfo, "Connected device: 750-%d", dev);
+ return;
+ }
+ if (input)
+ strncpy(module, "AI%d,", elCount(module));
+ else
+ strncpy(module, "AO%d,", elCount(module));
+ }
+ break; // switch(vendor)
+ default:
+ writeDbg(AlgoError, "ParseDeviceCode: Unknown vendor id: %d", vendor);
+ OnModbusClientPanics(VendorIdUnknown);
+ return;
+ }
+
+ snprintf(module, elCount(module), module, numChannels);
+ strncat(dios.Modules, module, elCount(dios.Modules));
+}
+
+// This function requests more information from the device and return the number of expected results
+///
+byte DeviceGetInformation(enum Vendor vendor)
+{
+ switch (vendor)
+ {
+ case Wago:
+ ModbusReadRegisters(0x2011, 1); // Serial Code
+ ModbusReadRegisters(0x2012, 1); // Device Code
+ ModbusReadRegisters(0x1022, 1); // Number of AOs (= size in bits)
+ ModbusReadRegisters(0x1023, 1); // Number of AIs (= size in bits)
+ ModbusReadRegisters(0x1024, 1); // Number of DOs
+ ModbusReadRegisters(0x1025, 1); // Number of DIs
+ ModbusReadRegisters(0x2030, 65); // Connected IO 1
+ ModbusReadRegisters(0x2031, 64); // Connected IO 2
+ ModbusReadRegisters(0x2032, 64); // Connected IO 3
+ ModbusReadRegisters(0x2033, 63); // Connected IO 4
+ return 10;
+ case BuR:
+ ModbusReadRegisters(0x1083, 1); // Product Code
+ ModbusReadRegisters(0x1101, 1); // Number of AIs
+ ModbusReadRegisters(0x1103, 1); // Number of AOs
+ ModbusReadRegisters(0x1105, 1); // Number of DIs
+ ModbusReadRegisters(0x1107, 1); // Number of DOs
+ return 5;
+ }
+ return 0;
+}
+
+// This function parses the received registers
+///
+void DeviceParseRegister(struct device device, word address, word data[], word count)
+{
+ byte i;
+
+ switch (device.Vendor)
+ {
+ case Wago:
+ // Parse the received data
+ switch (address)
+ {
+ case 0x2011:
+ device.serialCode = data[0];
+ break;
+ case 0x2012:
+ device.deviceCode = data[0];
+ break;
+ case 0x1022:
+ device.DeviceIOs.OutputRegisters = data[0] / 16; // Wago returns the size in bits allocated by the module
+ break;
+ case 0x1023:
+ device.DeviceIOs.InputRegisters = data[0] / 16;
+ break;
+ case 0x1024:
+ device.DeviceIOs.OutputBits = data[0];
+ break;
+ case 0x1025:
+ device.DeviceIOs.InputBits = data[0];
+ break;
+ case 0x2030:
+ case 0x2031:
+ case 0x2032:
+ case 0x2033:
+ for (i = 0; i < count; i++)
+ {
+ if (data[i] == 0x0000) // No more devices --> end
+ break;
+ DeviceParseCode(data[i], device.Vendor, device.DeviceIOs);
+ }
+ break;
+ }
+ break;
+ case BuR:
+ // Parse the received data
+ switch (address)
+ {
+ case 0x1083:
+ device.serialCode = data[0];
+ break;
+ case 0x1101:
+ device.DeviceIOs.InputRegisters = data[0];
+ break;
+ case 0x1103:
+ device.DeviceIOs.OutputRegisters = data[0];
+ break;
+ case 0x1105:
+ device.DeviceIOs.InputBits = data[0] * 8; // Unfortunately this is quite imprecise:
+ // in the process image one module will always fill a whole number of bytes.
+ // So 4 12DI modules not allocate not 4*12 bit = 6 byte, but 4*16 bit = 64 bit = 8 byte
+ // See Modbus X20BC0087 documentation v1.11 p. 22
+ break;
+ case 0x1107:
+ device.DeviceIOs.OutputBits = data[0] * 8;
+ break;
+ }
+ break;
+ }
+}
\ No newline at end of file
diff --git a/Modbus-CAPL/include/CAPL/include/ModbusClientCommon.cin b/Modbus-CAPL/include/CAPL/include/ModbusClientCommon.cin
index 7189d5b..af2d93d 100644
--- a/Modbus-CAPL/include/CAPL/include/ModbusClientCommon.cin
+++ b/Modbus-CAPL/include/CAPL/include/ModbusClientCommon.cin
@@ -7,8 +7,6 @@ includes
variables
{
- const word gMaxPacketLength = __size_of(struct ModbusReqWriteRegisters);
-
msTimer gtRobin; // Timer that sends the packets and watches for timeouts
word gTxID = 0x0000; // Transaction Identifier for Modbus. Used as index for gQueue
@@ -18,7 +16,7 @@ variables
word TimeoutTicks;
byte Timeouts;
word Length;
- byte Buffer[gMaxPacketLength];
+ byte Buffer[gModbusMaxTelegramSize];
};
struct QueueElement gQueuePending[long, 2];
struct QueueElement gQueueSent[long, 2];
@@ -48,49 +46,58 @@ void ModbusInit()
ModbusConnectTo(ip, @sysvar::Config::Modbus::Port);
}
-void ModbusMakeHeader(struct ModbusApHeader mbap, word length)
+void ModbusMakeHeader(struct ModbusApHeader mbap, word length, byte funcCode)
{
mbap.TxID = gTxID++; // [2] Transaction ID
mbap.Protocol = 0x0000; // [2] Protocol ID = 0 = Modbus
mbap.Length = length - __offset_of(struct ModbusApHeader, UnitID); // [2] Length; Number of bytes following
mbap.UnitID = 0xFF; // [1] Unit identifier; not relevant
+ mbap.FuncCode = funcCode; // [1] Function Code
}
// REGION: ModbusReadBits -------------------------------------------------------------
///
-void ModbusReadInBits(word address, word count)
+void ModbusReadInBits(word address, long count)
{
ModbusReadBits(0x02, address, count);
}
///
-void ModbusReadBits(word address, word count)
+void ModbusReadBits(word address, long count)
{
ModbusReadBits(0x02, address, count);
}
///
-void ModbusReadOutBits(word address, word count)
+void ModbusReadOutBits(word address, long count)
{
ModbusReadBits(0x01, address, count);
}
///
-void ModbusReadBits(byte funcCode, word address, word count)
+void ModbusReadBits(byte funcCode, word address, long count)
{
const byte length = __size_of(struct ModbusReqRead);
byte buffer[length];
- struct ModbusReqRead mbr;
+ word curCount;
+ struct ModbusReqRead mbreq;
- ModbusMakeHeader(mbr.Header, length);
- // Payload
- mbr.Header.FuncCode = funcCode; // [1] Function Code; 1: Read Coils (DI), 2: Read Discret Inputs (DIO), seems to be the same for WAGO 750-881
- mbr.Address = address; // [2] Start address
- mbr.Count = count; // [2] Number of items; 1:max 2000=0x7D0
+ // FC1: Read Coils (DO), FC2: Read Discret Inputs (DI)
+ while (count > 0)
+ {
+ curCount = count > gMaxBitsPerRead ? gMaxBitsPerRead : count;
+ ModbusMakeHeader(mbreq.Header, length, funcCode);
- writeDbg(MbDebug, "Sending 'Read Bits' (0x01) command. Addr: 0x%04X, Count: %d", address, count);
-
- memcpy_h2n(buffer, mbr);
- ModbusSend(buffer, length, mbr.Header.TxID);
+ mbreq.Address = address; // [2] Start address
+ mbreq.Count = curCount; // [2] Number of items; 1:max 2000=0x7D0
+
+ writeDbg(MbDebug, "Sending 'Read Bits' (0x01) command. TxID: 0x%04X, Addr: 0x%04X, Count: %d", mbreq.Header.TxID, address, curCount);
+
+ memcpy_h2n(buffer, mbreq);
+ ModbusSend(buffer, length, mbreq.Header.TxID);
+
+ count -= gMaxBitsPerRead;
+ address += gMaxBitsPerRead;
+ }
}
///
@@ -98,7 +105,7 @@ void OnModbusReceiveBits(byte buffer[])
{
struct ModbusResReceiveBits mbres;
struct ModbusReqRead mbreq;
- byte bitStatus[1968];
+ byte bitStatus[gMaxBitsPerRead];
word numBits;
byte i, j;
@@ -106,7 +113,6 @@ void OnModbusReceiveBits(byte buffer[])
memcpy_n2h(mbreq, gQueueAck[mbres.Header.TxID].Buffer);
writeDbg(MbInfo, "Received %d bits from 0x%04X", mbreq.Count, mbreq.Address);
-
for (i = 0; i < mbres.ByteCount; i++)
{
for (j = 0; j < 8; j++)
@@ -131,23 +137,45 @@ void OnModbusReceiveBitsException(struct ModbusApHeader mbap, enum ModbusExcepti
// REGION: ModbusReadRegisters -------------------------------------------------------
///
-void ModbusReadRegisters(word address, word count) // 16 bit
+void ModbusReadInRegisters(word address, long count)
+{
+ ModbusReadRegisters(0x04, address, count);
+}
+///
+void ModbusReadRegisters(word address, long count)
+{
+ ModbusReadRegisters(0x04, address, count);
+}
+///
+void ModbusReadOutRegisters(word address, long count)
+{
+ ModbusReadRegisters(0x03, address, count);
+}
+///
+void ModbusReadRegisters(byte funcCode, word address, long count)
{
const byte length = __size_of(struct ModbusReqRead);
- const byte funcCode = 0x03;
byte buffer[length];
- struct ModbusReqRead mbr;
-
- ModbusMakeHeader(mbr.Header, length);
- // Payload
- mbr.Header.FuncCode = funcCode; // [1] Function Code; 3: Read Holding Registers (AI), 4: Read Input Registers (AIO), seems to be the same for WAGO 750-881
- mbr.Address = address; // [2] Start address
- mbr.Count = count; // [2] Number of items; 1:max 125=0x7D
+ word curCount;
+ struct ModbusReqRead mbreq;
- writeDbg(MbDebug, "Sending 'Read Registers' (0x03) command. Addr: 0x%04X, Count: %d", address, count);
+ // FC3: Read Holding Registers (AO), FC4: Read Input Registers (AI)
+ while (count > 0)
+ {
+ curCount = count > gMaxRegsPerRead ? gMaxRegsPerRead : count;
+ ModbusMakeHeader(mbreq.Header, length, funcCode);
- memcpy_h2n(buffer, mbr);
- ModbusSend(buffer, length, mbr.Header.TxID);
+ mbreq.Address = address; // [2] Start address
+ mbreq.Count = curCount; // [2] Number of items; 1:max 125=0x7D
+
+ writeDbg(MbDebug, "Sending 'Read Registers' (0x03) command. TxID: 0x%04X, Addr: 0x%04X, Count: %d", mbreq.Header.TxID, address, curCount);
+
+ memcpy_h2n(buffer, mbreq);
+ ModbusSend(buffer, length, mbreq.Header.TxID);
+
+ count -= gMaxRegsPerRead;
+ address += gMaxRegsPerRead;
+ }
}
///
@@ -182,21 +210,21 @@ void ModbusWriteBit(word address, byte value)
const byte length = __size_of(struct ModbusReqWriteSingle);
const byte funcCode = 0x05; // B&R does not support 0x06
byte buffer[length];
- struct ModbusReqWriteSingle mbw;
+ struct ModbusReqWriteSingle mbreq;
if (value >= 1)
value = 0xFF;
- ModbusMakeHeader(mbw.Header, length);
- // Payload
- mbw.Header.FuncCode = funcCode; // [1] Function Code; 5: Write Single Coil (DO)
- mbw.Address = address; // [2] Output address
- mbw.Value = value << 8; // [2] Output value (0x0000: Off, 0xFF00: On)
+ // FC5: Write Single Coil (DO)
+ ModbusMakeHeader(mbreq.Header, length, funcCode);
- writeDbg(Debug, "Sending 'Write Bit' (0x05) command. Addr: 0x%04X, Value: 0x%02X", address, value);
+ mbreq.Address = address; // [2] Output address
+ mbreq.Value = value << 8; // [2] Output value (0x0000: Off, 0xFF00: On)
+
+ writeDbg(Debug, "Sending 'Write Bit' (0x05) command. TxID: 0x%04X, Addr: 0x%04X, Value: %d", mbreq.Header.TxID, address, value);
- memcpy_h2n(buffer, mbw);
- ModbusSend(buffer, length, mbw.Header.TxID);
+ memcpy_h2n(buffer, mbreq);
+ ModbusSend(buffer, length, mbreq.Header.TxID);
}
///
@@ -224,23 +252,23 @@ void OnModbusConfirmBitException(struct ModbusApHeader mbap, enum ModbusExceptio
// REGION: ModbusWriteRegister ------------------------------------------------------
///
-void ModbusWriteRegister(word address, int value)
+void ModbusWriteRegister(word address, word value)
{
const byte length = __size_of(struct ModbusReqWriteSingle);
const byte funcCode = 0x06;
byte buffer[length];
- struct ModbusReqWriteSingle mbw;
+ struct ModbusReqWriteSingle mbreq;
- ModbusMakeHeader(mbw.Header, length);
- // Payload
- mbw.Header.FuncCode = funcCode; // [1] Function Code; 5: Write Single Register (AO)
- mbw.Address = address; // [2] Output address
- mbw.Value = value; // [2] Output value
+ // 5: Write Single Register (AO)
+ ModbusMakeHeader(mbreq.Header, length, funcCode);
- writeDbg(MbDebug, "Sending 'Write Register' (0x06) command. Addr: 0x%04X, Value: 0x%02X", address, value);
+ mbreq.Address = address; // [2] Output address
+ mbreq.Value = value; // [2] Output value
- memcpy_h2n(buffer, mbw);
- ModbusSend(buffer, length, mbw.Header.TxID);
+ writeDbg(MbDebug, "Sending 'Write Register' (0x06) command. TxID: 0x%04X, Addr: 0x%04X, Value: %d", mbreq.Header.TxID, address, value);
+
+ memcpy_h2n(buffer, mbreq);
+ ModbusSend(buffer, length, mbreq.Header.TxID);
}
///
@@ -270,34 +298,42 @@ void OnModbusConfirmRegisterException(struct ModbusApHeader mbap, enum ModbusExc
// REGION: ModbusWriteBits ----------------------------------------------------------
///
-void ModbusWriteBits(word address, word count, byte values[])
+void ModbusWriteBits(word address, long count, byte values[])
{
const word maxLength = __size_of(struct ModbusReqWriteBits);
const byte funcCode = 0x0F;
byte buffer[maxLength];
- struct ModbusReqWriteBits mbw;
+ struct ModbusReqWriteBits mbreq;
+ word curCount;
byte dataLength;
byte overallLength;
word i;
- dataLength = _ceil(count / 8.0);
- overallLength = maxLength - 1968/8 + dataLength;
- ModbusMakeHeader(mbw.Header, overallLength);
- // Payload
- mbw.Header.FuncCode = funcCode; // [1] Function Code; 15: Write Multiple Bits (DOs)
- mbw.Address = address; // [2] Output address
- mbw.Count = count; // [2] Number of items; 1:max 1968=0x7B0
- mbw.ByteCount = dataLength; // [1] Number of bytes; = ceil(count/8)
- memcpy(mbw.Data, values, dataLength); // this is 1 memcpy too much -.-
+ // FC15: Write Multiple Bits (DOs)
+ while (count > 0)
+ {
+ curCount = count > gMaxBitsPerWrite ? gMaxBitsPerWrite : count;
+ dataLength = _ceil(curCount / 8.0);
+ overallLength = maxLength - gMaxBitsPerWrite/8 + dataLength;
+ ModbusMakeHeader(mbreq.Header, overallLength, funcCode);
- writeDbg(MbDebug, "Sending 'Write Bits' (0x0F) command. Addr: 0x%04X, Count: %d", address, count);
+ mbreq.Address = address; // [2] Output address
+ mbreq.Count = curCount; // [2] Number of items; 1:max 1968=0x7B0
+ mbreq.ByteCount = dataLength; // [1] Number of bytes; = ceil(count/8)
+ memcpy(mbreq.Data, values, dataLength); // [246] Data; this is 1 unneccessary memcpy :( Well, readability...
- memcpy_h2n(buffer, mbw);
- ModbusSend(buffer, overallLength, mbw.Header.TxID);
+ writeDbg(MbDebug, "Sending 'Write Bits' (0x0F) command. Addr: 0x%04X, Count: %d", address, curCount);
+
+ memcpy_h2n(buffer, mbreq);
+ ModbusSend(buffer, overallLength, mbreq.Header.TxID);
+
+ count -= gMaxBitsPerWrite;
+ address += gMaxBitsPerWrite;
+ }
}
///
-void ModbusWriteBitsB(word address, word count, byte values[])
+void ModbusWriteBitsB(word address, long count, byte values[])
{
byte buffer[2]; // length
word length;
@@ -361,31 +397,38 @@ void OnModbusConfirmBitsException(struct ModbusApHeader mbap, enum ModbusExcepti
// REGION: ModbusWriteRegisters -------------------------------------------------------
///
-void ModbusWriteRegisters(word address, word count, word values[])
+void ModbusWriteRegisters(word address, long count, word values[])
{
const word maxLength = __size_of(struct ModbusReqWriteRegisters);
const byte funcCode = 0x10;
byte buffer[maxLength];
- struct ModbusReqWriteRegisters mbw;
+ struct ModbusReqWriteRegisters mbreq;
+ word curCount;
byte dataLength;
word overallLength;
word i;
- dataLength = 2 * count;
- overallLength = maxLength - 2*123 + dataLength;
+ // FC16: Write Multiple Registers (AOs)
+ while (count > 0)
+ {
+ curCount = count > gMaxRegsPerWrite ? gMaxRegsPerWrite : count;
+ dataLength = 2 * curCount;
+ overallLength = maxLength - 2*gMaxRegsPerWrite + dataLength;
- ModbusMakeHeader(mbw.Header, overallLength);
- // Payload
- mbw.Header.FuncCode = funcCode; // [1] Function Code; 16: Write Multiple Registers (AOs)
- mbw.Address = address; // [2] Output address
- mbw.Count = count; // [2] Number of items; 1:max 123=0x7B
- mbw.ByteCount = dataLength; // [1] Number of bytes; = 2 * count
+ ModbusMakeHeader(mbreq.Header, overallLength, funcCode);
- for (i = 0; i < dataLength; i++)
- mbw.Data[i] = values[i];
+ mbreq.Address = address; // [2] Output address
+ mbreq.Count = curCount; // [2] Number of items; 1:max 123=0x7B
+ mbreq.ByteCount = dataLength; // [1] Number of bytes; = 2 * count
- memcpy_h2n(buffer, mbw);
- ModbusSend(buffer, overallLength, mbw.Header.TxID);
+ for (i = 0; i < curCount; i++)
+ mbreq.Data[i] = values[i];
+ for ( ; i < gMaxRegsPerWrite; i++) // do we need this?
+ mbreq.Data[i] = 0;
+
+ memcpy_h2n(buffer, mbreq);
+ ModbusSend(buffer, overallLength, mbreq.Header.TxID);
+ }
}
///
@@ -419,17 +462,17 @@ void ModbusWriteMasks(word address, word and, word or)
const word length = __size_of(struct ModbusReqWriteMasks);
const byte funcCode = 0x16;
byte buffer[length];
- struct ModbusReqWriteMasks mbw;
+ struct ModbusReqWriteMasks mbreq;
- ModbusMakeHeader(mbw.Header, length);
- // Payload
- mbw.Header.FuncCode = funcCode; // [1] Function Code; 22: Mask Write Registers (AO)
- mbw.Address = address; // [2] Output address
- mbw.And = and; // [2] AND mask
- mbw.Or = or; // [2] OR mask
+ // FC22: Mask Write Registers (AO)
+ ModbusMakeHeader(mbreq.Header, length, funcCode);
- memcpy_h2n(buffer, mbw);
- ModbusSend(buffer, length, mbw.Header.TxID);
+ mbreq.Address = address; // [2] Output address
+ mbreq.And = and; // [2] AND mask
+ mbreq.Or = or; // [2] OR mask
+
+ memcpy_h2n(buffer, mbreq);
+ ModbusSend(buffer, length, mbreq.Header.TxID);
}
///
@@ -457,33 +500,48 @@ void OnModbusConfirmMasksException(struct ModbusApHeader mbap, enum ModbusExcept
// REGION: ModbusReadWriteRegisters -------------------------------------------------------
///
-void ModbusReadWriteRegisters(word readAddress, word readCount, word writeAddress, word writeCount, int values[])
+void ModbusReadWriteRegisters(word readAddress, long readCount, word writeAddress, long writeCount, word values[])
{
const word maxLength = __size_of(struct ModbusReqReadWriteRegisters);
const byte funcCode = 0x17;
byte buffer[maxLength];
- struct ModbusReqReadWriteRegisters mbw;
+ struct ModbusReqReadWriteRegisters mbreq;
byte dataLength;
word overallLength;
- word i;
+ word i, offset;
+
+ offset = 0;
+ if (readCount > gMaxRegsPerRead - 2) // if we have to split the read request. count = n*max + y
+ {
+ ModbusReadRegisters(readAddress, readCount - readCount % gMaxRegsPerRead); // let this function read the main part: n*max
+ readAddress += readCount - readCount % gMaxRegsPerRead; // increment address by n*max
+ readCount %= gMaxRegsPerRead; // only read y elements in this function
+ }
+ if (writeCount > gMaxRegsPerWrite - 2) // if we have to split the write request. count = n*max + y
+ {
+ ModbusWriteRegisters(writeAddress, writeCount - writeCount % gMaxRegsPerWrite, values); // let this function read the main part: n*max
+ offset = writeCount - writeCount % gMaxRegsPerWrite; // start reading values at n*max
+ writeAddress += offset; // increment address by n*max
+ writeCount %= gMaxRegsPerWrite; // only read y elements in this function
+ }
dataLength = 2 * writeCount;
- overallLength = maxLength - 2*121 + dataLength;
+ overallLength = maxLength - 2*(gMaxRegsPerWrite-2) + dataLength;
- ModbusMakeHeader(mbw.Header, overallLength);
- // Payload
- mbw.Header.FuncCode = funcCode; // [1] Function Code; 16: Write Multiple Registers (AOs)
- mbw.ReadAddress = readAddress; // [2] Input address
- mbw.ReadCount = readCount; // [2] Number of items; 1:max 125=0x7D
- mbw.WriteAddress = writeAddress;// [2] Output address
- mbw.WriteCount = writeCount; // [2] Number of items; 1:max 121=0x79
- mbw.ByteCount = dataLength; // [1] Number of bytes; = 2 * count
+ // FC16: Write Multiple Registers (AOs)
+ ModbusMakeHeader(mbreq.Header, overallLength, funcCode);
- for (i = 0; i < dataLength; i++)
- mbw.Data[i] = values[i];
+ mbreq.ReadAddress = readAddress; // [2] Input address
+ mbreq.ReadCount = readCount; // [2] Number of items; 1:max 125=0x7D
+ mbreq.WriteAddress = writeAddress; // [2] Output address
+ mbreq.WriteCount = writeCount; // [2] Number of items; 1:max 121=0x79
+ mbreq.ByteCount = dataLength; // [1] Number of bytes; = 2 * count
- memcpy_h2n(buffer, mbw);
- ModbusSend(buffer, overallLength, mbw.Header.TxID);
+ for (i = 0; i < writeCount; i++)
+ mbreq.Data[i] = values[i + offset];
+
+ memcpy_h2n(buffer, mbreq);
+ ModbusSend(buffer, overallLength, mbreq.Header.TxID);
}
///
@@ -545,7 +603,7 @@ void OnModbusReceive(dword socket, long result, dword address, dword port, byte
void OnModbusReceive2(byte buffer[], dword size)
{
struct ModbusApHeader mbap;
- int offset;
+ long offset;
char str[3*20];
if (size < 8) // No complete Modbus Application Header
@@ -579,7 +637,7 @@ void OnModbusReceive2OnePacket(byte buffer[], int offset, struct ModbusApHeader
// Test unit/device identifier?
word i; // counter
word length; // length of current packet
- byte mbuffer[__size_of(struct ModbusResReceiveRegisters)]; // second buffer where we copy the message. This way the user won't overwrite other packages.
+ byte mbuffer[gModbusMaxTelegramSize]; // second buffer where we copy the message. This way the user won't overwrite other packages.
length = __offset_of(struct ModbusApHeader, UnitID) + mbap.Length;
// We cannot check this properly anymore. We have to trust the TCP/UDP stack and the sender... *sigh*
@@ -597,7 +655,7 @@ void OnModbusReceive2OnePacket(byte buffer[], int offset, struct ModbusApHeader
}
// MBAP Header is OK :) Go on
- if (!gQueueSent.ContainsKey(mbap.TxID)) // We don't wait for this message!
+ if (!gQueueSent.ContainsKey(mbap.TxID)) // We don't wait for this message!?
return;
//write("Received TxID: %d", mbap.TxID);
@@ -613,7 +671,6 @@ void OnModbusReceive2OnePacket(byte buffer[], int offset, struct ModbusApHeader
return;
}
-
// Copy the message
memcpy_off(mbuffer, 0, buffer, offset, length);
@@ -780,8 +837,8 @@ on timer gtRobin
// Second: send new packets
for (long TxID : gQueuePending)
{
- if (gQueueSent.Size() > 4) // Wago 750-881 cannot handle more than 5 messages at a time :(
- continue;
+ if (gQueueSent.Size() >= gDevReceiveWindow) // Device cannot handle many messages at a time
+ break;
// if packet was sent or the socket is not currently being opened
if (ModbusSnd(gQueuePending[TxID].Buffer, gQueuePending[TxID].Length) == 0 || gSocketState != NULL)
diff --git a/Modbus-CAPL/include/CAPL/include/ModbusFunctions.cin b/Modbus-CAPL/include/CAPL/include/ModbusFunctions.cin
deleted file mode 100644
index fc4a429..0000000
--- a/Modbus-CAPL/include/CAPL/include/ModbusFunctions.cin
+++ /dev/null
@@ -1,72 +0,0 @@
-/*@!Encoding:1252*/
-variables
-{
- struct deviceIOs
- {
- byte InputRegisters;
- word InputBits;
- byte OutputRegisters;
- word OutputBits;
- char Modules[1024];
- };
-}
-
-void ParseDeviceCode(word dev, enum Vendor vendor, struct deviceIOs dios)
-{
- byte input;
- byte numChannels;
- char module[10];
-
- switch(vendor)
- {
- case Wago: // if this is a Wago device
-
- if (dev & 0x8000) // Digital Module
- {
- numChannels = (dev >> 8) & 0x007F;
-
- if (dev & 0x0001) // Input Module
- {
- input = 1;
- strncpy(module, "DI%d,", elCount(module));
- }
- else if (dev & 0x0002) // Output Module
- {
- input = 0;
- strncpy(module, "DO%d,", elCount(module));
- }
- else // blööd
- {
- writeDbg(AlgoError, "ParseDeviceCode: Device code 0x%X cannot be decoded", dev);
- OnModbusClientPanics(DeviceCodeUnknown);
- }
- }
- else
- {
- switch (dev)
- {
- case 881: // devices that have no inputs/outputs
- return;
- case 477: // devices that have 2 inputs
- input = 1;
- numChannels = 2;
- break;
- default: // unknown device. Ouch!
- writeDbg(AlgoInfo, "Connected device: 750-%d", dev);
- return;
- }
- if (input)
- strncpy(module, "AI%d,", elCount(module));
- else
- strncpy(module, "AO%d,", elCount(module));
- }
- break; // switch(vendor)
- default:
- writeDbg(AlgoError, "ParseDeviceCode: Unknown vendor id: %d", vendor);
- OnModbusClientPanics(VendorIdUnknown);
- return;
- }
-
- snprintf(module, elCount(module), module, numChannels);
- strncat(dios.Modules, module, elCount(dios.Modules));
-}
\ No newline at end of file
diff --git a/Modbus-CAPL/include/CAPL/include/ModbusStructs.cin b/Modbus-CAPL/include/CAPL/include/ModbusStructs.cin
index 5aaa6c1..ef17756 100644
--- a/Modbus-CAPL/include/CAPL/include/ModbusStructs.cin
+++ b/Modbus-CAPL/include/CAPL/include/ModbusStructs.cin
@@ -1,6 +1,12 @@
/*@!Encoding:1252*/
variables
{
+ // according to Modbus Specification v1.1
+ const word gMaxBitsPerRead = 2000;
+ const word gMaxRegsPerRead = 125;
+ const word gMaxBitsPerWrite = 1968;
+ const word gMaxRegsPerWrite = 123;
+
// A normal Modbus Application Header. Every Modbus Packet begins with these 7 (+FuncCode) Bytes
_align(1) struct ModbusApHeader
{
@@ -31,7 +37,7 @@ variables
word Address;
word Count;
byte ByteCount;
- byte Data[246]; // Max length: 1968 bits
+ byte Data[gMaxBitsPerWrite/8]; // Max length: 1968 bits
};
// Write several values to bits starting with Address
_align(1) struct ModbusReqWriteRegisters
@@ -40,7 +46,7 @@ variables
word Address;
word Count;
byte ByteCount;
- word Data[123]; // Max length: 123 registers
+ word Data[gMaxRegsPerWrite]; // Max length: 123 registers
};
// Write AND and OR masks to a holding register
_align(1) struct ModbusReqWriteMasks
@@ -59,7 +65,7 @@ variables
word WriteAddress;
word WriteCount;
byte ByteCount;
- word Data[121]; // Max length: 123-2 registers
+ word Data[gMaxRegsPerWrite-2]; // Max length: 123-2 registers
};
@@ -68,14 +74,14 @@ variables
{
struct ModbusApHeader Header;
byte ByteCount;
- byte Data[250]; // Max length: 2000 bits
+ byte Data[gMaxBitsPerRead/8]; // Max length: 2000 bits
};
// Receive several register values
_align(1) struct ModbusResReceiveRegisters
{
struct ModbusApHeader Header;
byte ByteCount;
- word Data[125]; // Max length: 125 registers
+ word Data[gMaxRegsPerRead]; // Max length: 125 registers
};
// Confirm the write of a single bit/register
_align(1) struct ModbusResConfirmSingle
@@ -100,6 +106,7 @@ variables
word Or;
};
+ const word gModbusMaxTelegramSize = __size_of(struct ModbusResReceiveRegisters);
enum ModbusRequestError
@@ -107,7 +114,7 @@ variables
Exception,
Timeout,
FinalTimeout
- };
+ };
enum ModbusException
{
None = 0x00,
@@ -143,9 +150,4 @@ variables
VendorIdUnknown = 0x03,
ConnectionError = 0x04
};
- enum Vendor
- {
- Wago = 23,
- BuR = 2
- };
}
\ No newline at end of file
diff --git a/Modbus-CAPL/include/DBC/MakeConfig.ini b/Modbus-CAPL/include/DBC/MakeConfig.ini
index e7255ca..5a90901 100644
--- a/Modbus-CAPL/include/DBC/MakeConfig.ini
+++ b/Modbus-CAPL/include/DBC/MakeConfig.ini
@@ -52,7 +52,7 @@ COLUMNWIDTHS=125,100,100,150,100,100,
HIDDEN=
ORDER=0,1,2,3,4,
DEFINITIONS=1,
-COLUMNWIDTHS=125,125,100,150,100,
+COLUMNWIDTHS=125,125,100,150,123,
[View_NetworkTxMessages]
HIDDEN=
ORDER=0,1,2,3,4,5,6,7,8,
diff --git a/Modbus-CAPL/include/SysVars/generated.vsysvar b/Modbus-CAPL/include/SysVars/generated.vsysvar
index 61a9c19..03feb1f 100644
--- a/Modbus-CAPL/include/SysVars/generated.vsysvar
+++ b/Modbus-CAPL/include/SysVars/generated.vsysvar
@@ -1,16 +1,6 @@
-
-
-
-
-
-
-
-
-
-
@@ -18,25 +8,25 @@
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
@@ -45,27 +35,37 @@
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file