136 lines
4.0 KiB
C
136 lines
4.0 KiB
C
/*---------------------------------------------------------------------------
|
|
M O D B U S T C P . C
|
|
|
|
Paul Barron, January 2008
|
|
|
|
RTU Modbus functions designed for use with the WEST4100 Temperature Controller.
|
|
If another modbus device is required at ANSTO sections of this code will need
|
|
to be modified.
|
|
|
|
MBAP: Modbus Application Protocol Header
|
|
PDU: Protocol Data Unit
|
|
|
|
Modbus TCP Packet Format
|
|
| MBAP | PDU |
|
|
|Transact Identifier|Protocol Identifier|Length Field|Unit ID|Funct Code|Data|
|
|
| 2 Bytes | 2 Bytes | 2 Bytes | 1 Byte| 1 Byte | n |
|
|
|
|
Paul Barron, January 2008
|
|
----------------------------------------------------------------------------*/
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <rs232controller.h>
|
|
#include "modbustcp.h"
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
int ModbusTCPException(unsigned char *response);
|
|
|
|
int MsgGenModbusTCP(unsigned char *ModbusMsg, int ModbusMsgLength, unsigned char *TcpPacket,
|
|
int *TcpPacketLength)
|
|
{
|
|
unsigned char MBAPbyte1 = 1, MBAPbyte2 = 1;
|
|
unsigned char lengthByte1, lengthByte2;
|
|
int index;
|
|
|
|
// Check if Device Address is Valid. This is based on RS485 having up to
|
|
// 32 devices, since we currently only have one device this won't be a problem.
|
|
if ((ModbusMsg[0] > 32) || (ModbusMsg[0] < 1))
|
|
{
|
|
printf("Error: Modbus Address out of Range: %X\n",ModbusMsg[0]);
|
|
return MODBUSTCP_BadDataAddress;
|
|
}
|
|
|
|
// Check if Function code is Valid
|
|
if ((ModbusMsg[1] > 16) || (ModbusMsg[1] < 1))
|
|
{
|
|
printf("Error: Modbus Function Code Invalid: %X\n",ModbusMsg[1]);
|
|
return MODBUSTCP_BadFunction;
|
|
}
|
|
|
|
// Calculate Legth Field
|
|
// Length should never be greater than 255 but just in case.
|
|
if ((ModbusMsgLength)>255){
|
|
lengthByte1=ModbusMsgLength/255;
|
|
lengthByte2=ModbusMsgLength%255;
|
|
}
|
|
else{
|
|
lengthByte1=0;
|
|
lengthByte2=ModbusMsgLength;
|
|
}
|
|
|
|
sprintf((char *)TcpPacket,"%c%c%c%c%c%c",MBAPbyte1,MBAPbyte2,0,0,lengthByte1,lengthByte2);
|
|
|
|
for(index=0;index<=ModbusMsgLength;index++)sprintf((char *)&TcpPacket[index+6],"%c",ModbusMsg[index]);
|
|
|
|
*TcpPacketLength=ModbusMsgLength+6;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
int transactModbusTCP(prs232 self, unsigned char *query, int queryLength, unsigned char *response, int responseLength)
|
|
{
|
|
unsigned char TCPquery[40];
|
|
int iRet, index, TCPqueryLength;
|
|
|
|
// Generate the TCP message
|
|
iRet=MsgGenModbusTCP(query,queryLength,TCPquery,&TCPqueryLength);
|
|
|
|
// Send the message and Read the reply
|
|
memset(response,0,responseLength); // puts zeros in reply up until reply length
|
|
if ((iRet=transactRS232(self,TCPquery,/*strlen(pCommand)*/12,response,20))<=0)
|
|
{
|
|
printf("Comms error!\n");
|
|
return iRet; // Comms problem
|
|
}
|
|
|
|
// Check that the response transact and protocol identifier are the same
|
|
if( (strncmp((char *)TCPquery,(char *)response,3)) == 0)
|
|
{
|
|
// Check that there is not a modbus error, see page 98 from WEST4100 User manual.
|
|
if ( response[7] > 0x80 )
|
|
{
|
|
iRet=ModbusTCPException(response);
|
|
|
|
return iRet;
|
|
}
|
|
else
|
|
{
|
|
// Return the modbus response minus the TCP Header
|
|
for(index=0;index<6;index++)
|
|
response[index]=response[index+6];
|
|
|
|
return 1;
|
|
}
|
|
|
|
return 1; // Success
|
|
}
|
|
|
|
return MODBUSTCP_TCPError;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
int ModbusTCPException(unsigned char *response)
|
|
{
|
|
if(response[8] == 0x01){
|
|
printf("Exception Code 01h: Illegal Function\n");
|
|
return MODBUSTCP_IllegalFunction;
|
|
}else if(response[8] == 0x02){
|
|
printf("Exception Code 02h: Illegal Data Address\n");
|
|
return MODBUSTCP_IllegalDataAddress;
|
|
}else if(response[8] == 0x03){
|
|
printf("Exception Code 03h: Illegal Data Value\n");
|
|
return MODBUSTCP_IllegalDataValue;
|
|
}else{
|
|
printf("Error code is greater than 81h, 82h or 83h\n");
|
|
return MODBUSTCP_UnsupportedError;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|