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

📄 mb_slv.c

📁 modbus的c语言版本应用于dos下
💻 C
📖 第 1 页 / 共 3 页
字号:
     //parse serial mode
     tmp_value = atoi(argv[5]);
     if((tmp_value<0) || (tmp_value>2))
     {
       result=-1;
       goto END_PARSE_ARGS;
     }
     serial_mode = (unsigned char) tmp_value;
   }//elseif(argc!=6)
END_PARSE_ARGS:
   return result;
}
//***********************************************************
// CRC calculation routine
//***********************************************************
static unsigned int CRC16(unsigned char *puchMsg, unsigned int usDataLen)
{
  unsigned char uchCRCHi = 0xFF ; /* high byte of CRC initialized */
  unsigned char uchCRCLo = 0xFF ; /* low byte of CRC initialized */
  unsigned int  uIndex ; /* will index into CRC lookup table */

  while (usDataLen--) /* pass through message buffer */
  {
    uIndex = uchCRCHi ^ *puchMsg++ ; /* calculate the CRC */
    uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
    uchCRCLo = auchCRCLo[uIndex] ;
  }
  return ((uchCRCHi << 8) | uchCRCLo) ;
}
//***********************************************************
//Init/Deinit serial port for modbus communication
//***********************************************************
int mb_ser_init(int port,
                long baud,
                int parity,
                unsigned char serial_mode)
{
   if(0x1954!=fossil_init(port))
   {
      return MB_ERROR;
   }
   if(-1==fossil_setbaud(port,baud,parity,8,1))
   {
      return MB_ERROR;
   }
   switch(serial_mode)
   {
      case MB_RS485:
              fossil_set_rs485(port, FOSSIL_RS485_HIGHACTIVE);
              rs485=1; //set flag
              break;
      case MB_RS232_HWFLOW:
              fossil_set_flowcontrol (port, FOSSIL_FLOWCTRL_RTSCTS  );
              break;

   }
   /* Calculate the silent_interval
      Please note: the modbus serial spec. expects a max. time interval of 1.5 chars between two
      incoming bytes inside of frame, without defining a tolerance of this interval.
      At the @CHIP-RTOS, it is not possible to measure exctly 1,5 chars time interval:
      Because of this behaviour, we set fixed silent_intervals in dependency of the baudrate
   */
   switch(baudrate)
   {
      case 300:  silent_interval = 34; //ms
                 break;
      case 600:  silent_interval = 18; //ms
                 break;
      case 1200: silent_interval = 10; //ms
                 break;
      case 2400: silent_interval = 6; //ms
                 break;
      case 4800: silent_interval = 4; //ms
                 break;
      default:   silent_interval = 2; //ms
                 break;
   }
   frame_wait_interval = silent_interval *2;
   return NO_ERROR;
}
//******************************************************************************
void mb_ser_deinit(int port)
{
  fossil_deinit (port );
}
//******************************************************************************
//Wait and Receive a modbus request frame via serial fossil
//******************************************************************************
int mb_ser_recv_frame(unsigned char * buf) //buf must provide 256 bytes
{
   int byte_count;
   int ch=-1;

   #ifdef MB_SER_DEBUG
   printf("\r\nWait for first incoming byte of frame");
   #endif
   //1. Wait endless for the first incoming char: must be slave address
   while(ch==-1)
   {
     ch=fossil_getbyte(port);
     RTX_Sleep_Time(frame_wait_interval);
   }
   buf[0]=(unsigned char)ch;
   #ifdef MB_SER_DEBUG
   printf("\r\nFirst byte received %02X", (unsigned char)ch);
   #endif


   //2. Receive frame, until a timeout occurs
   byte_count = 1;
   while(byte_count<MB_SER_MAX_BUF)
   {
     ch=fossil_getbyte(port);
     if(ch==-1)
     {
        //wait defined interval and try to receive again
        RTX_Sleep_Time(silent_interval);
        ch=fossil_getbyte(port);
        if(ch==-1) break; //timeout reached: frame completely received or not?
     }

     if(ch!=-1) //Insert byte into recvbuf
     {
        buf[byte_count++]=(unsigned char)ch;
     }
   }
   //Calculate crc checksum and see, if we got a complete modbus frame
   if(byte_count>=4)
   {
     if(0!=CRC16(buf,byte_count))
     {
       #ifdef MB_SER_DEBUG
       printf("\r\nReceive checksum error\r\n");
       #endif
       return MB_ERROR;
     }
     else
     {
       return MB_NO_ERROR;
     }
   }
   #ifdef MB_SER_DEBUG
   printf("\r\nInvalid frame received: Less than 4 bytes\n");
   #endif
   return MB_ERROR;
}
//******************************************************************************
// General send of a modbus frame via fossil
//******************************************************************************
int mb_ser_send( unsigned char * buf,
                 unsigned int length)
{
   unsigned int  result;
   unsigned int  tcnt;
   int           ch;

   if(rs485)
   {
     fossil_purge_input (port);
   }

   result=
   tcnt  = 0;
   //Wait until block, is completely placed into rtos tx serial queue
   do
   {
        result+=fossil_writeblock(port,&buf[result],length-result);
        if(result!=length)
        {
          RTX_Sleep_Time(1);
          tcnt++;
          if(tcnt>=SEND_QUEUE_TIMEOUT)
          {
           #ifdef MB_SER_DEBUG
           printf("\r\nSend timeout");
           #endif
           return MB_ERROR;
          }
        }
        else
        {
          break;
        }
   }while(result!=length);
   //Wait until everything is out of tx queue
   fossil_flush_output(port);

   RTX_Sleep_Time(frame_wait_interval);

   //Try to receive the own frame and check, if frame was correct send
   if(rs485)
   {
      result=
      tcnt  = 0;
      while(result!=length)
      {
          ch = fossil_getbyte(port);
          if(ch==-1)
          {
             RTX_Sleep_Time(1);
             tcnt+=1;
             if(tcnt>=SEND_QUEUE_TIMEOUT)
             {
                #ifdef MB_SER_DEBUG
                printf("\r\nRS485 send failed (timeout)\r\n");
                #endif
                return MB_ERROR;

             }
          }
          else
          {
             //compare incoming character with send buffer
             if((unsigned char)ch!= buf[result++])
             {
                #ifdef MB_SER_DEBUG
                printf("\r\nRS485 send failed(no correct receive of own frame)\r\n");
                #endif
                return MB_ERROR;
             }
          }
      }
   }
   return MB_NO_ERROR;
}
/*******************************************************************************
Process an incoming modbus request and send a reply to client
Input parameter:   mb_request_buf: contains modbus request frame
********************************************************************************/
int mb_ser_process_request(unsigned char * mb_request_buf, unsigned char * mb_response_buf)
{
   unsigned char function_code;
   unsigned int  response_length;
   unsigned int  start_address;
   unsigned int  checksum;
   unsigned int  output_value;
   unsigned int  quantity;
   unsigned char  read_dev_id_length;
   unsigned char byte_count;
   int result;
   #ifdef MB_SER_DEBUG
   int i;
   #endif

   //Check slave address
   if((mb_request_buf[0]!=slave_address) && (mb_request_buf[0]!=MB_SER_BCAST))
   {
      //not for us
      return MB_NO_ERROR;
   }

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

   //general preformat of responsebuffer
   mb_response_buf[0]= mb_request_buf[0]; //take slave address
   mb_response_buf[1]= mb_request_buf[1]; //take function code

   //Preset length of response
   response_length = 2;   //slave address and function code

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

⌨️ 快捷键说明

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