MODbust TCP master

I have tried to implemented MODbust master on TCP on RCM 6700.
Havig really hard time with “int MBM_Send_ADU ( *ADUaddress, ADUlength );”
Any samples?

The following code extract should give you a start:


/*** BeginHeader MBM_Send_ADU_TCP */
int MBM_Send_ADU_TCP(uint32_t IPAddress, char *Packet, int ByteCount);

#define MMTCP_STATE_WAIT		0
#define MMTCP_STATE_STARTED		1
#define MMTCP_STATE_REMAINDER	2
#define MMTCP_STATE_DONE		3
#define MMTCP_STATE_ERROR		4

/*** EndHeader */
_modbus_dbg
int MBM_Send_ADU_TCP(uint32_t IPAddress, char *Packet, int ByteCount)
{
static tcp_Socket MMSocket;
static far char MMTCPBuffer[1024];
int i;
uint32_t ulTemp;
int16_t  iTemp;
int iExpected;
int iMMTState;
int bytes_read;
char cDiscard;
int iResponse;

iResponse = MB_SUCCESS;
#if MODBUS_PRINT
if(cModbusPrintEnabled)
	{
	printf("Tx TCP:");
	for(i=0; i 2)
	        break;
       	}

    if(0 != sock_established(&MMSocket))
        {
        sock_flushnext(&MMSocket);
        iTemp = sock_write(&MMSocket, Packet, ByteCount);

		iExpected = MBM_HowMany(&Packet[6]) - 2; // Subtract CRC bytes
		ulTemp = LocalTimeCorrected();           // Record when we sent packet
		iMMTState = MMTCP_STATE_WAIT;
		do
			{
            if((LocalTimeCorrected() - ulTemp) > 2) // Taking too long...
                iMMTState = MMTCP_STATE_ERROR;

			switch(iMMTState)
				{
				case MMTCP_STATE_WAIT:
                    if(sock_bytesready(&MMSocket) >= 8 ) // Got the minimum expected data so goto next stage
	                    iMMTState = MMTCP_STATE_STARTED;
        			break;

				case MMTCP_STATE_STARTED:
                    sock_read(&MMSocket, mbADU, 8 ); // Know this will not block as we checked in previous state...
                    if(mbADU[7] >= 0x80)            // Not a good response...
                    	iExpected = 1;              // Just the error code to get
                    else
                    	iExpected -= 2;             // Have address and function code...

                    iMMTState = MMTCP_STATE_REMAINDER;
					break;

				case MMTCP_STATE_REMAINDER:
                    if(sock_bytesready(&MMSocket) >= iExpected)
			            {
						sock_read(&MMSocket, &mbADU[8], iExpected);
						sock_close(&MMSocket);
						while(sock_bytesready(&MMSocket) != -1) // Flush any unread data just in case
							{
							sock_read(&MMSocket, &cDiscard, 1);
                            if((LocalTimeCorrected() - ulTemp) > 2) // Taking too long so...
                            	{
								sock_abort(&MMSocket);
 				               	break;
 				               	}
							}

	                    iMMTState = MMTCP_STATE_DONE;
	                    }
					break;

				case MMTCP_STATE_ERROR:
					sock_abort(&MMSocket);
                    return(MBM_PACKET_ERROR);

					break;
				}
          	} while(iMMTState != MMTCP_STATE_DONE);

        // receive the response into the same buffer used for the transmit data
		return(MB_SUCCESS);
        }
    else
		sock_abort(&MMSocket);
	}

return(MBM_PACKET_ERROR);
}

The LocalTimeCorrected() function is my own time function which takes into account the offset calculated via SNTP, you can just use the normal SEC_TIMER.

This code uses a fixed small 1024 byte buffer for the TCP socket for efficiency.

Regards,
Peter

2 Likes

Peter, you can use bbcode markup in your posts here. Wrap code in opening/closing “code” blocks, using square brackets. Not sure if I can embed it in my comment or not…

code goes here

Thanks for the tip Tom, done…

Thank you Peter, it’ll help me alot.
Regards,
Konstantin.