|
rllib
1
|
#include <rlmodbus.h>

Public Types | |
| enum | Modbus { MODBUS_CHECKSUM_ERROR = -2, MODBUS_ERROR = -1, MODBUS_SUCCESS = 0, MODBUS_RTU = 1, MODBUS_ASCII = 2 } |
| enum | ModbusFunctionCodes { ReadCoilStatus = 1, ReadInputStatus = 2, ReadHoldingRegisters = 3, ReadInputRegisters = 4, ForceSingleCoil = 5, PresetSingleRegister = 6, ReadExceptionStatus = 7, FetchCommEventCtr = 11, FetchCommEventLog = 12, ForceMultipleCoils = 15, PresetMultipleRegs = 16, ReportSlaveID = 17, ReadGeneralReference = 20, WriteGeneralReference = 21, MaskWrite4XRegisters = 22, ReadWrite4XRegisters = 23, ReadFifoQueue = 24 } |
Public Member Functions | |
| rlModbus (long max_telegram_length=1024, int mode=MODBUS_RTU, char end_delimitor=0x0a) | |
| virtual | ~rlModbus () |
| int | write (int slave, int function, const unsigned char *data, int len, int *transactionID=NULL) |
| int | request (int slave, int function, int start_adr, int num_register) |
| int | response (int *slave, int *function, unsigned char *data, int timeout=1000) |
| int | readRequest (int *slave, int *function, unsigned char *data, int timeout=1000, int *transactionID=NULL) |
| void | registerSocket (rlSocket *socket) |
| void | registerSerial (rlSerial *serial) |
| int | data2int (const unsigned char *data) |
| int | int2data (int val, unsigned char *data) |
| int | intsize () |
Public Attributes | |
| int | autoreconnectSocket |
Private Member Functions | |
| int | buf2int_rtu (unsigned char *buf) |
| void | int2buf_rtu (int i, unsigned char *buf) |
| int | buf2int_ascii (unsigned char *buf) |
| void | int2buf_ascii (int i, unsigned char *buf) |
| void | insertLRC (int len) |
| void | insertCRC (int len) |
| int | LRCerror (int len) |
| int | CRCerror (int len) |
Private Attributes | |
| rlSocket * | s |
| rlSerial * | tty |
| unsigned char * | tel |
| long | maxtel |
| int | mode |
| char | delimitor |
This class implements the modbus protocol. You can use serial interfaces or TCP/IP. Modbus RTU and ASCII are available.
Definition at line 28 of file rlmodbus.h.
| enum rlModbus::Modbus |
Definition at line 31 of file rlmodbus.h.
{
MODBUS_CHECKSUM_ERROR = -2,
MODBUS_ERROR = -1,
MODBUS_SUCCESS = 0,
MODBUS_RTU = 1,
MODBUS_ASCII = 2
};
Definition at line 40 of file rlmodbus.h.
{
ReadCoilStatus = 1,
ReadInputStatus = 2,
ReadHoldingRegisters = 3,
ReadInputRegisters = 4,
ForceSingleCoil = 5,
PresetSingleRegister = 6,
ReadExceptionStatus = 7,
FetchCommEventCtr = 11,
FetchCommEventLog = 12,
ForceMultipleCoils = 15,
PresetMultipleRegs = 16,
ReportSlaveID = 17,
ReadGeneralReference = 20,
WriteGeneralReference = 21,
MaskWrite4XRegisters = 22,
ReadWrite4XRegisters = 23,
ReadFifoQueue = 24
};
| rlModbus::rlModbus | ( | long | max_telegram_length = 1024, |
| int | mode = MODBUS_RTU, |
||
| char | end_delimitor = 0x0a |
||
| ) |
Definition at line 20 of file rlmodbus.cpp.
| rlModbus::~rlModbus | ( | ) | [virtual] |
Definition at line 32 of file rlmodbus.cpp.
| int rlModbus::buf2int_ascii | ( | unsigned char * | buf | ) | [private] |
Definition at line 612 of file rlmodbus.cpp.
{
int val;
sscanf((char *) buf,"%04X",&val);
return val;
}
| int rlModbus::buf2int_rtu | ( | unsigned char * | buf | ) | [private] |
Definition at line 597 of file rlmodbus.cpp.
{
return (buf[0]*256 + buf[1]);
}
| int rlModbus::CRCerror | ( | int | len | ) | [private] |
Definition at line 746 of file rlmodbus.cpp.
{
unsigned char crc_high, crc_low;
unsigned index;
int i;
if(len < 2) return 1;
crc_high = crc_low = 0xff;
for(i=0; i<len-2; i++)
{
index = crc_low ^ tel[i];
crc_low = crc_high ^ array_crc_low[index];
crc_high = array_crc_high[index];
}
if(crc_low != tel[len-2]) return 1;
if(crc_high != tel[len-1]) return 1;
return 0;
}
| int rlModbus::data2int | ( | const unsigned char * | data | ) |
Definition at line 37 of file rlmodbus.cpp.
{
return (data[0]*256)+data[1];
}
| void rlModbus::insertCRC | ( | int | len | ) | [private] |
Definition at line 728 of file rlmodbus.cpp.
{
unsigned char crc_high, crc_low;
unsigned index;
int i;
if(len < 0) return;
crc_high = crc_low = 0xff;
for(i=0; i<len; i++)
{
index = crc_low ^ tel[i];
crc_low = crc_high ^ array_crc_low[index];
crc_high = array_crc_high[index];
}
tel[len] = crc_low;
tel[len+1] = crc_high;
}
| void rlModbus::insertLRC | ( | int | len | ) | [private] |
Definition at line 625 of file rlmodbus.cpp.
{
unsigned char lrc;
int i,high,low,val;
if(len < 0) return;
lrc = 0;
for(i=1; i<len; i+=2) // exclude starting ':' and trailing <CR><LF>
{
sscanf((const char *) &tel[i], "%1X", &high);
sscanf((const char *) &tel[i+1], "%1X", &low);
val = high*16 + low;
lrc += val;
}
lrc = ((unsigned char)(-((char) lrc)));
sprintf((char *) &tel[len],"%02X",(unsigned int) lrc);
}
| void rlModbus::int2buf_ascii | ( | int | i, |
| unsigned char * | buf | ||
| ) | [private] |
Definition at line 620 of file rlmodbus.cpp.
{
sprintf((char *) buf,"%04X",i);
}
| void rlModbus::int2buf_rtu | ( | int | i, |
| unsigned char * | buf | ||
| ) | [private] |
Definition at line 602 of file rlmodbus.cpp.
{
int high, low;
high = i / 256;
low = i & 0x0ff;
buf[0] = (unsigned char) high;
buf[1] = (unsigned char) low;
}
| int rlModbus::int2data | ( | int | val, |
| unsigned char * | data | ||
| ) |
Definition at line 42 of file rlmodbus.cpp.
{
data[0] = (unsigned char) val / 256;
data[1] = (unsigned char) val & 0x0ff;
return 0;
}
| int rlModbus::intsize | ( | ) |
Definition at line 49 of file rlmodbus.cpp.
{
return 2;
}
| int rlModbus::LRCerror | ( | int | len | ) | [private] |
Definition at line 643 of file rlmodbus.cpp.
{
unsigned char *cptr;
unsigned char lrc;
int i,high,low,val;
if(len < 0) return 1;
tel[maxtel-1] = '\0';
cptr = (unsigned char *) strchr((char *)tel,':');
if(cptr == NULL) return 1;
cptr++;
lrc = 0;
for(i=1; i<len+2; i+=2) // exclude starting ':' and trailing <CR><LF>
{ // len is without lrc -> len+2
sscanf((const char *) cptr++, "%1X", &high);
sscanf((const char *) cptr++, "%1X", &low);
val = high*16 + low;
lrc += val;
}
if(lrc == 0) return 0; // lrc ok
return 1; // lrc error
}
| int rlModbus::readRequest | ( | int * | slave, |
| int * | function, | ||
| unsigned char * | data, | ||
| int | timeout = 1000, |
||
| int * | transactionID = NULL |
||
| ) |
Definition at line 350 of file rlmodbus.cpp.
{
unsigned char *telptr;
int ret,len,byte_count,i,itel,val;
len = 0;
if(mode != MODBUS_ASCII && mode != MODBUS_RTU) return MODBUS_ERROR;
if(s != NULL)
{
if(s->isConnected() == 0) return MODBUS_ERROR;
if(mode == MODBUS_RTU)
{
if(s->read((char *) tel, 6, timeout) <= 0) return MODBUS_ERROR;
if(transactionID != NULL) *transactionID = tel[0] * 256 + tel[1]; // return transactionID
// bytes 0,1 Transaction ID faithfully copied from the request message
// bytes 2,3 Protocol number always zero
// byte 4 Response length (upper byte) Always zero
// byte 5 Response length (lower byte). Equal to the number of bytes which follow
// Here comes the normal Modus telegram
if(s->read((char *) tel, 2, timeout) <= 0) return MODBUS_ERROR;
*slave = tel[0];
*function = tel[1];
switch(*function)
{
case ReadCoilStatus:
case ReadInputStatus:
case ReadHoldingRegisters:
case ReadInputRegisters:
case ForceSingleCoil:
case PresetSingleRegister:
if(s->read((char *) data, 4, timeout) <= 0) return MODBUS_ERROR;
return 4;
case ReadExceptionStatus:
case FetchCommEventCtr:
case FetchCommEventLog:
case ReportSlaveID:
return 0;
case ForceMultipleCoils:
case PresetMultipleRegs:
if(s->read((char *) data, 5, timeout) <= 0) return MODBUS_ERROR;
byte_count = data[4];
if(s->read((char *) &data[4], byte_count, timeout) <= 0) return MODBUS_ERROR;
return 4+byte_count;
case ReadGeneralReference:
case WriteGeneralReference:
if(s->read((char *) data, 1, timeout) <= 0) return MODBUS_ERROR;
byte_count = data[0];
if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
return byte_count;
case MaskWrite4XRegisters:
if(s->read((char *) data, 6, timeout) <= 0) return MODBUS_ERROR;
return 6;
case ReadWrite4XRegisters:
if(s->read((char *) data, 9, timeout) <= 0) return MODBUS_ERROR;
byte_count = data[8];
if(s->read((char *) &data[8], byte_count, timeout) <= 0) return MODBUS_ERROR;
return 8+byte_count;
case ReadFifoQueue:
if(s->read((char *) data, 2, timeout) <= 0) return MODBUS_ERROR;
return 2;
default:
return MODBUS_ERROR;
}
}
}
else if(tty != NULL)
{
if(mode == MODBUS_ASCII)
{
//printf("modbus ascii\n");
for(i=0; i<maxtel; i++)
{
ret = tty->select(timeout);
if(ret == 0) return MODBUS_ERROR;
//printf("readChar\n");
itel = tty->readChar();
if(itel < 0) return MODBUS_ERROR;
tel[i] = (unsigned char) itel;
if(tel[i] == 0x0d && delimitor != 0x0a) break;
if(tel[i] == 0x0a) break;
}
tel[i] = '\0';
telptr = (unsigned char *) strchr((const char *) tel,':');
if(telptr == NULL) return MODBUS_ERROR;
len++;
sscanf((char *) &telptr[len],"%02X",slave); len += 2;
sscanf((char *) &telptr[len],"%02X",function); len += 2;
switch(*function)
{
case ReadCoilStatus:
case ReadInputStatus:
case ReadHoldingRegisters:
case ReadInputRegisters:
case ForceSingleCoil:
case PresetSingleRegister:
sscanf((char *) &telptr[len],"%02X",&val); data[0] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[1] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[2] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[3] = (unsigned char) val; len += 2;
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 4;
case ReadExceptionStatus:
case FetchCommEventCtr:
case FetchCommEventLog:
case ReportSlaveID:
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 0;
case ForceMultipleCoils:
case PresetMultipleRegs:
sscanf((char *) &telptr[len],"%02X",&val); data[0] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[1] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[2] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[3] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&byte_count); len += 2;
for(i=0; i<byte_count; i++)
{
sscanf((char *) &telptr[len],"%02X",&val); data[4+i] = (unsigned char) val; len += 2;
}
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 4+byte_count;
case ReadGeneralReference:
case WriteGeneralReference:
sscanf((char *) &telptr[len],"%02X",&byte_count); len += 2;
for(i=0; i<byte_count; i++)
{
sscanf((char *) &telptr[len],"%02X",&val); data[i] = (unsigned char) val; len += 2;
}
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
case MaskWrite4XRegisters:
sscanf((char *) &telptr[len],"%02X",&val); data[0] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[1] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[2] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[3] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[4] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[5] = (unsigned char) val; len += 2;
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 6;
case ReadWrite4XRegisters:
sscanf((char *) &telptr[len],"%02X",&val); data[0] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[1] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[2] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[3] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[4] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[5] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[6] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[7] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&byte_count); len += 2;
for(i=0; i<byte_count; i++)
{
sscanf((char *) &telptr[len],"%02X",&val); data[8+i] = (unsigned char) val; len += 2;
}
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 8+byte_count;
case ReadFifoQueue:
sscanf((char *) &telptr[len],"%02X",&val); data[0] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[1] = (unsigned char) val; len += 2;
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 2;
default:
return MODBUS_ERROR;
}
}
else if(mode == MODBUS_RTU)
{
ret = tty->select(timeout);
if(ret == 0) return MODBUS_ERROR;
if(tty->readBlock(tel, 2) <= 0) return MODBUS_ERROR;
*slave = tel[len++];
*function = tel[len++];
ret = tty->select(timeout);
if(ret == 0) return MODBUS_ERROR;
switch(*function)
{
case ReadCoilStatus:
case ReadInputStatus:
case ReadHoldingRegisters:
case ReadInputRegisters:
case ForceSingleCoil:
case PresetSingleRegister:
if(tty->readBlock(data, 4+2) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,4+2); len += 4+2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 4;
case ReadExceptionStatus:
case FetchCommEventCtr:
case FetchCommEventLog:
case ReportSlaveID:
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 0;
case ForceMultipleCoils:
case PresetMultipleRegs:
if(tty->readBlock(data, 5) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,5); len += 5;
byte_count = data[4];
if(tty->readBlock(&data[4], byte_count+2) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count+2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 4+byte_count;
case ReadGeneralReference:
case WriteGeneralReference:
if(tty->readBlock(data, 1) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,1); len++;
byte_count = data[0];
if(tty->readBlock(data, byte_count+2) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count+2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
case MaskWrite4XRegisters:
if(tty->readBlock(data, 6+2) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,6+2); len += 6+2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 6;
case ReadWrite4XRegisters:
if(tty->readBlock(data, 9) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,9); len += 9;
byte_count = data[8];
if(tty->readBlock(&data[8], byte_count+2) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count+2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 8+byte_count;
case ReadFifoQueue:
if(tty->readBlock(data, 2+2) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,2+2); len += 2+2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 2;
default:
return MODBUS_ERROR;
}
}
}
else return MODBUS_ERROR;
return MODBUS_SUCCESS;
}
| void rlModbus::registerSerial | ( | rlSerial * | serial | ) |
Definition at line 591 of file rlmodbus.cpp.
| void rlModbus::registerSocket | ( | rlSocket * | socket | ) |
Definition at line 585 of file rlmodbus.cpp.
| int rlModbus::request | ( | int | slave, |
| int | function, | ||
| int | start_adr, | ||
| int | num_register | ||
| ) |
Definition at line 121 of file rlmodbus.cpp.
{
unsigned char data[4];
data[0] = (unsigned char) ( start_adr / 256 );
data[1] = (unsigned char) ( start_adr & 0x0ff );
data[2] = (unsigned char) ( num_register / 256 );
data[3] = (unsigned char) ( num_register & 0x0ff );
return write(slave, function, data, 4);
}
| int rlModbus::response | ( | int * | slave, |
| int * | function, | ||
| unsigned char * | data, | ||
| int | timeout = 1000 |
||
| ) |
Definition at line 132 of file rlmodbus.cpp.
{
unsigned char *telptr;
int ret,len,byte_count,idata,i,itel,val;
len = 0;
if(mode != MODBUS_ASCII && mode != MODBUS_RTU) return MODBUS_ERROR;
if(s != NULL)
{
if(s->isConnected() == 0) return MODBUS_ERROR;
if(mode == MODBUS_RTU)
{
if(s->read((char *) tel, 6, timeout) <= 0) return MODBUS_ERROR;
// bytes 0,1 Transaction ID faithfully copied from the request message
// bytes 2,3 Protocol number always zero
// byte 4 Response length (upper byte) Always zero
// byte 5 Response length (lower byte). Equal to the number of bytes which follow
// Here comes the normal Modus telegram
if(s->read((char *) tel, 2, timeout) <= 0) return MODBUS_ERROR;
*slave = tel[0];
*function = tel[1];
switch(*function)
{
case ReadCoilStatus:
case ReadInputStatus:
case ReadHoldingRegisters:
case ReadInputRegisters:
case FetchCommEventLog:
case ReportSlaveID:
case ReadGeneralReference:
case WriteGeneralReference:
case ReadWrite4XRegisters:
if(s->read((char *) tel, 1, timeout) <= 0) return MODBUS_ERROR;
byte_count = tel[0];
if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
return byte_count;
case ForceSingleCoil:
case PresetSingleRegister:
case FetchCommEventCtr:
case ForceMultipleCoils:
case PresetMultipleRegs:
byte_count = 4;
if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
return byte_count;
case ReadExceptionStatus:
byte_count = 1;
if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
return byte_count;
case MaskWrite4XRegisters:
byte_count = 6;
if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
return byte_count;
case ReadFifoQueue:
if(s->read((char *) tel, 2, timeout) <= 0) return MODBUS_ERROR;
byte_count = tel[0]*256 + tel[1];
if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
return byte_count;
default:
return MODBUS_ERROR;
}
}
}
else if(tty != NULL)
{
if(mode == MODBUS_ASCII)
{
//printf("modbus ascii\n");
for(i=0; i<maxtel; i++)
{
ret = tty->select(timeout);
if(ret == 0) return MODBUS_ERROR;
//printf("readChar\n");
itel = tty->readChar();
if(itel < 0) return MODBUS_ERROR;
tel[i] = (unsigned char) itel;
if(tel[i] == 0x0d && delimitor != 0x0a) break;
if(tel[i] == 0x0a) break;
}
tel[i] = '\0';
telptr = (unsigned char *) strchr((const char *) tel,':');
if(telptr == NULL) return MODBUS_ERROR;
len++;
sscanf((char *) &telptr[len],"%02X",slave); len += 2;
sscanf((char *) &telptr[len],"%02X",function); len += 2;
switch(*function)
{
case ReadCoilStatus:
case ReadInputStatus:
case ReadHoldingRegisters:
case ReadInputRegisters:
case FetchCommEventLog:
case ReportSlaveID:
case ReadGeneralReference:
case WriteGeneralReference:
case ReadWrite4XRegisters:
sscanf((char *) &telptr[len],"%02X",&byte_count); len += 2;
for(idata=0; idata<byte_count; idata++)
{
sscanf((const char *) &telptr[len], "%02X", &val); len += 2;
data[idata] = val;
}
data[idata] = 0x0ff; // terminator, this data can't come over modbus
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
case ForceSingleCoil:
case PresetSingleRegister:
case FetchCommEventCtr:
case ForceMultipleCoils:
case PresetMultipleRegs:
byte_count = 8;
for(idata=0; idata<(byte_count/2); idata++)
{
data[idata] = buf2int_ascii(&telptr[len]); len += 2;
}
data[idata] = 0x0ff; // terminator, this data can't come over modbus
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
case ReadExceptionStatus:
byte_count = 2;
for(idata=0; idata<(byte_count/2); idata++)
{
data[idata] = buf2int_ascii(&telptr[len]); len += 2;
}
data[idata] = 0x0ff; // terminator, this data can't come over modbus
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
case MaskWrite4XRegisters:
byte_count = 12;
for(idata=0; idata<(byte_count/2); idata++)
{
data[idata] = buf2int_ascii(&telptr[len]); len += 2;
}
data[idata] = 0x0ff; // terminator, this data can't come over modbus
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
case ReadFifoQueue:
sscanf((char *) &telptr[len],"%04X",&byte_count); len += 4;
for(idata=0; idata<(byte_count/2); idata++)
{
data[idata] = buf2int_ascii(&telptr[len]); len += 2;
}
data[idata] = 0x0ff; // terminator, this data can't come over modbus
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
break;
default:
return MODBUS_ERROR;
}
}
else if(mode == MODBUS_RTU)
{
ret = tty->select(timeout);
if(ret == 0) return MODBUS_ERROR;
if(tty->readBlock(tel, 2) <= 0) return MODBUS_ERROR;
*slave = tel[len++];
*function = tel[len++];
switch(*function)
{
case ReadCoilStatus:
case ReadInputStatus:
case ReadHoldingRegisters:
case ReadInputRegisters:
case FetchCommEventLog:
case ReportSlaveID:
case ReadGeneralReference:
case WriteGeneralReference:
case ReadWrite4XRegisters:
if(tty->select(timeout) == 0) return MODBUS_ERROR;
if(tty->readBlock(&tel[len], 1) <= 0) return MODBUS_ERROR;
byte_count = tel[len++];
if(tty->select(timeout) == 0) return MODBUS_ERROR;
if(tty->readBlock(data, byte_count+2) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count + 2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
case ForceSingleCoil:
case PresetSingleRegister:
case FetchCommEventCtr:
case ForceMultipleCoils:
case PresetMultipleRegs:
byte_count = 4;
if(tty->select(timeout) == 0) return MODBUS_ERROR;
if(tty->readBlock(data, byte_count+2) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count + 2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
case ReadExceptionStatus:
byte_count = 1;
if(tty->select(timeout) == 0) return MODBUS_ERROR;
if(tty->readBlock(data, byte_count+2) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count + 2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
case MaskWrite4XRegisters:
byte_count = 6;
if(tty->select(timeout) == 0) return MODBUS_ERROR;
if(tty->readBlock(data, byte_count+2) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count + 2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
case ReadFifoQueue:
if(tty->select(timeout) == 0) return MODBUS_ERROR;
if(tty->readBlock(&tel[len], 2) <= 0) return MODBUS_ERROR;
byte_count = tel[len]*256 + tel[len+1]; len += 2;
if(tty->select(timeout) == 0) return MODBUS_ERROR;
if(tty->readBlock(data, byte_count+2) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count + 2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
default:
return MODBUS_ERROR;
}
}
}
else return MODBUS_ERROR;
return MODBUS_SUCCESS;
}
| int rlModbus::write | ( | int | slave, |
| int | function, | ||
| const unsigned char * | data, | ||
| int | len, | ||
| int * | transactionID = NULL |
||
| ) |
Definition at line 54 of file rlmodbus.cpp.
{
int len,i;
if(slave < 0 || slave > 255) return MODBUS_ERROR;
len = 0;
if(mode == MODBUS_ASCII)
{
tel[len++] = ':';
sprintf((char *) &tel[len], "%02X", slave); len += 2;
sprintf((char *) &tel[len], "%02X", function); len += 2;
for(i=0; i<datalen; i++)
{
sprintf((char *) &tel[len], "%02X",(int) data[i]); len += 2;
if((len+4) > maxtel) return MODBUS_ERROR;
}
insertLRC(len); len += 2;
tel[len++] = 0x0d;
if(delimitor == 0x0a) tel[len++] = 0x0a;
}
else if(mode == MODBUS_RTU)
{
if(s != NULL)
{
if(transactionID == NULL)
{
tel[len++] = 0; // bytes 0,1 Transaction ID. Not important. Usually zero when making a request, the server will copy them faithfully into the response.
tel[len++] = 0;
}
else
{
tel[len++] = ((*transactionID) & 0xFF00) / 256; // bytes 0,1 Transaction ID.
tel[len++] = (*transactionID) & 0xFF;
}
tel[len++] = 0; // bytes 2,3 Protocol number. Must be zero.
tel[len++] = 0;
tel[len++] = 0; // byte 4 Length (upper byte). Since all requests will be less than 256 bytes in length (!), this will always be zero.
tel[len++] = 2+datalen; // byte 5 Length (lower byte). Equal to the number of bytes which follow
}
tel[len++] = (unsigned char) slave;
tel[len++] = (unsigned char) function;
for(i=0; i<datalen; i++)
{
tel[len++] = data[i];
if((len+2) > maxtel) return MODBUS_ERROR;
}
insertCRC(len); len += 2;
}
else return MODBUS_ERROR;
if(s != NULL)
{
if(s->isConnected() == 0)
{
if(autoreconnectSocket) s->connect();
if(s->isConnected() == 0) return MODBUS_ERROR;
}
if(s->write(tel,len-2) < 0) return MODBUS_ERROR; // don't send LRC or CRC
}
else if(tty != NULL)
{
if(tty->writeBlock(tel,len) < 0) return MODBUS_ERROR;
}
else return MODBUS_ERROR;
return MODBUS_SUCCESS;
}
Definition at line 72 of file rlmodbus.h.
char rlModbus::delimitor [private] |
Definition at line 88 of file rlmodbus.h.
long rlModbus::maxtel [private] |
Definition at line 86 of file rlmodbus.h.
int rlModbus::mode [private] |
Definition at line 87 of file rlmodbus.h.
rlSocket* rlModbus::s [private] |
Definition at line 83 of file rlmodbus.h.
unsigned char* rlModbus::tel [private] |
Definition at line 85 of file rlmodbus.h.
rlSerial* rlModbus::tty [private] |
Definition at line 84 of file rlmodbus.h.
1.7.5.1