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

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * FreeModbus Libary: Win32 Port
  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.  * File: $Id: portserial.c,v 1.6 2006/07/21 10:59:14 wolti Exp $
  20.  */
  21. #include <windows.h>
  22. #include "port.h"
  23. /* ----------------------- Modbus includes ----------------------------------*/
  24. #include "mb.h"
  25. #include "mbport.h"
  26. #include "mbconfig.h"
  27. /* ----------------------- Defines  -----------------------------------------*/
  28. #if MB_ASCII_ENABLED == 1
  29. #define BUF_SIZE 513     /* must hold a complete ASCII frame. */
  30. #else
  31. #define BUF_SIZE 256     /* must hold a complete RTU frame. */
  32. #endif
  33. /* ----------------------- Static variables ---------------------------------*/
  34. static HANDLE   g_hSerial;
  35. static BOOL     bRxEnabled;
  36. static BOOL     bTxEnabled;
  37. static UCHAR    ucBuffer[BUF_SIZE];
  38. static INT      uiRxBufferPos;
  39. static INT      uiTxBufferPos;
  40. /* ----------------------- Function prototypes ------------------------------*/
  41. LPTSTR          Error2String( DWORD dwError );
  42. /* ----------------------- Begin implementation -----------------------------*/
  43. void
  44. vMBPortSerialEnable( BOOL bEnableRx, BOOL bEnableTx )
  45. {
  46.     /* it is not allowed that both receiver and transmitter are enabled. */
  47.     assert( !bEnableRx || !bEnableTx );
  48.     if( bEnableRx )
  49.     {
  50.         PurgeComm( g_hSerial, PURGE_RXCLEAR );
  51.         uiRxBufferPos = 0;
  52.         bRxEnabled = TRUE;
  53.     }
  54.     else
  55.     {
  56.         bRxEnabled = FALSE;
  57.     }
  58.     if( bEnableTx )
  59.     {
  60.         bTxEnabled = TRUE;
  61.         uiTxBufferPos = 0;
  62.     }
  63.     else
  64.     {
  65.         bTxEnabled = FALSE;
  66.     }
  67. }
  68. BOOL
  69. xMBPortSerialInit( UCHAR ucPort, ULONG ulBaudRate, UCHAR ucDataBits,
  70.                    eMBParity eParity )
  71. {
  72.     TCHAR           szDevice[8];
  73.     BOOL            bStatus = TRUE;
  74.     DCB             dcb;
  75.     memset( &dcb, 0, sizeof( dcb ) );
  76.     dcb.DCBlength = sizeof( dcb );
  77.     dcb.BaudRate = ulBaudRate;
  78.     _stprintf_s( szDevice, 8, _T( "COM%d" ), ucPort );
  79.     switch ( eParity )
  80.     {
  81.         case MB_PAR_NONE:
  82.             dcb.Parity = NOPARITY;
  83.             dcb.fParity = 0;
  84.             break;
  85.         case MB_PAR_EVEN:
  86.             dcb.Parity = EVENPARITY;
  87.             dcb.fParity = 1;
  88.             break;
  89.         case MB_PAR_ODD:
  90.             dcb.Parity = ODDPARITY;
  91.             dcb.fParity = 1;
  92.             break;
  93.         default:
  94.             bStatus = FALSE;
  95.     }
  96.     switch ( ucDataBits )
  97.     {
  98.         case 8:
  99.             dcb.ByteSize = 8;
  100.             break;
  101.         case 7:
  102.             dcb.ByteSize = 7;
  103.             break;
  104.         default:
  105.             bStatus = FALSE;
  106.     }
  107.     if( bStatus )
  108.     {
  109.         /* we don't use XON/XOFF flow control. */
  110.         dcb.fInX = dcb.fOutX = FALSE;
  111.         /* we don't need hardware handshake. */
  112.         dcb.fOutxCtsFlow = dcb.fOutxCtsFlow = FALSE;
  113.         dcb.fRtsControl = RTS_CONTROL_ENABLE;
  114.         dcb.fDtrControl = DTR_CONTROL_ENABLE;
  115.         /* misc parameters */
  116.         dcb.fErrorChar = FALSE;
  117.         dcb.fBinary = TRUE;
  118.         dcb.fNull = FALSE;
  119.         dcb.fAbortOnError = FALSE;
  120.         dcb.wReserved = 0;
  121.         dcb.XonLim = 2;
  122.         dcb.XoffLim = 4;
  123.         dcb.XonChar = 0x13;
  124.         dcb.XoffChar = 0x19;
  125.         dcb.EvtChar = 0;
  126.         /* Open the serial device. */
  127.         g_hSerial =
  128.             CreateFile( szDevice, GENERIC_READ | GENERIC_WRITE, 0, NULL,
  129.                         OPEN_EXISTING, 0, NULL );
  130.         if( g_hSerial == INVALID_HANDLE_VALUE )
  131.         {
  132.             vMBPortLog( MB_LOG_ERROR, _T( "SER-INIT" ), _T( "Can't open serial port %s: %s" ),
  133.                         szDevice, Error2String( GetLastError( ) ) );
  134.             bStatus = FALSE;
  135.         }
  136.         else if( !SetCommState( g_hSerial, &dcb ) )
  137.         {
  138.             vMBPortLog( MB_LOG_ERROR, _T( "SER-INIT" ),
  139.                         _T( "Can't set settings for serial device %s: %s" ), 
  140.                         szDevice, Error2String( GetLastError( ) ) );
  141.             bStatus = FALSE;
  142.         }
  143.         else if( !SetCommMask( g_hSerial, 0 ) )
  144.         {
  145.             vMBPortLog( MB_LOG_ERROR, _T( "SER-INIT" ),
  146.                         _T( "Can't set communication event mask for serial device %s: %s" ),
  147.                         szDevice, Error2String( GetLastError( ) ) );
  148.             bStatus = FALSE;
  149.         }
  150.         else
  151.         {
  152.             vMBPortSerialEnable( FALSE, FALSE );
  153.             bStatus = TRUE;
  154.         }
  155.     }
  156.     return bStatus;
  157. }
  158. BOOL
  159. xMBPortSerialSetTimeout( DWORD dwTimeoutMs )
  160. {
  161.     BOOL            bStatus;
  162.     COMMTIMEOUTS    cto;
  163.     /* usTimeOut is the inter character timeout used to detect the end 
  164.      * of frame. The total timeout is set to 50ms to make sure we
  165.      * can exit the blocking read. */
  166.     cto.ReadIntervalTimeout = dwTimeoutMs;
  167.     cto.ReadTotalTimeoutConstant = 50;
  168.     cto.ReadTotalTimeoutMultiplier = 0;
  169.     cto.WriteTotalTimeoutConstant = 0;
  170.     cto.WriteTotalTimeoutMultiplier = 0;
  171.     if( !SetCommTimeouts( g_hSerial, &cto ) )
  172.     {
  173.          vMBPortLog( MB_LOG_ERROR, _T( "SER-INIT" ),
  174.                      _T( "Can't set timeouts for serial device: %s" ),
  175.                      Error2String( GetLastError( ) ) );
  176.         bStatus = FALSE;
  177.     }
  178.     else
  179.     {
  180.         bStatus = TRUE;
  181.     }
  182.     return bStatus;
  183. }
  184. void
  185. vMBPortClose ( void )
  186. {
  187.     ( void )CloseHandle( g_hSerial );
  188. }
  189. BOOL
  190. xMBPortSerialPoll(  )
  191. {
  192.     BOOL            bStatus = TRUE;
  193.     DWORD           dwBytesRead;
  194.     DWORD           dwBytesWritten;
  195.     DWORD           i;
  196.     while( bRxEnabled )
  197.     {
  198.         /* buffer wrap around. */
  199.         if( uiRxBufferPos >= BUF_SIZE )
  200.             uiRxBufferPos = 0;
  201.         if( ReadFile( g_hSerial, &ucBuffer[uiRxBufferPos],
  202.                       BUF_SIZE - uiRxBufferPos, &dwBytesRead, NULL ) )
  203.         {
  204.             if( dwBytesRead == 0 )
  205.             {
  206.                 /* timeout with no bytes. */
  207.                 break;
  208.             }
  209.             else if( dwBytesRead > 0 )
  210.             {
  211.                 vMBPortLog( MB_LOG_DEBUG, _T( "SER-POLL" ),
  212.                             _T( "detected end of frame (t3.5 expired.)rn" ) );
  213.                 for( i = 0; i < dwBytesRead; i++ )
  214.                 {
  215.                     /* Call the modbus stack and let him fill the buffers. */
  216.                     ( void )pxMBFrameCBByteReceived(  );
  217.                 }
  218.             }
  219.         }
  220.         else
  221.         {
  222.             vMBPortLog( MB_LOG_ERROR, _T( "SER-POLL" ), _T( "I/O error on serial device: %s" ),
  223.                         Error2String( GetLastError ( ) ) );
  224.             bStatus = FALSE;
  225.         }
  226.     }
  227.     if( bTxEnabled )
  228.     {
  229.         while( bTxEnabled )
  230.         {
  231.             ( void )pxMBFrameCBTransmitterEmpty(  );
  232.             /* Call the modbus stack to let him fill the buffer. */
  233.         }
  234.         dwBytesWritten = 0;
  235.         if( !WriteFile
  236.             ( g_hSerial, &ucBuffer[0], uiTxBufferPos, &dwBytesWritten, NULL )
  237.             || ( dwBytesWritten != uiTxBufferPos ) )
  238.         {
  239.             vMBPortLog( MB_LOG_ERROR, _T( "SER-POLL" ), _T( "I/O error on serial device: %s" ),
  240.                         Error2String( GetLastError ( ) ) );
  241.             bStatus = FALSE;
  242.         }
  243.     }
  244.     return bStatus;
  245. }
  246. BOOL
  247. xMBPortSerialPutByte( CHAR ucByte )
  248. {
  249.     assert( uiTxBufferPos < BUF_SIZE );
  250.     ucBuffer[uiTxBufferPos] = ucByte;
  251.     uiTxBufferPos++;
  252.     return TRUE;
  253. }
  254. BOOL
  255. xMBPortSerialGetByte( CHAR * pucByte )
  256. {
  257.     assert( uiRxBufferPos < BUF_SIZE );
  258.     *pucByte = ucBuffer[uiRxBufferPos];
  259.     uiRxBufferPos++;
  260.     return TRUE;
  261. }