133 #define MAX_BUFFER 64
143 HardwareSerial *port;
150 uint8_t u8BufferSize;
153 uint16_t u16InCnt, u16OutCnt, u16errCnt;
155 uint32_t u32time, u32timeOut;
158 void init(uint8_t u8id, uint8_t u8serno, uint8_t u8txenpin);
160 int8_t getRxBuffer();
161 uint16_t calcCRC(uint8_t u8length);
162 uint8_t validateAnswer();
163 uint8_t validateRequest();
166 int8_t process_FC1( uint16_t *regs, uint8_t u8size );
167 int8_t process_FC3( uint16_t *regs, uint8_t u8size );
168 int8_t process_FC5( uint16_t *regs, uint8_t u8size );
169 int8_t process_FC6( uint16_t *regs, uint8_t u8size );
170 int8_t process_FC15( uint16_t *regs, uint8_t u8size );
171 int8_t process_FC16( uint16_t *regs, uint8_t u8size );
172 void buildException( uint8_t u8exception );
176 Modbus(uint8_t u8id, uint8_t u8serno);
177 Modbus(uint8_t u8id, uint8_t u8serno, uint8_t u8txenpin);
178 void begin(
long u32speed);
185 int8_t
poll( uint16_t *regs, uint8_t u8size );
192 void setID( uint8_t u8id );
219 init(u8id, u8serno, 0);
235 init(u8id, u8serno, u8txenpin);
277 port->begin(u32speed);
280 pinMode(u8txenpin, OUTPUT);
281 digitalWrite(u8txenpin, LOW);
285 u8lastRec = u8BufferSize = 0;
286 u16InCnt = u16OutCnt = u16errCnt = 0;
311 if (( u8id != 0) && (u8id <= 247)) {
339 this->u16timeOut = u16timeOut;
351 return (millis() > u32timeOut);
426 uint8_t u8regsno, u8bytesno;
427 if (u8id!=0)
return -2;
430 if ((telegram.
u8id==0) || (telegram.
u8id>247))
return -3;
435 au8Buffer[
ID ] = telegram.
u8id;
440 switch( telegram.
u8fct ) {
450 au8Buffer[
NB_HI ] = ((au16regs[0] > 0) ? 0xff : 0);
451 au8Buffer[
NB_LO ] = 0;
455 au8Buffer[
NB_HI ] = highByte(au16regs[0]);
456 au8Buffer[
NB_LO ] = lowByte(au16regs[0]);
461 u8bytesno = u8regsno * 2;
469 au8Buffer[
NB_LO+1 ] = u8bytesno;
472 u8regsno = u8bytesno = 0;
473 for (uint16_t i = 0; i < telegram.
u16CoilsNo; i++) {
485 for (uint16_t i=0; i< telegram.
u16CoilsNo; i++) {
486 au8Buffer[ u8BufferSize ] = highByte( au16regs[ i ] );
488 au8Buffer[ u8BufferSize ] = lowByte( au16regs[ i ] );
515 uint8_t u8current = port->available();
517 if (millis() > u32timeOut) {
524 if (u8current == 0)
return 0;
527 if (u8current != u8lastRec) {
528 u8lastRec = u8current;
529 u32time = millis() +
T35;
532 if (millis() < u32time)
return 0;
536 int8_t i8state = getRxBuffer();
544 uint8_t u8exception = validateAnswer();
545 if (u8exception != 0) {
551 switch( au8Buffer[
FUNC ] ) {
594 uint8_t u8current = port->available();
595 if (u8current == 0)
return 0;
598 if (u8current != u8lastRec) {
599 u8lastRec = u8current;
600 u32time = millis() +
T35;
603 if (millis() < u32time)
return 0;
606 int8_t i8state = getRxBuffer();
607 u8lastError = i8state;
608 if (i8state < 7)
return i8state;
611 if (au8Buffer[
ID ] != u8id)
return 0;
614 uint8_t u8exception = validateRequest();
615 if (u8exception > 0) {
617 buildException( u8exception );
620 u8lastError = u8exception;
624 u32timeOut = millis() + long(u16timeOut);
628 switch( au8Buffer[
FUNC ] ) {
631 return process_FC1( regs, u8size );
635 return process_FC3( regs, u8size );
638 return process_FC5( regs, u8size );
641 return process_FC6( regs, u8size );
644 return process_FC15( regs, u8size );
647 return process_FC16( regs, u8size );
657 void Modbus::init(uint8_t u8id, uint8_t u8serno, uint8_t u8txenpin) {
659 this->u8serno = (u8serno > 3) ? 0 : u8serno;
660 this->u8txenpin = u8txenpin;
661 this->u16timeOut = 1000;
671 int8_t Modbus::getRxBuffer() {
672 boolean bBuffOverflow =
false;
674 if (u8txenpin > 1) digitalWrite( u8txenpin, LOW );
677 while ( port->available() ) {
678 au8Buffer[ u8BufferSize ] = port->read();
681 if (u8BufferSize >=
MAX_BUFFER) bBuffOverflow =
true;
704 void Modbus::sendTxBuffer() {
708 uint16_t u16crc = calcCRC( u8BufferSize );
709 au8Buffer[ u8BufferSize ] = u16crc >> 8;
711 au8Buffer[ u8BufferSize ] = u16crc & 0x00ff;
719 UCSR1A=UCSR1A |(1 << TXC1);
725 UCSR2A=UCSR2A |(1 << TXC2);
731 UCSR3A=UCSR3A |(1 << TXC3);
736 UCSR0A=UCSR0A |(1 << TXC0);
739 digitalWrite( u8txenpin, HIGH );
743 port->write( au8Buffer, u8BufferSize );
750 while (!(UCSR1A & (1 << TXC1)));
756 while (!(UCSR2A & (1 << TXC2)));
762 while (!(UCSR3A & (1 << TXC3)));
767 while (!(UCSR0A & (1 << TXC0)));
772 digitalWrite( u8txenpin, LOW );
778 u32timeOut = millis() + (
unsigned long) u16timeOut;
791 uint16_t Modbus::calcCRC(uint8_t u8length) {
792 unsigned int temp, temp2, flag;
794 for (
unsigned char i = 0; i < u8length; i++) {
795 temp = temp ^ au8Buffer[i];
796 for (
unsigned char j = 1; j <= 8; j++) {
797 flag = temp & 0x0001;
805 temp = (temp << 8) | temp2;
819 uint8_t Modbus::validateRequest() {
822 ((au8Buffer[u8BufferSize - 2] << 8)
823 | au8Buffer[u8BufferSize - 1]);
824 if ( calcCRC( u8BufferSize-2 ) != u16MsgCRC ) {
830 boolean isSupported =
false;
843 uint16_t u16regs = 0;
845 switch ( au8Buffer[
FUNC ] ) {
849 u16regs = word( au8Buffer[
ADD_HI ], au8Buffer[
ADD_LO ]) / 16;
850 u16regs += word( au8Buffer[
NB_HI ], au8Buffer[
NB_LO ]) /16;
851 u8regs = (uint8_t) u16regs;
855 u16regs = word( au8Buffer[
ADD_HI ], au8Buffer[
ADD_LO ]) / 16;
856 u8regs = (uint8_t) u16regs;
860 u16regs = word( au8Buffer[
ADD_HI ], au8Buffer[
ADD_LO ]);
861 u8regs = (uint8_t) u16regs;
867 u16regs = word( au8Buffer[
ADD_HI ], au8Buffer[
ADD_LO ]);
868 u16regs += word( au8Buffer[
NB_HI ], au8Buffer[
NB_LO ]);
869 u8regs = (uint8_t) u16regs;
883 uint8_t Modbus::validateAnswer() {
886 ((au8Buffer[u8BufferSize - 2] << 8)
887 | au8Buffer[u8BufferSize - 1]);
888 if ( calcCRC( u8BufferSize-2 ) != u16MsgCRC ) {
894 if ((au8Buffer[ FUNC ] & 0x80) != 0) {
900 boolean isSupported =
false;
921 void Modbus::buildException( uint8_t u8exception ) {
922 uint8_t u8func = au8Buffer[
FUNC ];
924 au8Buffer[
ID ] = u8id;
925 au8Buffer[
FUNC ] = u8func + 0x80;
926 au8Buffer[ 2 ] = u8exception;
936 void Modbus::get_FC1() {
954 void Modbus::get_FC3() {
958 for (i=0; i< au8Buffer[ 2 ] /2; i++) {
959 au16regs[ i ] = word(
961 au8Buffer[ u8byte +1 ]);
974 int8_t Modbus::process_FC1( uint16_t *regs, uint8_t u8size ) {
975 uint8_t u8currentRegister, u8currentBit, u8bytesno, u8bitsno;
976 uint8_t u8CopyBufferSize;
977 uint16_t u16currentCoil, u16coil;
980 uint16_t u16StartCoil = word( au8Buffer[
ADD_HI ], au8Buffer[
ADD_LO ] );
981 uint16_t u16Coilno = word( au8Buffer[
NB_HI ], au8Buffer[
NB_LO ] );
984 u8bytesno = (uint8_t) (u16Coilno / 8);
985 if (u16Coilno % 8 != 0) u8bytesno ++;
986 au8Buffer[
ADD_HI ] = u8bytesno;
992 for (u16currentCoil = 0; u16currentCoil < u16Coilno; u16currentCoil++) {
993 u16coil = u16StartCoil + u16currentCoil;
994 u8currentRegister = (uint8_t) (u16coil / 16);
995 u8currentBit = (uint8_t) (u16coil % 16);
998 au8Buffer[ u8BufferSize ],
1000 bitRead( regs[ u8currentRegister ], u8currentBit ) );
1010 if (u16Coilno % 8 != 0) u8BufferSize ++;
1011 u8CopyBufferSize = u8BufferSize +2;
1013 return u8CopyBufferSize;
1024 int8_t Modbus::process_FC3( uint16_t *regs, uint8_t u8size ) {
1026 uint8_t u8StartAdd = word( au8Buffer[
ADD_HI ], au8Buffer[
ADD_LO ] );
1027 uint8_t u8regsno = word( au8Buffer[
NB_HI ], au8Buffer[
NB_LO ] );
1028 uint8_t u8CopyBufferSize;
1031 au8Buffer[ 2 ] = u8regsno * 2;
1034 for (i = u8StartAdd; i < u8StartAdd + u8regsno; i++) {
1035 au8Buffer[ u8BufferSize ] = highByte(regs[i]);
1037 au8Buffer[ u8BufferSize ] = lowByte(regs[i]);
1040 u8CopyBufferSize = u8BufferSize +2;
1043 return u8CopyBufferSize;
1054 int8_t Modbus::process_FC5( uint16_t *regs, uint8_t u8size ) {
1055 uint8_t u8currentRegister, u8currentBit;
1056 uint8_t u8CopyBufferSize;
1057 uint16_t u16coil = word( au8Buffer[
ADD_HI ], au8Buffer[
ADD_LO ] );
1060 u8currentRegister = (uint8_t) (u16coil / 16);
1061 u8currentBit = (uint8_t) (u16coil % 16);
1065 regs[ u8currentRegister ],
1067 au8Buffer[
NB_HI ] == 0xff );
1072 u8CopyBufferSize = u8BufferSize +2;
1075 return u8CopyBufferSize;
1086 int8_t Modbus::process_FC6( uint16_t *regs, uint8_t u8size ) {
1088 uint8_t u8add = word( au8Buffer[
ADD_HI ], au8Buffer[
ADD_LO ] );
1089 uint8_t u8CopyBufferSize;
1090 uint16_t u16val = word( au8Buffer[
NB_HI ], au8Buffer[
NB_LO ] );
1092 regs[ u8add ] = u16val;
1097 u8CopyBufferSize = u8BufferSize +2;
1100 return u8CopyBufferSize;
1111 int8_t Modbus::process_FC15( uint16_t *regs, uint8_t u8size ) {
1112 uint8_t u8currentRegister, u8currentBit, u8frameByte, u8bitsno;
1113 uint8_t u8CopyBufferSize;
1114 uint16_t u16currentCoil, u16coil;
1118 uint16_t u16StartCoil = word( au8Buffer[
ADD_HI ], au8Buffer[
ADD_LO ] );
1119 uint16_t u16Coilno = word( au8Buffer[
NB_HI ], au8Buffer[
NB_LO ] );
1125 for (u16currentCoil = 0; u16currentCoil < u16Coilno; u16currentCoil++) {
1127 u16coil = u16StartCoil + u16currentCoil;
1128 u8currentRegister = (uint8_t) (u16coil / 16);
1129 u8currentBit = (uint8_t) (u16coil % 16);
1132 au8Buffer[ u8frameByte ],
1136 regs[ u8currentRegister ],
1151 u8CopyBufferSize = u8BufferSize +2;
1153 return u8CopyBufferSize;
1164 int8_t Modbus::process_FC16( uint16_t *regs, uint8_t u8size ) {
1165 uint8_t u8func = au8Buffer[
FUNC ];
1166 uint8_t u8StartAdd = au8Buffer[
ADD_HI ] << 8 | au8Buffer[
ADD_LO ];
1167 uint8_t u8regsno = au8Buffer[
NB_HI ] << 8 | au8Buffer[
NB_LO ];
1168 uint8_t u8CopyBufferSize;
1173 au8Buffer[
NB_HI ] = 0;
1174 au8Buffer[
NB_LO ] = u8regsno;
1178 for (i = 0; i < u8regsno; i++) {
1180 au8Buffer[ (
BYTE_CNT + 1) + i * 2 ],
1181 au8Buffer[ (
BYTE_CNT + 2) + i * 2 ]);
1183 regs[ u8StartAdd + i ] = temp;
1185 u8CopyBufferSize = u8BufferSize +2;
1188 return u8CopyBufferSize;