Lydia - Printhead
Loading...
Searching...
No Matches
Modbus Buffer Management

Functions

void Modbus::buildException (uint8_t u8exception)
 This method builds an exception message.
 
uint16_t Modbus::calcCRC (uint8_t u8length)
 This method calculates CRC.
 
uint16_t Modbus::getErrCnt ()
 error counter
 
uint16_t Modbus::getInCnt ()
 number of incoming messages
 
uint8_t Modbus::getLastError ()
 get last error message
 
uint16_t Modbus::getOutCnt ()
 number of outcoming messages
 
int8_t Modbus::getRxBuffer ()
 This method moves Serial buffer data to the Modbus au8Buffer.
 
uint8_t Modbus::getState ()
 
void Modbus::sendTxBuffer ()
 This method transmits au8Buffer to Serial line. Only if u8txenpin != 0, there is a flow handling in order to keep the RS485 transceiver in output state as long as the message is being sent. This is done with UCSRxA register. The CRC is appended to the buffer before starting to send it.
 
uint8_t Modbus::validateAnswer ()
 This method validates master incoming messages.
 
uint8_t Modbus::validateRequest ()
 This method validates slave incoming messages.
 

Detailed Description

Function Documentation

◆ buildException()

void Modbus::buildException ( uint8_t u8exception)
private

This method builds an exception message.

Definition at line 1244 of file ModbusRtu.h.

1245{
1246 uint8_t u8func = au8Buffer[FUNC]; // get the original FUNC code
1247
1248 au8Buffer[ID] = u8id;
1249 au8Buffer[FUNC] = u8func + 0x80;
1252}
@ EXCEPTION_SIZE
Definition ModbusRtu.h:82
@ ID
ID field.
Definition ModbusRtu.h:93
@ FUNC
Function code position.
Definition ModbusRtu.h:94
uint8_t u8id
0=master, 1..247=slave number
Definition ModbusRtu.h:157
uint8_t au8Buffer[MAX_BUFFER]
Definition ModbusRtu.h:162
uint8_t u8BufferSize
Definition ModbusRtu.h:163
Definition xtimer.h:21

◆ calcCRC()

uint16_t Modbus::calcCRC ( uint8_t u8length)
private

This method calculates CRC.

Returns
uint16_t calculated CRC value for the message

Definition at line 1096 of file ModbusRtu.h.

1097{
1098 unsigned int temp, temp2, flag;
1099 temp = 0xFFFF;
1100 for (unsigned char i = 0; i < u8length; i++)
1101 {
1102 temp = temp ^ au8Buffer[i];
1103 // Serial.println(au8Buffer[i], DEC);
1104 for (unsigned char j = 1; j <= 8; j++)
1105 {
1106 flag = temp & 0x0001;
1107 temp >>= 1;
1108 if (flag)
1109 temp ^= 0xA001;
1110 }
1111 }
1112 // Reverse byte order.
1113 temp2 = temp >> 8;
1114 temp = (temp << 8) | temp2;
1115 temp &= 0xFFFF;
1116 // the returned value is already swapped
1117 // crcLo byte is first & crcHi byte is last
1118 return temp;
1119}

◆ getErrCnt()

uint16_t Modbus::getErrCnt ( )

error counter

Get errors counter value This can be useful to diagnose communication.

Returns
errors counter

Definition at line 545 of file ModbusRtu.h.

546{
547 return u16errCnt;
548}
uint16_t u16errCnt
Definition ModbusRtu.h:166

◆ getInCnt()

uint16_t Modbus::getInCnt ( )

number of incoming messages

Get input messages counter value This can be useful to diagnose communication.

Returns
input messages counter

Definition at line 519 of file ModbusRtu.h.

520{
521 return u16InCnt;
522}
uint16_t u16InCnt
Definition ModbusRtu.h:166

◆ getLastError()

uint8_t Modbus::getLastError ( )

get last error message

Get the last error in the protocol processor

@returnreturn NO_REPLY = 255 Time-out

Returns
EXC_FUNC_CODE = 1 Function code not available
EXC_ADDR_RANGE = 2 Address beyond available space for Modbus registers
EXC_REGS_QUANT = 3 Coils or registers number beyond the available space

Definition at line 575 of file ModbusRtu.h.

576{
577 return u8lastError;
578}
uint8_t u8lastError
Definition ModbusRtu.h:161

◆ getOutCnt()

uint16_t Modbus::getOutCnt ( )

number of outcoming messages

Get transmitted messages counter value This can be useful to diagnose communication.

Returns
transmitted messages counter

Definition at line 532 of file ModbusRtu.h.

533{
534 return u16OutCnt;
535}
uint16_t u16OutCnt
Definition ModbusRtu.h:166

◆ getRxBuffer()

int8_t Modbus::getRxBuffer ( )
private

This method moves Serial buffer data to the Modbus au8Buffer.

Returns
buffer size if OK, ERR_BUFF_OVERFLOW if u8BufferSize >= MAX_BUFFER

Definition at line 905 of file ModbusRtu.h.

906{
907 boolean bBuffOverflow = false;
908
909 if (u8txenpin > 1)
910 {
913 // digitalWrite( u8txenpin, LOW );
914 }
915
916 u8BufferSize = 0;
917 if (u8serno < 4)
918 while (port->available())
919 {
920 au8Buffer[u8BufferSize] = port->read();
922 u8BufferSize++;
923
925 bBuffOverflow = true;
926 }
927 else
928 while (softPort->available())
929 {
931 u8BufferSize++;
932
934 bBuffOverflow = true;
935 }
936 u16InCnt++;
937
938 if (bBuffOverflow)
939 {
940 Log.verboseln("buffer overflow: %d", u8BufferSize);
941 u16errCnt++;
942 return ERR_BUFF_OVERFLOW;
943 }
944 //Log.verboseln("getRX-Buffer : %d",u8BufferSize);
945 //printHex(rxBuffer, u8BufferSize);
947 return u8BufferSize;
948}
#define MAX_BUFFER
maximum size for the communication buffer in bytes
Definition ModbusRtu.h:57
@ ERR_BUFF_OVERFLOW
Definition ModbusRtu.h:121
#define RS485_CLEAR_DE
Definition ModbusRtu.h:51
#define RS485_CLEAR_RE
Definition ModbusRtu.h:52
HardwareSerial * port
Pointer to Serial class object.
Definition ModbusRtu.h:155
uint8_t rxSize
Definition ModbusRtu.h:216
uint8_t rxBuffer[MAX_BUFFER]
Definition ModbusRtu.h:217
uint8_t u8serno
serial port: 0-Serial, 1..3-Serial1..Serial3; 4: use software serial
Definition ModbusRtu.h:158
uint8_t u8txenpin
flow control pin: 0=USB or RS-232 mode, >0=RS-485 mode
Definition ModbusRtu.h:159
SoftwareSerial * softPort
Pointer to SoftwareSerial class object.
Definition ModbusRtu.h:156

◆ getState()

uint8_t Modbus::getState ( )

Get modbus master state

Returns
= 0 IDLE, = 1 WAITING FOR ANSWER

Definition at line 561 of file ModbusRtu.h.

562{
563 return u8state;
564}
uint8_t u8state
Definition ModbusRtu.h:160

◆ sendTxBuffer()

void Modbus::sendTxBuffer ( )
private

This method transmits au8Buffer to Serial line. Only if u8txenpin != 0, there is a flow handling in order to keep the RS485 transceiver in output state as long as the message is being sent. This is done with UCSRxA register. The CRC is appended to the buffer before starting to send it.

Parameters
nothing
Returns
nothing

Definition at line 962 of file ModbusRtu.h.

963{
964 uint8_t i = 0;
965
966 // append CRC to message
968/*
969 Serial.print("---- calc CRC : HEX : ");
970 Serial.print(u16crc, DEC);
971 Serial.print(" - HEX : ");
972 Serial.print(u16crc, HEX);
973 Serial.print(" - ");
974 Serial.print(u8BufferSize);
975 Serial.print("\n");
976 */
977
979 u8BufferSize++;
980 au8Buffer[u8BufferSize] = u16crc & 0x00ff;
981 u8BufferSize++;
982
983 if (debugSend)
984 {
985 Serial.print("Send Hex : \t");
986 for (int i = 0; i < 8; i++)
987 {
988 Serial.print(au8Buffer[i], HEX);
989 Serial.print(" : ");
990 }
991 Serial.println("--------------- \n");
992 }
993
994 // set RS485 transceiver to transmit mode
995 if (u8txenpin > 1)
996 {
997 switch (u8serno)
998 {
999#if defined(UBRR1H)
1000 case 1:
1001 UCSR1A = UCSR1A | (1 << TXC1);
1002 break;
1003#endif
1004
1005#if defined(UBRR2H)
1006 case 2:
1007 UCSR2A = UCSR2A | (1 << TXC2);
1008 break;
1009#endif
1010
1011#if defined(UBRR3H)
1012 case 3:
1013 UCSR3A = UCSR3A | (1 << TXC3);
1014 break;
1015#endif
1016 case 0:
1017 default:
1018 UCSR0A = UCSR0A | (1 << TXC0);
1019 break;
1020 }
1023 // digitalWrite( u8txenpin, HIGH );
1024 }
1025
1026 // transfer buffer to serial line
1027 if (u8serno < 4)
1028 {
1029 port->write(au8Buffer, u8BufferSize);
1030 }
1031 else
1032 {
1034 }
1035 // keep RS485 transceiver in transmit mode as long as sending
1036 if (u8txenpin > 1)
1037 {
1038 switch (u8serno)
1039 {
1040#if defined(UBRR1H)
1041 case 1:
1042 while (!(UCSR1A & (1 << TXC1)))
1043 ;
1044 break;
1045#endif
1046
1047#if defined(UBRR2H)
1048 case 2:
1049 while (!(UCSR2A & (1 << TXC2)))
1050 ;
1051 break;
1052#endif
1053
1054#if defined(UBRR3H)
1055 case 3:
1056 while (!(UCSR3A & (1 << TXC3)))
1057 ;
1058 break;
1059#endif
1060 case 0:
1061 default:
1062 while (!(UCSR0A & (1 << TXC0)))
1063 ;
1064 break;
1065 }
1066 // return RS485 transceiver to receive mode
1069 // digitalWrite( u8txenpin, LOW );
1070 }
1071 if (u8serno < 4)
1072 while (port->read() >= 0)
1073 ;
1074 else
1075 while (softPort->read() >= 0)
1076 ;
1077
1078 u8BufferSize = 0;
1079
1080 // set time-out for master
1081 u32timeOut = millis() + (unsigned long)u16timeOut;
1082
1083 // increase message counter
1084 u16OutCnt++;
1085
1087}
#define RS485_SET_RE
Definition ModbusRtu.h:54
#define RS485_SET_DE
Definition ModbusRtu.h:53
bool debugSend
Definition ModbusRtu.h:214
modbus_t * currentQuery
Definition ModbusRtu.h:178
uint32_t u32timeOut
Definition ModbusRtu.h:168
uint16_t u16timeOut
Definition ModbusRtu.h:167
uint16_t calcCRC(uint8_t u8length)
This method calculates CRC.
Definition ModbusRtu.h:1096
uint8_t flags
Definition ModbusRtu.h:74

◆ validateAnswer()

uint8_t Modbus::validateAnswer ( )
private

This method validates master incoming messages.

Returns
0 if OK, EXCEPTION if anything fails

Definition at line 1201 of file ModbusRtu.h.

1202{
1203 // check message crc vs calculated crc
1205 ((au8Buffer[u8BufferSize - 2] << 8) | au8Buffer[u8BufferSize - 1]); // combine the crc Low & High bytes
1206 if (calcCRC(u8BufferSize - 2) != u16MsgCRC)
1207 {
1208 u16errCnt++;
1209 return NO_REPLY;
1210 }
1211
1212 // check exception
1213 if ((au8Buffer[FUNC] & 0x80) != 0)
1214 {
1215 u16errCnt++;
1216 return ERR_EXCEPTION;
1217 }
1218
1219 // check fct code
1220 boolean isSupported = false;
1221 for (uint8_t i = 0; i < sizeof(fctsupported); i++)
1222 {
1223 if (fctsupported[i] == au8Buffer[FUNC])
1224 {
1225 isSupported = 1;
1226 break;
1227 }
1228 }
1229 if (!isSupported)
1230 {
1231 u16errCnt++;
1232 return EXC_FUNC_CODE;
1233 }
1234
1235 return 0; // OK, no exception code thrown
1236}
@ ERR_EXCEPTION
Definition ModbusRtu.h:123
@ NO_REPLY
Definition ModbusRtu.h:128
@ EXC_FUNC_CODE
Definition ModbusRtu.h:129
const unsigned char fctsupported[]
Definition ModbusRtu.h:135

◆ validateRequest()

uint8_t Modbus::validateRequest ( )
private

This method validates slave incoming messages.

Returns
0 if OK, EXCEPTION if anything fails

Definition at line 1128 of file ModbusRtu.h.

1129{
1130 // check message crc vs calculated crc
1132 ((au8Buffer[u8BufferSize - 2] << 8) | au8Buffer[u8BufferSize - 1]); // combine the crc Low & High bytes
1133 if (calcCRC(u8BufferSize - 2) != u16MsgCRC)
1134 {
1135 u16errCnt++;
1136 return NO_REPLY;
1137 }
1138
1139 // check fct code
1140 boolean isSupported = false;
1141 for (uint8_t i = 0; i < sizeof(fctsupported); i++)
1142 {
1143 if (fctsupported[i] == au8Buffer[FUNC])
1144 {
1145 isSupported = 1;
1146 break;
1147 }
1148 }
1149 if (!isSupported)
1150 {
1151 u16errCnt++;
1152 return EXC_FUNC_CODE;
1153 }
1154
1155 // check start address & nb range
1156 uint16_t u16regs = 0;
1158 switch (au8Buffer[FUNC])
1159 {
1160 case MB_FC_READ_COILS:
1166 if (u8regs > u8regsize)
1167 return EXC_ADDR_RANGE;
1168 break;
1169 case MB_FC_WRITE_COIL:
1172 if (u8regs > u8regsize)
1173 return EXC_ADDR_RANGE;
1174 break;
1178 if (u8regs > u8regsize)
1179 return EXC_ADDR_RANGE;
1180 break;
1187 if (u8regs > u8regsize)
1188 return EXC_ADDR_RANGE;
1189 break;
1190 }
1191 return 0; // OK, no exception code thrown
1192}
@ NB_LO
Number of coils or registers low byte.
Definition ModbusRtu.h:98
@ ADD_LO
Address low byte.
Definition ModbusRtu.h:96
@ NB_HI
Number of coils or registers high byte.
Definition ModbusRtu.h:97
@ ADD_HI
Address high byte.
Definition ModbusRtu.h:95
@ EXC_ADDR_RANGE
Definition ModbusRtu.h:130
uint8_t u8regsize
Definition ModbusRtu.h:169