BOOL xMBPortSerialPoll( ) { BOOL bStatus = TRUE; DWORD dwBytesRead; DWORD dwBytesWritten; DWORD i; while( bRxEnabled ) { /* buffer wrap around. */ if( uiRxBufferPos >= BUF_SIZE ) uiRxBufferPos = 0; if( ReadFile( g_hSerial, &ucBuffer[uiRxBufferPos], BUF_SIZE - uiRxBufferPos, &dwBytesRead, NULL ) ) { if( dwBytesRead == 0 ) { /* timeout with no bytes. */ break; } else if( dwBytesRead > 0 ) { vMBPortLog( MB_LOG_DEBUG, _T( "SER-POLL" ), _T( "detected end of frame (t3.5 expired.)\r\n" ) ); for( i = 0; i < dwBytesRead; i++ ) { /* Call the modbus stack and let him fill the buffers. */ ( void )pxMBFrameCBByteReceived( ); } } } else { vMBPortLog( MB_LOG_ERROR, _T( "SER-POLL" ), _T( "I/O error on serial device: %s" ), Error2String( GetLastError ( ) ) ); bStatus = FALSE; } } if( bTxEnabled ) { while( bTxEnabled ) { ( void )pxMBFrameCBTransmitterEmpty( ); /* Call the modbus stack to let him fill the buffer. */ } dwBytesWritten = 0; if( !WriteFile ( g_hSerial, &ucBuffer[0], uiTxBufferPos, &dwBytesWritten, NULL ) || ( dwBytesWritten != uiTxBufferPos ) ) { vMBPortLog( MB_LOG_ERROR, _T( "SER-POLL" ), _T( "I/O error on serial device: %s" ), Error2String( GetLastError ( ) ) ); bStatus = FALSE; } } return bStatus; }
BOOL xMBPortSerialSetTimeout( DWORD dwTimeoutMs ) { BOOL bStatus; COMMTIMEOUTS cto; /* usTimeOut is the inter character timeout used to detect the end * of frame. The total timeout is set to 50ms to make sure we * can exit the blocking read. */ cto.ReadIntervalTimeout = dwTimeoutMs; cto.ReadTotalTimeoutConstant = 50; cto.ReadTotalTimeoutMultiplier = 0; cto.WriteTotalTimeoutConstant = 0; cto.WriteTotalTimeoutMultiplier = 0; if( !SetCommTimeouts( g_hSerial, &cto ) ) { vMBPortLog( MB_LOG_ERROR, _T( "SER-INIT" ), _T( "Can't set timeouts for serial device: %s" ), Error2String( GetLastError( ) ) ); bStatus = FALSE; } else { bStatus = TRUE; } return bStatus; }
/**************************************************************************** * * * FUNCTION : CompleteTransaction() * * * * PURPOSE : This handles completed synchronous and asynchronous * * transactions as well as failed attempted transactions. * * * * RETURNS : TRUE - If successful. * * FALSE - otherwise. * * * ****************************************************************************/ VOID CompleteTransaction( HWND hwndInfoCtrl, XACT *pxact) { PSTR psz; if (pxact->ret) { /* * Successful transaction case */ SendMessage(hwndInfoCtrl, ICM_SETSTRING, ICSID_LL, (DWORD)(LPSTR)"Completed"); if (pxact->wType == XTYP_REQUEST) { /* * Show resulting data */ psz = GetTextData((HDDEDATA)pxact->ret); SendMessage(hwndInfoCtrl, ICM_SETSTRING, ICSID_CENTER, (DWORD)(LPSTR)psz); MyFree(psz); /* * free returned data since it is displayed. */ DdeFreeDataHandle(pxact->ret); pxact->ret = 0L; SendMessage(hwndInfoCtrl, ICM_SETSTRING, ICSID_UR, NULL); } } else { /* * failed - show error result. */ SendMessage(hwndInfoCtrl, ICM_SETSTRING, ICSID_LL, (DWORD)(LPSTR)Error2String(DdeGetLastError(idInst))); } pxact->fsOptions |= XOPT_COMPLETED; }
BOOL xMBPortSerialInit( UCHAR ucPort, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity ) { TCHAR szDevice[8]; BOOL bStatus = TRUE; DCB dcb; memset( &dcb, 0, sizeof( dcb ) ); dcb.DCBlength = sizeof( dcb ); dcb.BaudRate = ulBaudRate; _stprintf_s( szDevice, 8, _T( "COM%d" ), ucPort ); switch ( eParity ) { case MB_PAR_NONE: dcb.Parity = NOPARITY; dcb.fParity = 0; break; case MB_PAR_EVEN: dcb.Parity = EVENPARITY; dcb.fParity = 1; break; case MB_PAR_ODD: dcb.Parity = ODDPARITY; dcb.fParity = 1; break; default: bStatus = FALSE; } switch ( ucDataBits ) { case 8: dcb.ByteSize = 8; break; case 7: dcb.ByteSize = 7; break; default: bStatus = FALSE; } if( bStatus ) { /* we don't use XON/XOFF flow control. */ dcb.fInX = dcb.fOutX = FALSE; /* we don't need hardware handshake. */ dcb.fOutxCtsFlow = dcb.fOutxCtsFlow = FALSE; dcb.fRtsControl = RTS_CONTROL_ENABLE; dcb.fDtrControl = DTR_CONTROL_ENABLE; /* misc parameters */ dcb.fErrorChar = FALSE; dcb.fBinary = TRUE; dcb.fNull = FALSE; dcb.fAbortOnError = FALSE; dcb.wReserved = 0; dcb.XonLim = 2; dcb.XoffLim = 4; dcb.XonChar = 0x13; dcb.XoffChar = 0x19; dcb.EvtChar = 0; /* Open the serial device. */ g_hSerial = CreateFile( szDevice, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); if( g_hSerial == INVALID_HANDLE_VALUE ) { vMBPortLog( MB_LOG_ERROR, _T( "SER-INIT" ), _T( "Can't open serial port %s: %s" ), szDevice, Error2String( GetLastError( ) ) ); bStatus = FALSE; } else if( !SetCommState( g_hSerial, &dcb ) ) { vMBPortLog( MB_LOG_ERROR, _T( "SER-INIT" ), _T( "Can't set settings for serial device %s: %s" ), szDevice, Error2String( GetLastError( ) ) ); bStatus = FALSE; } else if( !SetCommMask( g_hSerial, 0 ) ) { vMBPortLog( MB_LOG_ERROR, _T( "SER-INIT" ), _T( "Can't set communication event mask for serial device %s: %s" ), szDevice, Error2String( GetLastError( ) ) ); bStatus = FALSE; } else { vMBPortSerialEnable( FALSE, FALSE ); bStatus = TRUE; } } return bStatus; }