Bachelorthesis/Modbus-CAPL/include/CAPL/ModbusClient.can
Jonny007-MKD 93dd56469d ModbusClientCommon.cin
Introduced loops to automatically split requests that are too large for Modbus

ModbusClient.can
  Modified Modbus events so that the split requests (see above) will be written at the correct position in sys vars

ModbusFunctions.cin
DeviceInformation.cin
  Introduced new file that will handle most device specific things

ModbusStructs.cin
  Introduced new constants with maximum Modbus values

MakeConfig.can
  Increment IP address with swapDWord
  Moved detection stuff to DeviceInformation.cin
2014-06-17 14:21:45 +00:00

241 lines
7.5 KiB
Plaintext

/*@!Encoding:1252*/
includes
{
#include "include\ModbusUdpClientCommon.cin"
#include "include\DeviceInformation.cin"
}
variables
{
msTimer gtRead;
}
on preStart
{
writeClear(0);
setStartdelay(10);
OutputDebugLevel = MbDebug;
}
on start
{
DeviceInit(@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::Vendor);
ModbusInit();
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);
}
// Modbus events ----------------------------------------------------------------------
void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
{
word i;
switch (error)
{
case Exception:
break;
case Timeout:
break;
case FinalTimeout:
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] = -1;
sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputBits");
break;
}
}
void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
{
byte i;
switch (error)
{
case Exception:
break;
case Timeout:
break;
case FinalTimeout:
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] = -1;
sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputRegisters");
break;
}
}
void OnModbusWriteBitFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
{
}
void OnModbusWriteRegisterFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
{
}
void OnModbusWriteMasksFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
{
}
void OnModbusReadWriteRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
{
}
void OnModbusWriteBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
{
}
void OnModbusWriteRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
{
}
void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq)
{
word i, offset;
switch (mbres.Header.FuncCode) // We assume that we separate between 0x01 and 0x02 even though the address space may be the same
{
case 0x01: // Read output bits
sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputBits");
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;
case 0x02: // Read input bits
sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputBits");
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;
}
}
void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct ModbusReqRead mbreq)
{
word i, offset;
switch (mbres.Header.FuncCode) // We assume that we separate between 0x03 and 0x04 even though the address space may be the same
{
case 0x03: // Read output registers
sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputRegisters");
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 0x04: // Read input registers
sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputRegisters");
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;
}
}
void OnModbusWriteBitSuccess(struct ModbusResConfirmSingle mbc)
{
}
void OnModbusWriteRegisterSuccess(struct ModbusResConfirmSingle mbc)
{
}
void OnModbusWriteBitsSuccess(struct ModbusResConfirmMultiple mbc)
{
}
void OnModbusWriteRegistersSuccess(struct ModbusResConfirmMultiple mbc)
{
}
void OnModbusWriteMasksSuccess(struct ModbusResConfirmMasks mbc)
{
}
void OnModbusClientPanics(enum FatalErrors reason)
{
writeLineEx(0, 4, "<%NODE_NAME%> FATAL! %d", reason);
switch(reason)
{
case ParsingBuffer:
case ModbusPackageWasSplit:
case DeviceCodeUnknown:
case VendorIdUnknown:
runError(1001, reason);
break;
case ConnectionError:
gtRead.Cancel();
break;
}
}
// Key events -------------------------------------------------------------------------
on timer gtRead
{
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
{
word count, i;
byte bitStatus[1968];
count = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits;
for (i = 0; i < count; i++)
bitStatus[i] = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits[i];
ModbusWriteBitsB(0, count, bitStatus);
}
on sysvar %BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputRegisters
{
word count, i;
word regValues[123];
count = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputRegisters;
for (i = 0; i < count; i++)
regValues[i] = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputRegisters[i];
ModbusWriteRegisters(0x000, count, regValues);
}
on sysvar %BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config::Interval
{
if (@this <= 0)
gtRead.Cancel();
else
setTimerCyclic(gtRead, @this);
}
on key '+'
{
word i;
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] = 1;
sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputBits");
}
on key '-'
{
word i;
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] = 0;
sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputBits");
}