📄 serialport.cpp
字号:
#include "StdAfx.h"
#include ".\serialport.h"
CSerialPort::CSerialPort(void)
{
m_hComm = INVALID_HANDLE_VALUE;
// m_hWriteThread = NULL;
m_hWatchThread = NULL;
m_fOpen = FALSE;
SetDCB();
SetTimeouts();
InitializeCriticalSection(&m_CriticalSection);
m_osWrite.Offset = 0;
m_osWrite.OffsetHigh = 0;
m_osWrite.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
m_osRead.Offset = 0;
m_osRead.OffsetHigh = 0;
m_osRead.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
}
CSerialPort::~CSerialPort(void)
{
Close();
DeleteCriticalSection(&m_CriticalSection);
CloseHandle(m_osWrite.hEvent);
CloseHandle(m_osRead.hEvent);
}
// property inquire
BOOL CSerialPort::IsOpen(void)
{
return m_fOpen;
}
// port process
BOOL CSerialPort::Open(DWORD dwComPort,DWORD dwBaudrate,BYTE bByteBits,BYTE bStopBits,BYTE bParity)
{
TCHAR szComName[20];
DWORD dwResult = TRUE;
DWORD dwID;
Close();
wsprintf(szComName,"COM%d",dwComPort+1);
m_hComm = CreateFile(szComName,
GENERIC_READ|GENERIC_WRITE,0,NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,NULL);
if (INVALID_HANDLE_VALUE != m_hComm)
{
SetDCB(dwBaudrate,bByteBits,bStopBits,bParity);
if (FALSE != SetupConnect())
{
m_hWatchThread = CreateThread(NULL,0,WatchThreadProc,this,0,&dwID);
if (NULL != m_hWatchThread)
{
;
}
else
{
CloseHandle(m_hComm);
dwResult = FALSE;
}
}
else // setup port property error
{
CloseHandle(m_hComm);
dwResult = FALSE;
}
} // errror open port
else
{
dwResult = FALSE;
}
m_fOpen = dwResult;
return dwResult;
}
BOOL CSerialPort::Close(void)
{
if (TRUE == m_fOpen)
{
m_fOpen = FALSE;
PurgeComm(m_hComm,PURGE_TXABORT | PURGE_RXABORT);
SetCommMask(m_hComm,EV_RXCHAR | EV_BREAK);
WaitForSingleObject(m_hWatchThread,INFINITE);
CloseHandle(m_hComm);
CloseHandle(m_hWatchThread);
m_hComm = INVALID_HANDLE_VALUE;
m_hWatchThread = NULL;
}
return 0;
}
// set port property
BOOL CSerialPort::SetupConnect()
{
COMSTAT ComStat;
DWORD dwError;
DWORD dwResult1,dwResult2,dwResult3,dwResult4,dwResult5;
dwResult1 = SetCommState(m_hComm,&m_Dcb);
dwResult2 = SetCommTimeouts(m_hComm,&m_CommTimeouts);
dwResult3 = ClearCommError(m_hComm,&dwError,&ComStat);
dwResult4 = SetupComm(m_hComm,1024,1024);
dwResult5 = PurgeComm(m_hComm,PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR);
return dwResult1 && dwResult2 && dwResult3 && dwResult4 && dwResult5;
}
void CSerialPort::SetDCB(DWORD dwBaudrate,BYTE bByteBits,BYTE bStopBits,BYTE bParity)
{
m_Dcb.BaudRate = dwBaudrate;
m_Dcb.ByteSize = bByteBits;
m_Dcb.StopBits = bStopBits;
switch (bParity)
{
case NOPARITY:
m_Dcb.fParity = FALSE;
m_Dcb.Parity = bParity;
break;
case ODDPARITY:
case EVENPARITY:
case MARKPARITY:
case SPACEPARITY:
m_Dcb.fParity = TRUE;
m_Dcb.Parity = bParity;
break;
}
}
void CSerialPort::SetDCB(DCB* pDcb)
{
TCHAR szDef[40] = "baud=9600 parity=N data=8 stop=1";
if (NULL != pDcb)
{
memcpy(&m_Dcb,pDcb,sizeof(m_Dcb));
}
else
{
BuildCommDCB(szDef,&m_Dcb);
m_Dcb.fOutxCtsFlow = FALSE;
m_Dcb.fOutxDsrFlow = FALSE;
m_Dcb.fDsrSensitivity = FALSE;
m_Dcb.fTXContinueOnXoff = FALSE;
m_Dcb.fDtrControl = DTR_CONTROL_ENABLE;
m_Dcb.fRtsControl = RTS_CONTROL_ENABLE;//RTS_CONTROL_TOGGLE;
m_Dcb.fBinary = TRUE;
m_Dcb.XoffLim = 0;
m_Dcb.XonLim = 0;
m_Dcb.XoffChar = 0x13;
m_Dcb.XonChar = 0x11;
m_Dcb.fBinary = TRUE;
m_Dcb.fErrorChar = FALSE;
m_Dcb.fNull = FALSE;
}
}
void CSerialPort::SetTimeouts(COMMTIMEOUTS* pCommTimeouts)
{
if (NULL != pCommTimeouts)
{
memcpy(&m_CommTimeouts,pCommTimeouts,sizeof(m_CommTimeouts));
}
else
{
m_CommTimeouts.ReadIntervalTimeout = 20;
m_CommTimeouts.ReadTotalTimeoutMultiplier = 10;
m_CommTimeouts.ReadTotalTimeoutConstant = 100;
m_CommTimeouts.WriteTotalTimeoutMultiplier = 10;
m_CommTimeouts.WriteTotalTimeoutConstant = 100;
}
}
void CSerialPort::SetFlowControl(DWORD dwDtrControl,DWORD dwRtsControl,
BOOL fOutCtsFlow,BOOL fOutDsrFlow,
BOOL fOutX,BOOL fInX,char cXonChar,char cXoffChar)
{
m_Dcb.fDtrControl = dwDtrControl;
m_Dcb.fRtsControl = dwRtsControl;
m_Dcb.fOutxCtsFlow = fOutCtsFlow;
m_Dcb.fOutxDsrFlow = fOutDsrFlow;
m_Dcb.fOutX = fOutX;
m_Dcb.fInX = fInX;
m_Dcb.XonChar = cXonChar;
m_Dcb.XoffChar = cXoffChar;
}
// communication
BOOL CSerialPort::PortOutput(BYTE* pData,UINT uLen)
{
DWORD dwError;
DWORD dwResult = TRUE;
DWORD dwLen;
if (NULL != m_osWrite.hEvent)
{
EnterCriticalSection(&m_CriticalSection);
ClearCommError(m_hComm,&dwError,NULL);
dwResult = WriteFile(m_hComm,pData,uLen,&dwLen,&m_osWrite);
if (FALSE != dwResult)
{
dwResult = TRUE;
}
else // Written data to port is error or not complete
{
dwResult = GetLastError();
if (dwResult == ERROR_IO_PENDING) // Sent data is pending
{
GetOverlappedResult(m_hComm,&m_osWrite,&dwLen,TRUE);
dwResult = TRUE;
}
else
{
dwResult = FALSE;
}
}
LeaveCriticalSection(&m_CriticalSection);
} // Created evnet handle is error
else
{
dwResult = FALSE;
}
return dwResult;
}
BOOL CSerialPort::PortInput(BYTE* pData,UINT& uLen)
{
DWORD dwError;
COMSTAT cs;
DWORD dwResult = TRUE;
DWORD dwReadLen;
if (NULL != m_osRead.hEvent)
{
EnterCriticalSection(&m_CriticalSection);
ClearCommError(m_hComm,&dwError,&cs);
uLen = uLen < cs.cbInQue ? uLen : cs.cbInQue;
dwResult = ReadFile(m_hComm,pData,uLen,&dwReadLen,&m_osRead);
if (FALSE != dwResult)
{
dwResult = TRUE;
}
else // Written data to port is error or not complete
{
dwResult = GetLastError();
if (ERROR_IO_PENDING == dwResult) // received data is pending
{
GetOverlappedResult(m_hComm,&m_osRead,&dwReadLen,TRUE);
dwResult = TRUE;
}
else
{
dwResult = FALSE;
}
}
LeaveCriticalSection(&m_CriticalSection);
}
else // Created evnet handle is error
{
dwResult = FALSE;
}
return dwResult;
}
// receive buffer using queue
#include <queue>
using namespace std;
queue<BYTE> g_qReceive;
// interface of device
BOOL CSerialPort::Send(BYTE* pData,UINT uLen)
{
return PortOutput(pData,uLen);
}
BOOL CSerialPort::Receive(BYTE* pData,UINT& uLen,DWORD dwMilliSecond)
{
clock_t tStart,tEnd;
UINT uReceiveLen = uLen;
// DWORD dwResult = TRUE;
tEnd = tStart = clock();
while (((tEnd - tStart) * 1000 < dwMilliSecond*CLK_TCK) && (uReceiveLen > 0))
{
tEnd = clock();
Sleep(100);
Receive(pData,uReceiveLen);
pData += uReceiveLen;
uReceiveLen = uLen - uReceiveLen;
}
return uReceiveLen == 0;
}
UINT CSerialPort::GetReceivedLenght()
{
return (UINT)g_qReceive.size();
}
BOOL CSerialPort::Receive(BYTE* pData,UINT& uLen)
{
UINT uRec(0);
DWORD dwResult = TRUE;
while (!g_qReceive.empty() && uLen > uRec)
{
*pData++ = g_qReceive.front();
g_qReceive.pop();
uRec++;
}
dwResult = (uLen == uRec);
uLen = uRec;
return dwResult;
}
// thread of watch input port
DWORD WINAPI CSerialPort::WatchThreadProc(PVOID pParam)
{
CSerialPort* pOwner = (CSerialPort*)pParam;
BYTE* pBuffer = new BYTE[1024];
UINT uLen = 1024;
DWORD dwEvtMask = EV_RXCHAR | EV_BREAK;
SetCommMask(pOwner->m_hComm,dwEvtMask);
while(TRUE == pOwner->IsOpen())
{
// SetCommMask(pOwner->m_hComm,dwEvtMask);
WaitCommEvent(pOwner->m_hComm,&dwEvtMask,NULL);
uLen = 1024;
if (TRUE == pOwner->PortInput(pBuffer,uLen))
{
for (UINT i=0; i<uLen; i++)
{
g_qReceive.push(*(pBuffer+i));
}
}
}
pOwner->m_fOpen = FALSE;
delete []pBuffer;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -