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

📄 mb_tcp_s.c

📁 modbus的c语言版本应用于dos下
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
*
* (c) 2004 by BECK IPC GmbH
*
*******************************************************************************
*
* Module:   mb_tcp_s.c
* Function: This program provides a tcp modbus single server for SC1x3/DK60, SC12/DK40 SC13/DK50.
*           It shall be used as a template for building own own tcp modbus single
*           server applications on IPC@CHIP based devices.
*           The server executes(serves) incoming tcp client modbus requests.
*           The application programmer shall feel free to modify,expand and improve this
*           example for his own modbus server application.
*
*           The  server executes(serves)incoming modbus requests, according to the
*           SC1x3/DK60,DK50/DK40 register and coil definition below.
*           The application programmer shall feel free to modify,expand and improve this
*           example for his own modbus slave application.
*
*           For understanding the source code and using it for own applications the
*           following premises are required:
*           1. Good knowledge about the modbus protocol
*           2. Careful reading and understanding of this example program
*
*           Required hardware/software for testing:
*           1. SC1x3/DK60,DK50/SC13 or DK40/SC12 as modbus rtu server, running this program
*           2. Windows PC running a modbus tcp client application
*
*           The implementation based on the follwing docunments from modbus.org
*           Please note: The server uses only a subset of the specified modbus features
*           1. Modbus over serial line Specification & Implementation V1.0
*           2. Modbus application protocol specification V1.1
*
*           Main files of this project:
*           1. Modbus.h  :  Contains several modbus specific defines
*           2. Mb_tcp_s.c:  Contains the modbus server initialzation
                            and the general parts for receiving/executing
                            an incoming modbus client request and sending of
                            the reply.
*           3. Mb_dev.c  :  Basic functions for handle the different types of incoming
*                           modbus requests. Inside of the several function handlers
*                           the DK40/DK50 specific register/coil read/write functions
*                           are inserted, according to the DKxx demo modbus
*                           register and coil definition below.
*                           Implemented modbus function codes:
*                           01, 02, 05, 15, 04, 03, 06 , 43 (only in parts)
*
*           4. Mb_dkxx.c : Contains our DK40/DK50 specfic functions. which are called
*                          inside of the modbus handler functions implemented at mb_dev.c.
*
*           To exit the modbus server it is necessary to reboot the IPC@CHIP
*
*           The implementation based on the follwing documents from modbus.org
*           1. Modbus Messaging on TCP/IP Implementation guide
*           2. Modbus application protocol specification V1.1
********************************************************************************
*           DKxx Modbus demo holding register definition
*           Register address     Access         Meaning
*               00                 R/W          DKxx 8Bit IO port at IO addr 600h/c00h
*                                               (on DK40 only Bit 6-0 available)
*               01                 R/W          16 Bit variable, for
*                                               demonstration purpose only
*               02                 R/W          16 Bit counter variable, for
*                                               demonstration purpose only, counter
*                                               is automatically incremented by a RTOS tiner
*               03                 R/W          another 16 Bit counter variable, for
*                                               demonstration purpose only, counter
*                                               is automatically changed by a RTOS timer
*
*           DKxx Modbus  demo input register definition
*           Register address     Access         Meaning
*               00                 R            DKxx 8Bit I port at IO addr 600h/c00h
*                                               (on DK40 only Bit 6-0 available)
*               01                 R            16 Bit counter variable, for
*                                               demonstration purpose only, counter
*                                               is automatically incremented by a RTOS
*               02                 R            16 Bit counter variable, for
*                                               demonstration purpose only, counter
*                                               is automatically changed by a RTOS timer
********************************************************************************
*           DKxx Modbus  demo coil  definition
*           Register address     Access         Meaning
*               00                 R/W          DKxx/SC1x PIO 3
*               01                 R/W          DKxx/SC1x PIO 13
*               02                 R/W          Bit 0 of  mb_dkxx_var (Holding reg var 01)
*               03                 R/W          Bit 1 of  mb_dkxx_var
*               04                 R/W          Bit 2 of  mb_dkxx_var
*               05                 R/W          Bit 3 of  mb_dkxx_var
*               06                 R/W          Bit 4 of  mb_dkxx_var
*               07                 R/W          Bit 5 of  mb_dkxx_var
*               08                 R/W          Bit 6 of  mb_dkxx_var
*               09                 R/W          Bit 7 of  mb_dkxx_var
*               10                 R/W          Bit 8 of  mb_dkxx_var
*               11                 R/W          Bit 9 of  mb_dkxx_var
*               12                 R/W          Bit 10 of  mb_dkxx_var
*               13                 R/W          Bit 11 of  mb_dkxx_var
*               14                 R/W          Bit 12 of  mb_dkxx_var
********************************************************************************
*           DKxx Modbus  demo discrete input  definition
*           Register address     Access         Meaning
*               00                 R          Bit 0 of DKxx IO port 0x600/0xC00
*               01                 R          Bit 1 of DKxx IO port 0x600/0xC00
*               02                 R          Bit 2 of DKxx IO port 0x600/0xC00
*               03                 R          Bit 3 of DKxx IO port 0x600/0xC00
*               04                 R          Bit 4 of DKxx IO port 0x600/0xC00
*               05                 R          Bit 5 of DKxx IO port 0x600/0xC00
*               06                 R          Bit 6 of DKxx IO port 0x600/0xC00
********************************************************************************
* Disclaimer: This program is an example and should be used as such.
*             If you wish to use this program or parts of it in your application,
*             you must validate the code yourself. BECK IPC GmbH can not be held
*             responsible for the correct functioning or coding of this example.
*******************************************************************************
*
* $Header: mb_tcp_s.c, 6, 02.09.2005 11:07:59, Markus Bartat$
*
******************************************************************************/

/******************************************************************************
* Includes
******************************************************************************/
#include <stdio.h>
#include <mem.h>
#include "clib.h"
#include "modbus.h"
#include "mb_dev.h"

/******************************************************************************
* Constants
******************************************************************************/
#define MB_PORT                       502     // modbus server port
#define MB_RECV_TIMEOUT              2000     // ms

#define MB_TCP_IDLE                   0      // no connection established
#define MB_TCP_CONN                   1      // connection established

//#define MB_TCP_DEBUG
/******************************************************************************
* Global variables
******************************************************************************/
unsigned char mb_tcp_request_buf[MB_TCP_MAX_BUF];
unsigned char mb_tcp_response_buf[MB_TCP_MAX_BUF];

#ifdef MB_TCP_DEBUG
char ClientIP[17];
#endif
/*******************************************************************************
Check by given ip address unsigned long client_ip, if the client is authorized
to access the server.
Returns MB_ERROR, if client has no access, else MB_NO_ERROR is returned

At this example we allow everybody the access to the dkxx module.
The application programmer can insert here his own ip address check procedure
********************************************************************************/
#pragma argsused
int mb_tcp_authorized(unsigned long client_ip)
{
   return MB_NO_ERROR;
}
/*******************************************************************************
Receive and parse a incoming modbus request
Input parameter     sd: socket descriptor
Return: MB_NO_ERROR   : sucessful, mb_recvbuf contains a valid modbus request
                        with MBAB header and modbus request data as specified at the
                        "Modbus Messaging on TCP/IP Implementation guide" fro modbus.org
        MB_ERROR      : receiving of modbus request timed out
        MB_TCP_ERROR  : A tcp socket error has occured
********************************************************************************/
int mb_tcp_recv_request(int sd, unsigned char * mb_recvbuf)
{
  int fr_rcvd;
  int retval;
  int fr_length;
  int error;
  #ifdef MB_TCP_DEBUG
  int i;
  #endif

  fr_rcvd=0;
  retval = recv(sd,(char *)mb_recvbuf,MB_TCP_MAX_BUF,MSG_BLOCKING,0L,&error);
  if(retval == API_ERROR)
  {
    //an tcpip socket error has occured
    #ifdef MB_TCP_DEBUG
    printf("\r\nmb_tcp_recv: 1 socket error %d",error);
    #endif
    return MB_TCP_ERROR;
  }

  fr_rcvd=retval;
  //Try to receive 7 bytes as a MBAB header
  while(fr_rcvd<MBAB_SIZE)
  {
     retval = recv( sd, (char *)&mb_recvbuf[fr_rcvd], MB_TCP_MAX_BUF-fr_rcvd,
                    MSG_TIMEOUT, MB_RECV_TIMEOUT, &error );
     if(retval>0)
     {
        fr_rcvd+=retval;
     }
     else
     {
      if(retval==0)
      {
        //tcp reveive timeout
        #ifdef MB_TCP_DEBUG
        printf("\r\nmb_tcp_recv: 1 Receive timeout");
        #endif
        return MB_ERROR;
      }
      else
      {
         //tcp receive error
         #ifdef MB_TCP_DEBUG
         printf("\r\nmb_tcp_recv: 2 socket error %d",error);
         #endif
         return MB_TCP_ERROR;
      }
     }
  }
  //Parse the MBAB header
  if((mb_recvbuf[2]!=0) || (mb_recvbuf[3]!=0))
  {
     //invalid protocol field
    #ifdef MB_TCP_DEBUG
    printf("\r\nmb_tcp_recv: Invalid protocol %02X  %02X",mb_recvbuf[2],mb_recvbuf[3]);
    #endif
    return MB_ERROR;
  }
  //Get length
  fr_length=(int)(((unsigned int)mb_recvbuf[4] << 8) + (unsigned int)mb_recvbuf[5]);
  if(fr_length > 254)
  {
     //invalid length
     #ifdef MB_TCP_DEBUG
     printf("\r\nmb_tcp_recv: Invalid length field %04X  ",fr_length);
     #endif
     return MB_ERROR;
  }
  #ifdef MB_TCP_DEBUG
  printf("\r\nmb_tcp_recv: Length field %04X  ",fr_length);
  #endif
  //Receive the whole frame with now known length
  while(fr_rcvd < fr_length + 6)
  {
     retval = recv( sd, (char *)&mb_recvbuf[fr_rcvd], MB_TCP_MAX_BUF-fr_rcvd,
                    MSG_TIMEOUT, MB_RECV_TIMEOUT, &error );
     if(retval > 0)
     {
       fr_rcvd+=retval;
     }
     else
     {
       if(retval==0)
       {
         //tcp reveive timeout
         #ifdef MB_TCP_DEBUG
         printf("\r\nmb_tcp_recv: 2 Receive timeout");
         #endif
         return MB_ERROR;
       }
       else
       {
         //tcp receive error
         #ifdef MB_TCP_DEBUG
         printf("\r\nmb_tcp_recv: 3 socket error %d",error);
         #endif
         return MB_TCP_ERROR;
       }
     }
  }
  #ifdef MB_TCP_DEBUG
  printf("\r\nRequest MBAB: ");
  for(i=0;i<7;i++)
  {
    printf(" %02X",mb_recvbuf[i]);
  }
  printf("\r\nRequest PDU: ");
  for(i=7;i<fr_rcvd;i++)
  {
    printf(" %02X",mb_recvbuf[i]);
  }
  printf("\r\n");
  #endif
  return MB_NO_ERROR;
}
/*******************************************************************************
Process an incoming mdobus request and send a reply to client
Input parameter     mb_request_buf: contains modbus request frame
********************************************************************************/
int mb_tcp_process_request(int sd, unsigned char * mb_request_buf, unsigned char * mb_response_buf)
{
   unsigned char function_code;
   unsigned int  response_length;
   unsigned int  start_address;
   unsigned int  output_value;
   unsigned int  quantity;
   unsigned char  read_dev_id_length;
   unsigned char byte_count;
   int result,error;
   #ifdef MB_TCP_DEBUG
   int i;
   #endif

   function_code = mb_request_buf[7];
   #ifdef MB_TCP_DEBUG
   printf("\r\nmb_tcp_process: function 0x%02X\r\n",function_code);
   #endif

   //general preformat of responsebuffer
   memcpy(mb_response_buf,mb_request_buf,MBAB_SIZE+1); //copy from request_buf, incl. function_code
   //Preset length of response
   response_length = MBAB_SIZE + 1;   //7 byte header  +  1 byte function code

   switch(function_code)
   {
    //************************************************************************
    //Function code 0x01,0x02: read discrete input, coil
    //************************************************************************
    case MB_RD_COIL_STATE      :
    case MB_RD_DISCRETE_INP    :

         start_address  = ((unsigned int)mb_request_buf[8] << 8)+(unsigned int)mb_request_buf[9];
         quantity       = ((unsigned int)mb_request_buf[10] << 8)+(unsigned int)mb_request_buf[11];

         if(function_code==MB_RD_COIL_STATE)
         {
           //execute defined modbus device read coil operation
           result         =  mb_read_coils(start_address,

⌨️ 快捷键说明

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