?? modbus_server.c
字號(hào):
/*******************************************************************************
Written by: Haemish Kyd
It is hereby certified that the author of this code specified above
has made reference only to information that is in the public domain
or is available to FieldServer Technologies via a duly signed
Non-Disclosure Agreement. This code is guaranteed free and clear of
any claim upon it by any Third Party.
The basis for this certification includes:
Original work performed by Eddie Hague.
Copyright (c) 1991-2003, FieldServer Technologies.
1991 Tarob Court, Milpitas, CA 95035, USA
(408) 262 2299
********************************************************************************
Versions
1.00aA 15 Oct 04 HLK Created
1.00aB 09 Nov 04 HLK Beautified and organised
*******************************************************************************/
#include <fst.h>
#include <ProtoMod.h>
#include <SIOAPI.H>
/*These are the main input and output buffers for the modbus messages*/
BYTE UART_RX_buf[MX_RX_TX_BUFFERSIZE] ; //Receive Buffer
BYTE UART_TX_Buffer[MX_RX_TX_BUFFERSIZE] ; //Transmit Buffer
BYTE UART_rcv_count; //Receive Buffer Counter
extern MAP_DESC_TYP coil_map[MX_COILS] ;
extern MAP_DESC_TYP discrete_inputs_map[MX_DI] ;
extern MAP_DESC_TYP register_map[MX_REG] ;
IN_BUF_TYP in_buffer;
/*============================================================================*/
//CRC Tables
rom const rom BYTE auchCRCHi_exp[] = {
0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81,
0x40, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0,
0x80, 0x41, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01,
0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80, 0x41,
0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81,
0x40, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0,
0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01,
0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81,
0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0,
0x80, 0x41, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01,
0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81,
0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0,
0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01,
0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81,
0x40
} ;
rom const rom BYTE auchCRCLo_exp[] = {
0x00, 0xc0, 0xc1, 0x01, 0xc3, 0x03, 0x02, 0xc2, 0xc6, 0x06, 0x07, 0xc7, 0x05, 0xc5, 0xc4,
0x04, 0xcc, 0x0c, 0x0d, 0xcd, 0x0f, 0xcf, 0xce, 0x0e, 0x0a, 0xca, 0xcb, 0x0b, 0xc9, 0x09,
0x08, 0xc8, 0xd8, 0x18, 0x19, 0xd9, 0x1b, 0xdb, 0xda, 0x1a, 0x1e, 0xde, 0xdf, 0x1f, 0xdd,
0x1d, 0x1c, 0xdc, 0x14, 0xd4, 0xd5, 0x15, 0xd7, 0x17, 0x16, 0xd6, 0xd2, 0x12, 0x13, 0xd3,
0x11, 0xd1, 0xd0, 0x10, 0xf0, 0x30, 0x31, 0xf1, 0x33, 0xf3, 0xf2, 0x32, 0x36, 0xf6, 0xf7,
0x37, 0xf5, 0x35, 0x34, 0xf4, 0x3c, 0xfc, 0xfd, 0x3d, 0xff, 0x3f, 0x3e, 0xfe, 0xfa, 0x3a,
0x3b, 0xfb, 0x39, 0xf9, 0xf8, 0x38, 0x28, 0xe8, 0xe9, 0x29, 0xeb, 0x2b, 0x2a, 0xea, 0xee,
0x2e, 0x2f, 0xef, 0x2d, 0xed, 0xec, 0x2c, 0xe4, 0x24, 0x25, 0xe5, 0x27, 0xe7, 0xe6, 0x26,
0x22, 0xe2, 0xe3, 0x23, 0xe1, 0x21, 0x20, 0xe0, 0xa0, 0x60, 0x61, 0xa1, 0x63, 0xa3, 0xa2,
0x62, 0x66, 0xa6, 0xa7, 0x67, 0xa5, 0x65, 0x64, 0xa4, 0x6c, 0xac, 0xad, 0x6d, 0xaf, 0x6f,
0x6e, 0xae, 0xaa, 0x6a, 0x6b, 0xab, 0x69, 0xa9, 0xa8, 0x68, 0x78, 0xb8, 0xb9, 0x79, 0xbb,
0x7b, 0x7a, 0xba, 0xbe, 0x7e, 0x7f, 0xbf, 0x7d, 0xbd, 0xbc, 0x7c, 0xb4, 0x74, 0x75, 0xb5,
0x77, 0xb7, 0xb6, 0x76, 0x72, 0xb2, 0xb3, 0x73, 0xb1, 0x71, 0x70, 0xb0, 0x50, 0x90, 0x91,
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9c, 0x5c,
0x5d, 0x9d, 0x5f, 0x9f, 0x9e, 0x5e, 0x5a, 0x9a, 0x9b, 0x5b, 0x99, 0x59, 0x58, 0x98, 0x88,
0x48, 0x49, 0x89, 0x4b, 0x8b, 0x8a, 0x4a, 0x4e, 0x8e, 0x8f, 0x4f, 0x8d, 0x4d, 0x4c, 0x8c,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
0x40
} ;
/*============================================================================*/
// Procedure to check the checksum of the message
UINT16 modrtuChecksum ( BYTE *chkbuf, BYTE len )
{
BYTE uchCRCHi = 0xff ;
BYTE uchCRCLo = 0xff ;
UINT16 uIndex ;
UINT16 temp_code;
while ( len )
{
uIndex = (UINT16) ( uchCRCHi ^ *chkbuf++ ) ;
uchCRCHi = (BYTE) ( uchCRCLo ^ auchCRCHi_exp[uIndex] ) ;
uchCRCLo = auchCRCLo_exp[uIndex] ;
len-- ;
}
temp_code = (UINT16) uchCRCHi;
temp_code = (UINT16) (temp_code << 8);
return(UINT16) ( temp_code | uchCRCLo ) ;
}
/*============================================================================*/
// Access the node ID of the system
BYTE Get_Modbus_Node_ID ( VOID )
{
BYTE Node_Address = MODBUS_NODE_ID;
return Node_Address ;
}
/*============================================================================*/
// Send response to client
VOID modbusSendUARTPacket ( BYTE length)
{
UINT16 check ;
UART_TX_Buffer[0] = (Get_Modbus_Node_ID()) ;
check = modrtuChecksum( UART_TX_Buffer, length ) ;
UART_TX_Buffer[length++] = (BYTE)(check >> 8) ;
UART_TX_Buffer[length++] = (BYTE)(check & 0xff) ;
(VOID)sioapi_puts(P6720SER2,(BYTE *)UART_TX_Buffer,length);
}
/*=========================================================================*/
// Send exception response to client
VOID modbusReturnException ( BYTE exception )
{
UART_TX_Buffer[1] |= 0x80 ; //function code for exception
UART_TX_Buffer[2] = exception ;
modbusSendUARTPacket( 3 ) ;
}
/*=========================================================================*/
// Calculate the number of bytes from the number of bits requested
BYTE modbusByteFromBitLength( UINT16 coils )
{
BYTE len = (BYTE)(coils >> 3) ; //this devides the number of bits by 8
if ( coils & 0x07 )
{ //if there was a remainder then add 1 more
len++;
}
return( len ) ;
}
/*============================================================================*/
// Return a pointer to the map descriptor containing the data requested
MAP_DESC_TYP *find_map_desc_with_data(BYTE function,UINT16 address)
{
switch ( function )
{
BYTE index;
case MODBUS_READ_COILS :
for ( index=0;index<(BYTE)MX_COILS;index++ )
{
if ( (coil_map[index].address-1)==(UINT16)address )
{
da_get_BIT(&coil_map[index]);
return &coil_map[index];
}
}
return 0;
//break;
case MODBUS_READ_DISCRETEINPUTS :
for ( index=0;index<(BYTE)MX_DI;index++ )
{
if ( (discrete_inputs_map[index].address-1)==(UINT16)address )
{
da_get_BIT(&discrete_inputs_map[index]);
return &discrete_inputs_map[index];
}
}
return 0;
//break;
case MODBUS_READ_INPUTREGISTERS:
for ( index=0;index<(BYTE)MX_REG;index++ )
{
if ( (UINT16)(register_map[index].address-1)==(UINT16)address )
{
da_get_UINT16(®ister_map[index]);
return ®ister_map[index];
}
}
return 0;
//break;
default:
return 0;
//break;
}
}
/*============================================================================*/
// Return a pointer to a map descriptor where data will be stored
MAP_DESC_TYP *store_data_to_data_array(BYTE function,UINT16 address,UINT16 data)
{
switch ( function )
{
BYTE index;
case MODBUS_WRITE_COIL :
for ( index=0;index<(BYTE)MX_COILS;index++ )
{
if ( (coil_map[index].address-1)==(UINT16)address )
{
da_put_BIT(&coil_map[index],data);
return &coil_map[index];
}
}
return 0;
//break;
case MODBUS_WRITE_REGISTER:
for ( index=0;index<(BYTE)MX_REG;index++ )
{
if ( (register_map[index].address-1)==(UINT16)address )
{
da_put_UINT16(®ister_map[index],data);
return ®ister_map[index];
}
}
return 0;
//break;
default:
return 0;
//break;
}
}
/*=========================================================================*/
// Respond to the modbus poll from the client
VOID modbusRespond ( MAP_DESC_TYP *temp_md )
{
BYTE byte_cnt, i , t, bool_val ;
BYTE byte_store, temp_bool ;
switch ( UART_RX_buf[1] )
{
/******************************************************************/
/* FUNCTION CODE 0X01 -> READ COILS */
/******************************************************************/
case MODBUS_READ_COILS :
byte_cnt = modbusByteFromBitLength( in_buffer.length ) ;
UART_TX_Buffer[2] = byte_cnt ;
for ( i = 0 ; i < byte_cnt ; i++ )
{
byte_store = 0 ;
for ( t = 0 ; t < (BYTE)BYTE_SIZE ; t++ )
{
if ( !temp_md )
{
modbusReturnException( ILLEGAL_DATA_ADDRESS ) ;
return ;
}
bool_val = (BYTE)temp_md->data ;
temp_bool = (BYTE)(bool_val << t) ;
byte_store = (BYTE)(byte_store|temp_bool) ;
in_buffer.address++ ;
if ( in_buffer.address >= in_buffer.length )
{
break ;
}
temp_md=modbusFetchData();
}
UART_TX_Buffer[3+i] = byte_store ;
}
UART_TX_Buffer[1] = UART_RX_buf[1] ;
modbusSendUARTPacket( (BYTE)(3+byte_cnt) ) ;
return ;
/******************************************************************/
/* FUNCTION CODE 0X02 -> READ DISCRETE INPUTS */
/******************************************************************/
case MODBUS_READ_DISCRETEINPUTS :
byte_cnt = modbusByteFromBitLength( in_buffer.length ) ; //divides length by 8
UART_TX_Buffer[2] = byte_cnt ;
for ( i = 0 ; i < byte_cnt ; i++ )
{
byte_store = 0 ;
for ( t = 0 ; t <(BYTE)8 ; t++ )
{
if ( !temp_md )
{
modbusReturnException( ILLEGAL_DATA_ADDRESS ) ;
return;
}
bool_val = (BYTE)temp_md->data ;
temp_bool = (BYTE)(bool_val << t) ;
byte_store = (BYTE)(byte_store|temp_bool) ;
in_buffer.address++ ;
if ( in_buffer.address >= in_buffer.length )
{
break ;
}
temp_md=modbusFetchData();
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -