⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modbus_server.c

📁 build a modbus client/server for use on the Protocessor (from FieldServer Technologies) Tools Req
💻 C
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************************

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(&register_map[index]);
               return &register_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(&register_map[index],data);
               return &register_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();
               }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -