// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + // + FileName: CommsDevice.cpp Author: S.Hammond // + // + Version: 1 Date: 24/June/1999 // + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + // + This file contains the low level code to talk to the // + communications interface. It contains the following functions: // + // + CCommsDevice() // + This function is called when the CommsDevice class is created // + and resets the communications handle to its default state. // + // + ~CCommsDevice() // + This function is called when the CommsDevice class is // + destroyed. // + // + OpenComms(PCOMMSSETUP pSetup) // + This function is called to open the communications channel. // + The details of the communications channel are held in the // + COMSSETUP structure passed to it. If a communications channel is // + already open then the function first closes the open channel. // + // + CheckComms() // + This function is used to check the state of the communications // + channel. It returns a true value if the communications channel is // + open and ready for use // + // + CheckBaud(BYTE bBaud) // + This function is used to compare a baud rate value from an // + instrument with the baud rate of the currently open communications // + channel. It returns true if the baud rates are the same. // + // + WriteDevice(BYTE *Buffer,DWORD dwLen,DWORD *dwWritten) // + This function is used to send data to the currently open // + communications channel. It sends the number of bytes specified in // + the parameter dwLen and sets the actual number of bytes written into // + the parameter dwWritten. The function returns false if their was a // + communications error. // + // + ReadDevice(BYTE *Buffer,DWORD *dwRead) // + This function is used to receive date from the currently open // + communications channel. It checks the communications device for data // + ready to read and if present reads the data. It will attempt to read // + data from the device a number of times but will time out if no data // + is present. The function returns false if their was a communications // + error. // + // + CloseComms() // + This function closes the currently open communications // + channel. // + // + This file also makes use of the following structures: // + // + COMMSSETUP: // + This structure contains the information required to setup // + a communications channel. It has the following members // + Device: A string containing the device name. e.g. "COM1" // + Baud: A number which is the baud rate required. // + Parity: A value which is the parity type required, it is one of // + the following _PARITY_NONE, _PARITY_EVEN or _PARITY_ODD // + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #include "stdafx.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define _COMMSDEVICE_C_ #include "CalPoll.h" #include "Comms.h" #include "CommsDevice.h" #include "ModBus.h" #include "CalPollDlg.h" // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CCommsDevice::CCommsDevice() { // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Reset communications device handle // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ComHandle=INVALID_HANDLE_VALUE; } CCommsDevice::~CCommsDevice() { } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Open the required communications resource and configure as specified // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void CCommsDevice::OpenComms(PCOMMSSETUP pSetup) { DCB dcb; COMMTIMEOUTS cto; // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Do we currently have an open communications handle ? // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if ( ComHandle!=INVALID_HANDLE_VALUE ) { // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Close the current handle // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CloseComms(); } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Open a new communications handle // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ComHandle=CreateFile(pSetup->Device,GENERIC_READ|GENERIC_WRITE,0, NULL,OPEN_EXISTING,0,NULL); if ( ComHandle==INVALID_HANDLE_VALUE ) { // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + A handle could not be opened // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ AfxMessageBox( "The requested communications device could not be opened"); return; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Set the communications buffer sizes // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ SetupComm(ComHandle,256,256); // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Get the current communications parameters from the device // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if ( GetCommState(ComHandle,&dcb)==0 ) { // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Unable to get communications setup // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ AfxMessageBox("Unable to configure selected communications resource"); CloseComms(); return; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Setup the communications setup (dcb) structure as required // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CurrentBaud=pSetup->Baud; switch (pSetup->Baud) { case 1200: dcb.BaudRate=CBR_1200; break; case 2400: dcb.BaudRate=CBR_2400; break; case 4800: dcb.BaudRate=CBR_4800; break; case 9600: dcb.BaudRate=CBR_9600; break; case 19200: dcb.BaudRate=CBR_19200; break; } switch (pSetup->Parity) { case _PARITY_NONE: dcb.fParity=FALSE; dcb.Parity=NOPARITY; break; case _PARITY_EVEN: dcb.fParity=TRUE; dcb.Parity=EVENPARITY; break; case _PARITY_ODD: dcb.fParity=TRUE; dcb.Parity=ODDPARITY; break; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Turn off all hardware handshaking // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ dcb.fOutxCtsFlow=FALSE; dcb.fOutxDsrFlow=FALSE; dcb.fDtrControl=DTR_CONTROL_ENABLE; dcb.fDsrSensitivity=FALSE; dcb.fOutX=FALSE; dcb.fInX=FALSE; dcb.fRtsControl=RTS_CONTROL_DISABLE; // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Other setup // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ dcb.fAbortOnError=FALSE; dcb.StopBits=ONESTOPBIT; dcb.ByteSize=8; // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Set the new communications parameters for the device // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if ( SetCommState(ComHandle,&dcb)==0 ) { // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + The communications device cannot be configured // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ AfxMessageBox("Unable to configure selected communications resource"); CloseComms(); return; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Setup the communications timeout values // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cto.ReadIntervalTimeout=MAXDWORD; cto.ReadTotalTimeoutMultiplier=0; cto.ReadTotalTimeoutConstant=10000; cto.WriteTotalTimeoutMultiplier=0; cto.WriteTotalTimeoutConstant=10000; SetCommTimeouts(ComHandle,&cto); // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Remove any active break event // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ClearCommBreak(ComHandle); } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Check if we have a valid communication channel // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BOOL CCommsDevice::CheckComms(void) { if ( ComHandle==INVALID_HANDLE_VALUE ) { return(FALSE); } return(TRUE); } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Check the baud byte returned from the instrument is the same as // + the current communications rate // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BOOL CCommsDevice::CheckBaud(BYTE bBaud) { switch ( bBaud ) { case 0: if ( CurrentBaud==1200 ) { return(TRUE); } break; case 1: if ( CurrentBaud==2400 ) { return(TRUE); } break; case 2: if ( CurrentBaud==4800 ) { return(TRUE); } break; case 3: if ( CurrentBaud==9600 ) { return(TRUE); } break; case 4: if ( CurrentBaud==19200 ) { return(TRUE); } break; } return(FALSE); } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Write characters to the communications device // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BOOL CCommsDevice::WriteDevice(BYTE *Buffer,DWORD dwLen,DWORD *dwWritten) { BOOL bReturn=FALSE; *dwWritten=0; if ( CheckComms() ) { // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Send the data to the instrument // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bReturn=WriteFile(ComHandle,Buffer,dwLen,dwWritten,NULL); // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Wait to allow the instrument to process the message // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Sleep(20); } return(bReturn); } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Read characters from the communications device // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BOOL CCommsDevice::ReadDevice(BYTE *Buffer,DWORD *dwRead) { DWORD dwError; COMSTAT sStat; int iWait; DWORD dwReadLength; BOOL bReturn; // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Reset count of read bytes and check that the communications // + handle is open // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ *dwRead=0; if ( !CheckComms() ) { return(FALSE); } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Wait for some reply data // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ for (iWait=0;iWaitMODBUS_MINIMUM_LENGTH ) { // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + We have some characters now so read them in // + Ensure that we do not read beyond the length of the // + input buffer // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ dwReadLength=min(sStat.cbInQue,MESSAGE_BUFFER_LENGTH); bReturn=ReadFile(ComHandle,Buffer,dwReadLength,dwRead,NULL); // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Wait to allow other instruments to process the message // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Sleep(20); return(bReturn); } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + A short delay // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Sleep(1); } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + No errors so return true but leave the bytes read count at zero // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ return(TRUE); } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Close the communications down // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void CCommsDevice::CloseComms(void) { // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + Close the current communications handle // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CloseHandle(ComHandle); ComHandle=INVALID_HANDLE_VALUE; }