168 lines
4.5 KiB
Plaintext
168 lines
4.5 KiB
Plaintext
/*@!Encoding:1252*/
|
|
variables
|
|
{
|
|
// Constant maximum values according to Modbus Specification v1.1
|
|
const word gMaxBitsPerRead = 2000;
|
|
const word gMaxRegsPerRead = 125;
|
|
const word gMaxBitsPerWrite = 1968; // Multiple of 8!
|
|
const word gMaxRegsPerWrite = 123;
|
|
|
|
// Function Codes according to Modbus Specification v1.1
|
|
enum ModbusFuncCode
|
|
{
|
|
ReadBitsOut = 0x01, // Read Coils
|
|
ReadBitsIn = 0x02, // Read Discrete Inputs
|
|
ReadRegistersOut = 0x03, // Read Holding Registers
|
|
ReadRegistersIn = 0x04, // Read Input Registers
|
|
WriteBit = 0x05, // Write Single Coil
|
|
WriteRegister = 0x06, // Write Single Holding Register
|
|
WriteBits = 0x0F, // Write Multiple Coils
|
|
WriteRegisters = 0x10, // Write Multiple Holding Registers
|
|
MaskRegister = 0x16, // Mask Write Holding Register
|
|
ReadWriteRegisters = 0x17 // Read/Write Multiple Registers
|
|
};
|
|
|
|
// Modbus Application Header
|
|
// Every Modbus Packet begins with these 7 (+FuncCode) Bytes
|
|
_align(1) struct ModbusApHeader
|
|
{
|
|
word TxID;
|
|
word Protocol;
|
|
word Length;
|
|
byte UnitID;
|
|
byte FuncCode;
|
|
};
|
|
|
|
/// Request structures following
|
|
// Read Data from the host. We only need the start address and the number of bits/registers we want to read
|
|
_align(1) struct ModbusReqRead
|
|
{
|
|
struct ModbusApHeader Header;
|
|
word Address;
|
|
word Count;
|
|
};
|
|
// Write a single value to a bit/register
|
|
_align(1) struct ModbusReqWriteSingle
|
|
{
|
|
struct ModbusApHeader Header;
|
|
word Address;
|
|
word Value;
|
|
};
|
|
// Write several values to a bit/register starting with Address
|
|
_align(1) struct ModbusReqWriteBits
|
|
{
|
|
struct ModbusApHeader Header;
|
|
word Address;
|
|
word Count;
|
|
byte ByteCount;
|
|
byte Data[gMaxBitsPerWrite/8]; // Max length: 1968 bits
|
|
};
|
|
// Write several values to bits starting with Address
|
|
_align(1) struct ModbusReqWriteRegisters
|
|
{
|
|
struct ModbusApHeader Header;
|
|
word Address;
|
|
word Count;
|
|
byte ByteCount;
|
|
word Data[gMaxRegsPerWrite]; // Max length: 123 registers
|
|
};
|
|
// Write AND and OR masks to a holding register
|
|
_align(1) struct ModbusReqWriteMasks
|
|
{
|
|
struct ModbusApHeader Header;
|
|
word Address;
|
|
word And;
|
|
word Or;
|
|
};
|
|
// Read and write multiple registers
|
|
_align(1) struct ModbusReqReadWriteRegisters
|
|
{
|
|
struct ModbusApHeader Header;
|
|
word ReadAddress;
|
|
word ReadCount;
|
|
word WriteAddress;
|
|
word WriteCount;
|
|
byte ByteCount;
|
|
word Data[gMaxRegsPerWrite-2]; // Max length: 123-2 registers
|
|
};
|
|
|
|
|
|
/// Response structures following
|
|
// Receive several bit values
|
|
_align(1) struct ModbusResReceiveBits
|
|
{
|
|
struct ModbusApHeader Header;
|
|
byte ByteCount;
|
|
byte Data[gMaxBitsPerRead/8]; // Max length: 2000 bits
|
|
};
|
|
// Receive several register values
|
|
_align(1) struct ModbusResReceiveRegisters
|
|
{
|
|
struct ModbusApHeader Header;
|
|
byte ByteCount;
|
|
word Data[gMaxRegsPerRead]; // Max length: 125 registers
|
|
};
|
|
// Confirm the write of a single bit/register
|
|
_align(1) struct ModbusResConfirmSingle
|
|
{
|
|
struct ModbusApHeader Header;
|
|
word Address;
|
|
int Value;
|
|
};
|
|
// Confirm the write of several bits/registers
|
|
_align(1) struct ModbusResConfirmMultiple
|
|
{
|
|
struct ModbusApHeader Header;
|
|
word Address;
|
|
word Count;
|
|
};
|
|
// Confirm the write of AND and OR mask
|
|
_align(1) struct ModbusResConfirmMasks
|
|
{
|
|
struct ModbusApHeader Header;
|
|
word Address;
|
|
word And;
|
|
word Or;
|
|
};
|
|
|
|
// The maximum modbus telegram size.
|
|
// Several telegrams use this many bytes, but CAPL does not support a constant max function to let it calculate it. So we use ModbusResReceiveRegisters
|
|
const word gModbusMaxTelegramSize = __size_of(struct ModbusResReceiveRegisters);
|
|
|
|
|
|
// Some errors that may occur when sending a request
|
|
enum ModbusRequestError
|
|
{
|
|
Exception, // Modbus exception was returned
|
|
Timeout, // Timeout occured, resending the packet
|
|
FinalTimeout, // Timeout occured, not resending the packet
|
|
NotSent // Sending the packet was impossible
|
|
};
|
|
|
|
// Modbus exception codes according to Modbus Specification v1.1
|
|
enum ModbusException
|
|
{
|
|
None = 0x00,
|
|
IllegalFuncCode = 0x01,
|
|
IllegalDataAddress = 0x02,
|
|
IllegalDataValue = 0x03,
|
|
ServerFailure = 0x04,
|
|
Acknowledge = 0x05,
|
|
ServerBusy = 0x06,
|
|
GatewayPathsNA = 0x0A,
|
|
TargetOffline = 0x0B
|
|
};
|
|
|
|
// Fatal errors that may stop the code execution
|
|
enum FatalErrors
|
|
{
|
|
ParsingBuffer,
|
|
ModbusPackageWasSplit,
|
|
DeviceCodeUnknown,
|
|
VendorIdUnknown,
|
|
ConnectionError,
|
|
FuncCodeIncorrect,
|
|
AddressFailure,
|
|
SwitchArgumentInvalid
|
|
};
|
|
} |