|
@@ -434,4 +434,229 @@ bool CBaseSerial::SetupPort()
|
|
|
return false;
|
|
|
|
|
|
return true;
|
|
|
-}
|
|
|
+}
|
|
|
+
|
|
|
+namespace CFG
|
|
|
+{
|
|
|
+ bool CSerial::Open(int nPort, DWORD dwBaudRate /* = 9600 */, int nParity /* = NOPARITY */, BYTE DataBits /* = 8 */, int nStopBits /* = ONESTOPBIT */, int nFC /* = NoFlowControl */ )
|
|
|
+ {
|
|
|
+ Close();
|
|
|
+ _stprintf_s(_szPort, _T("\\\\.\\COM%d"), nPort);
|
|
|
+
|
|
|
+ // 以独占方式打开串口;
|
|
|
+ _hPort = CreateFile(_szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, NULL /*FILE_ATTRIBUTE_NORMAL*/, NULL);
|
|
|
+ if( _hPort == INVALID_HANDLE_VALUE)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ // SetupComm设置缓冲区大小;
|
|
|
+ bool bResult = SetupComm(_hPort, 1024, 1024);
|
|
|
+ ASSERT(bResult);
|
|
|
+ if( !bResult )
|
|
|
+ return false;
|
|
|
+
|
|
|
+ // 在串口读写之前,清除缓冲区;
|
|
|
+ bResult = PurgeComm(_hPort, PURGE_TXCLEAR|PURGE_RXCLEAR);
|
|
|
+ ASSERT(bResult);
|
|
|
+ if(!bResult)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ DCB dcb;
|
|
|
+ COMMTIMEOUTS timeout;
|
|
|
+ //////////////////////////////////////////////////////////////////////////
|
|
|
+ // GetCommState获取设备控制块状态;
|
|
|
+ bResult = GetCommState(_hPort, &_DCB);
|
|
|
+ ASSERT(bResult);
|
|
|
+ if(!bResult)
|
|
|
+ return FALSE;
|
|
|
+
|
|
|
+ _DCB.Parity = nParity;
|
|
|
+ if(_DCB.Parity == NOPARITY)
|
|
|
+ _DCB.fParity = FALSE;
|
|
|
+ else
|
|
|
+ _DCB.fParity = TRUE;
|
|
|
+
|
|
|
+ _DCB.BaudRate = dwBaudRate;
|
|
|
+ _DCB.ByteSize = DataBits;
|
|
|
+ _DCB.StopBits = nStopBits;
|
|
|
+ if(_DCB.ByteSize == 8)
|
|
|
+ _DCB.StopBits = ONESTOPBIT;
|
|
|
+
|
|
|
+ //Setup the flow control
|
|
|
+ _DCB.fDsrSensitivity = FALSE;
|
|
|
+ switch (nFC)
|
|
|
+ {
|
|
|
+ case NoFlowControl:
|
|
|
+ {
|
|
|
+ _DCB.fOutxCtsFlow = FALSE;
|
|
|
+ _DCB.fOutxDsrFlow = FALSE;
|
|
|
+ _DCB.fOutX = FALSE;
|
|
|
+ _DCB.fInX = FALSE;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case CtsRtsFlowControl:
|
|
|
+ {
|
|
|
+ _DCB.fOutxCtsFlow = TRUE;
|
|
|
+ _DCB.fOutxDsrFlow = FALSE;
|
|
|
+ _DCB.fRtsControl = RTS_CONTROL_HANDSHAKE;
|
|
|
+ _DCB.fOutX = FALSE;
|
|
|
+ _DCB.fInX = FALSE;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case CtsDtrFlowControl:
|
|
|
+ {
|
|
|
+ _DCB.fOutxCtsFlow = TRUE;
|
|
|
+ _DCB.fOutxDsrFlow = FALSE;
|
|
|
+ _DCB.fDtrControl = DTR_CONTROL_HANDSHAKE;
|
|
|
+ _DCB.fOutX = FALSE;
|
|
|
+ _DCB.fInX = FALSE;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case DsrRtsFlowControl:
|
|
|
+ {
|
|
|
+ _DCB.fOutxCtsFlow = FALSE;
|
|
|
+ _DCB.fOutxDsrFlow = TRUE;
|
|
|
+ _DCB.fRtsControl = RTS_CONTROL_HANDSHAKE;
|
|
|
+ _DCB.fOutX = FALSE;
|
|
|
+ _DCB.fInX = FALSE;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case DsrDtrFlowControl:
|
|
|
+ {
|
|
|
+ _DCB.fOutxCtsFlow = FALSE;
|
|
|
+ _DCB.fOutxDsrFlow = TRUE;
|
|
|
+ _DCB.fDtrControl = DTR_CONTROL_HANDSHAKE;
|
|
|
+ _DCB.fOutX = FALSE;
|
|
|
+ _DCB.fInX = FALSE;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case XonXoffFlowControl:
|
|
|
+ {
|
|
|
+ _DCB.fOutxCtsFlow = FALSE;
|
|
|
+ _DCB.fOutxDsrFlow = FALSE;
|
|
|
+ _DCB.fOutX = TRUE;
|
|
|
+ _DCB.fInX = TRUE;
|
|
|
+ _DCB.XonChar = 0x11;
|
|
|
+ _DCB.XoffChar = 0x13;
|
|
|
+ _DCB.XoffLim = 100;
|
|
|
+ _DCB.XonLim = 100;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ {
|
|
|
+ ATLASSERT(FALSE);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // SetCommState设置设备的控制块状态;
|
|
|
+ bResult = SetCommState(_hPort, &_DCB);
|
|
|
+ ASSERT(bResult);
|
|
|
+ if(!bResult)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ //////////////////////////////////////////////////////////////////////////
|
|
|
+ // 获取设备的超时值;
|
|
|
+ bResult = GetCommTimeouts(_hPort, &_TIMEOUT);
|
|
|
+ ASSERT(bResult);
|
|
|
+ if(!bResult)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ _TIMEOUT.ReadIntervalTimeout = 1;
|
|
|
+ // 设置0,否则读取超时=ReadTotalTimeoutMultiplier*读取的长度+ReadTotalTimeoutConstant;
|
|
|
+ _TIMEOUT.ReadTotalTimeoutMultiplier = 0;
|
|
|
+ _TIMEOUT.ReadTotalTimeoutConstant = 3000;
|
|
|
+ // 写可设置此值,写超时=WriteTotalTimeoutMultiplier*写入长度+WriteTotalTimeoutConstant;
|
|
|
+ _TIMEOUT.WriteTotalTimeoutMultiplier = 5;
|
|
|
+ _TIMEOUT.WriteTotalTimeoutConstant = 1500;
|
|
|
+
|
|
|
+ // 设置设备的超时值;
|
|
|
+ bResult = SetCommTimeouts(_hPort, &_TIMEOUT);
|
|
|
+ ASSERT(bResult);
|
|
|
+ if(!bResult)
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ void CSerial::Close()
|
|
|
+ {
|
|
|
+ if ( IsOpen() ) {
|
|
|
+ CloseHandle(_hPort);
|
|
|
+ _hPort = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ bool CSerial::Write(LPCVOID lpBuffer, DWORD dwNumberOfBytesToWrite)
|
|
|
+ {
|
|
|
+ if (!IsOpen())
|
|
|
+ return false;
|
|
|
+
|
|
|
+ DWORD dwError;
|
|
|
+ if (::ClearCommError(_hPort, &dwError, NULL) && dwError > 0)
|
|
|
+ ::PurgeComm(_hPort, PURGE_TXABORT | PURGE_TXCLEAR); // 清空输出缓冲区(PURGE_TXCLEAR)
|
|
|
+
|
|
|
+ DWORD dwNumberOfBytesWritten = 0;
|
|
|
+ if ( !::WriteFile(_hPort, lpBuffer, dwNumberOfBytesToWrite, &dwNumberOfBytesWritten, NULL) )
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ }
|
|
|
+
|
|
|
+ return dwNumberOfBytesWritten == dwNumberOfBytesToWrite;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool CSerial::Read(LPVOID lpBuffer, DWORD dwNumberOfBytesToRead)
|
|
|
+ {
|
|
|
+ if (!IsOpen())
|
|
|
+ return false;
|
|
|
+
|
|
|
+ COMSTAT Stat;
|
|
|
+ DWORD dwError;
|
|
|
+
|
|
|
+ if ( ::ClearCommError(_hPort, &dwError, &Stat) && dwError > 0 ) {
|
|
|
+ ::PurgeComm(_hPort, PURGE_RXABORT | PURGE_RXCLEAR); // 清空输入缓冲区(PURGE_RXCLEAR)
|
|
|
+ }
|
|
|
+
|
|
|
+ DWORD dwNumberOfBytesRead = 0;
|
|
|
+ if ( !::ReadFile(_hPort, lpBuffer, dwNumberOfBytesToRead, &dwNumberOfBytesRead, NULL) )
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return dwNumberOfBytesRead > 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool CSerial::SetWriteTimeout(DWORD dwWriteTotalTimeoutMultiplier /* = 5 */, DWORD dwWriteTotalTimeoutConstant /* = 1500 */)
|
|
|
+ {
|
|
|
+ _TIMEOUT.WriteTotalTimeoutConstant = dwWriteTotalTimeoutConstant;
|
|
|
+ _TIMEOUT.WriteTotalTimeoutMultiplier = dwWriteTotalTimeoutMultiplier;
|
|
|
+ return IsOpen() ? ::SetCommTimeouts(_hPort, &_TIMEOUT) == TRUE : false;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool CSerial::SetReadTimeout(DWORD dwReadIntervalTimeout /* = 5 */, DWORD dwReadTotalTimeoutMultiplier /* = 0 */, DWORD dwReadTotalTimeoutConstant /* = 3000 */)
|
|
|
+ {
|
|
|
+ _TIMEOUT.ReadIntervalTimeout = dwReadIntervalTimeout;
|
|
|
+ _TIMEOUT.ReadTotalTimeoutMultiplier = dwReadTotalTimeoutMultiplier;
|
|
|
+ _TIMEOUT.ReadTotalTimeoutConstant = dwReadTotalTimeoutConstant;
|
|
|
+ return IsOpen() ? ::SetCommTimeouts(_hPort, &_TIMEOUT) == TRUE : false;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool CSerial::SetBufferSize(DWORD dwInputSize, DWORD dwOutputSize)
|
|
|
+ {
|
|
|
+ // SetupComm设置输入输出缓冲区大小;
|
|
|
+ return IsOpen() ? ::SetupComm(_hPort, dwInputSize, dwOutputSize) == TRUE : false;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool CSerial::SetDTR(BOOL bEnable/* =TRUE */)
|
|
|
+ {
|
|
|
+ return IsOpen() ? EscapeCommFunction(_hPort, bEnable ? SETDTR : CLRDTR) : false;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool CSerial::SetRTS(BOOL bEnable/* =TRUE */)
|
|
|
+ {
|
|
|
+ return IsOpen() ? EscapeCommFunction(_hPort, bEnable ? SETDTR : CLRDTR) : false;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool CSerial::SetX(BOOL bON/* =TRUE */)
|
|
|
+ {
|
|
|
+ return IsOpen() ? EscapeCommFunction(_hPort, bON ? SETXON : SETXOFF) : false;
|
|
|
+ }
|
|
|
+};
|