mbfunccoils.c
上传用户:kongshuqi
上传日期:2013-10-09
资源大小:59k
文件大小:9k
源码类别:

通讯编程

开发平台:

Visual C++

  1.  /*
  2.   * FreeRTOS Modbus Libary: A Modbus serial implementation for FreeRTOS
  3.   * Copyright (C) 2006 Christian Walter <wolti@sil.at>
  4.   *
  5.   * This library is free software; you can redistribute it and/or
  6.   * modify it under the terms of the GNU Lesser General Public
  7.   * License as published by the Free Software Foundation; either
  8.   * version 2.1 of the License, or (at your option) any later version.
  9.   *
  10.   * This library is distributed in the hope that it will be useful,
  11.   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.   * Lesser General Public License for more details.
  14.   *
  15.   * You should have received a copy of the GNU Lesser General Public
  16.   * License along with this library; if not, write to the Free Software
  17.   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  18.   */
  19. /* ----------------------- System includes ----------------------------------*/
  20. #include "stdlib.h"
  21. #include "string.h"
  22. /* ----------------------- Platform includes --------------------------------*/
  23. #include "port.h"
  24. /* ----------------------- Modbus includes ----------------------------------*/
  25. #include "mb.h"
  26. #include "mbframe.h"
  27. #include "mbproto.h"
  28. #include "mbconfig.h"
  29. /* ----------------------- Defines ------------------------------------------*/
  30. #define MB_PDU_FUNC_READ_ADDR_OFF           ( MB_PDU_DATA_OFF )
  31. #define MB_PDU_FUNC_READ_COILCNT_OFF        ( MB_PDU_DATA_OFF + 2 )
  32. #define MB_PDU_FUNC_READ_SIZE               ( 4 )
  33. #define MB_PDU_FUNC_READ_COILCNT_MAX        ( 0x07D0 )
  34. #define MB_PDU_FUNC_WRITE_ADDR_OFF          ( MB_PDU_DATA_OFF )
  35. #define MB_PDU_FUNC_WRITE_VALUE_OFF         ( MB_PDU_DATA_OFF + 2 )
  36. #define MB_PDU_FUNC_WRITE_SIZE              ( 4 )
  37. #define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF      ( MB_PDU_DATA_OFF )
  38. #define MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF   ( MB_PDU_DATA_OFF + 2 )
  39. #define MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF   ( MB_PDU_DATA_OFF + 4 )
  40. #define MB_PDU_FUNC_WRITE_MUL_VALUES_OFF    ( MB_PDU_DATA_OFF + 5 )
  41. #define MB_PDU_FUNC_WRITE_MUL_SIZE_MIN      ( 5 )
  42. #define MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX   ( 0x07B0 )
  43. /* ----------------------- Static functions ---------------------------------*/
  44. eMBException    prveMBError2Exception( eMBErrorCode eErrorCode );
  45. /* ----------------------- Start implementation -----------------------------*/
  46. #if MB_FUNC_READ_COILS_ENABLED > 0
  47. eMBException
  48. eMBFuncReadCoils( UCHAR * pucFrame, USHORT * usLen )
  49. {
  50.     USHORT          usRegAddress;
  51.     USHORT          usCoilCount;
  52.     UCHAR           ucNBytes;
  53.     UCHAR          *pucFrameCur;
  54.     eMBException    eStatus = MB_EX_NONE;
  55.     eMBErrorCode    eRegStatus;
  56.     if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) )
  57.     {
  58.         usRegAddress = pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8;
  59.         usRegAddress |= pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1];
  60.         usRegAddress++;
  61.         usCoilCount = pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF] << 8;
  62.         usCoilCount = pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF + 1];
  63.         /* Check if the number of registers to read is valid. If not
  64.          * return Modbus illegal data value exception. 
  65.          */
  66.         if( ( usCoilCount >= 1 ) &&
  67.             ( usCoilCount < MB_PDU_FUNC_READ_COILCNT_MAX ) )
  68.         {
  69.             /* Set the current PDU data pointer to the beginning. */
  70.             pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
  71.             *usLen = MB_PDU_FUNC_OFF;
  72.             /* First byte contains the function code. */
  73.             *pucFrameCur++ = MB_FUNC_READ_COILS;
  74.             *usLen += 1;
  75.             /* Test if the quantity of coils is a multiple of 8. If not last
  76.              * byte is only partially field with unused coils set to zero. */
  77.             if( ( usCoilCount & 0x0007 ) != 0 )
  78.             {
  79.                 ucNBytes = ( UCHAR )( usCoilCount / 8 + 1 );
  80.             }
  81.             else
  82.             {
  83.                 ucNBytes = ( UCHAR )( usCoilCount / 8 );
  84.             }
  85.             *pucFrameCur++ = ucNBytes;
  86.             *usLen += 1;
  87.             eRegStatus =
  88.                 eMBRegCoilsCB( pucFrameCur, usRegAddress, usCoilCount,
  89.                                MB_REG_READ );
  90.             /* If an error occured convert it into a Modbus exception. */
  91.             if( eRegStatus != MB_ENOERR )
  92.             {
  93.                 eStatus = prveMBError2Exception( eRegStatus );
  94.             }
  95.             else
  96.             {
  97.                 /* The response contains the function code, the starting address
  98.                  * and the quantity of registers. We reuse the old values in the 
  99.                  * buffer because they are still valid. */
  100.                 *usLen += ucNBytes;;
  101.             }
  102.         }
  103.         else
  104.         {
  105.             eStatus = MB_EX_ILLEGAL_DATA_VALUE;
  106.         }
  107.     }
  108.     else
  109.     {
  110.         /* Can't be a valid read coil register request because the length
  111.          * is incorrect. */
  112.         eStatus = MB_EX_ILLEGAL_DATA_VALUE;
  113.     }
  114.     return eStatus;
  115. }
  116. #if MB_FUNC_WRITE_COIL_ENABLED > 0
  117. eMBException
  118. eMBFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen )
  119. {
  120.     USHORT          usRegAddress;
  121.     UCHAR           ucBuf[2];
  122.     eMBException    eStatus = MB_EX_NONE;
  123.     eMBErrorCode    eRegStatus;
  124.     if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) )
  125.     {
  126.         usRegAddress = pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8;
  127.         usRegAddress |= pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1];
  128.         usRegAddress++;
  129.         if( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF + 1] == 0x00 ) &&
  130.             ( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF ) ||
  131.               ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0x00 ) ) )
  132.         {
  133.             ucBuf[1] = 0;
  134.             if( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF )
  135.             {
  136.                 ucBuf[0] = 1;
  137.             }
  138.             else
  139.             {
  140.                 ucBuf[0] = 0;
  141.             }
  142.             eRegStatus =
  143.                 eMBRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE );
  144.             /* If an error occured convert it into a Modbus exception. */
  145.             if( eRegStatus != MB_ENOERR )
  146.             {
  147.                 eStatus = prveMBError2Exception( eRegStatus );
  148.             }
  149.         }
  150.         else
  151.         {
  152.             eStatus = MB_EX_ILLEGAL_DATA_VALUE;
  153.         }
  154.     }
  155.     else
  156.     {
  157.         /* Can't be a valid write coil register request because the length
  158.          * is incorrect. */
  159.         eStatus = MB_EX_ILLEGAL_DATA_VALUE;
  160.     }
  161.     return eStatus;
  162. }
  163. #endif
  164. #if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0
  165. eMBException
  166. eMBFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen )
  167. {
  168.     USHORT          usRegAddress;
  169.     USHORT          usCoilCnt;
  170.     UCHAR           ucByteCount;
  171.     UCHAR           ucByteCountVerify;
  172.     eMBException    eStatus = MB_EX_NONE;
  173.     eMBErrorCode    eRegStatus;
  174.     if( *usLen > ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) )
  175.     {
  176.         usRegAddress = pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8;
  177.         usRegAddress |= pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1];
  178.         usRegAddress++;
  179.         usCoilCnt = pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF] << 8;
  180.         usCoilCnt |= pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF + 1];
  181.         ucByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF];
  182.         /* Compute the number of expected bytes in the request. */
  183.         if( ( usCoilCnt & 0x0007 ) != 0 )
  184.         {
  185.             ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 + 1 );
  186.         }
  187.         else
  188.         {
  189.             ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 );
  190.         }
  191.         if( ( usCoilCnt >= 1 ) &&
  192.             ( usCoilCnt <= MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX ) &&
  193.             ( ucByteCountVerify == ucByteCount ) )
  194.         {
  195.             eRegStatus =
  196.                 eMBRegCoilsCB( &pucFrame[MB_PDU_FUNC_WRITE_MUL_VALUES_OFF],
  197.                                usRegAddress, usCoilCnt, MB_REG_WRITE );
  198.             /* If an error occured convert it into a Modbus exception. */
  199.             if( eRegStatus != MB_ENOERR )
  200.             {
  201.                 eStatus = prveMBError2Exception( eRegStatus );
  202.             }
  203.             else
  204.             {
  205.                 /* The response contains the function code, the starting address
  206.                  * and the quantity of registers. We reuse the old values in the 
  207.                  * buffer because they are still valid. */
  208.                 *usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF;
  209.             }
  210.         }
  211.         else
  212.         {
  213.             eStatus = MB_EX_ILLEGAL_DATA_VALUE;
  214.         }
  215.     }
  216.     else
  217.     {
  218.         /* Can't be a valid write coil register request because the length
  219.          * is incorrect. */
  220.         eStatus = MB_EX_ILLEGAL_DATA_VALUE;
  221.     }
  222.     return eStatus;
  223. }
  224. #endif
  225. #endif