class CSerialPort
{
private:
HANDLE hComm;
public:
static CSerialPort* GetInstance();
~CSerialPort(void);
bool Open();
bool Close();
bool SndMessage(const unsigned char* buf, int buflen);
bool RcvMessage(unsigned char* buf, int buflen, int& rcvlen);
private:
CSerialPort(void);
static CSerialPort* instance;
};
CSerialPort::CSerialPort(void)
{
hComm = INVALID_HANDLE_VALUE;
}
CSerialPort::~CSerialPort(void)
{
Close();
}
CSerialPort* CSerialPort::instance = new CSerialPort();
CSerialPort* CSerialPort::GetInstance()
{
return instance;
}
bool CSerialPort::Open()
{
hComm = CreateFile(L"COM1:", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hComm == INVALID_HANDLE_VALUE)
{
return false;
}
//set the DCB:Device Control Block
DCB PortDCB;
PortDCB.ByteSize = sizeof(DCB);
//get the default COM state
GetCommState(hComm, &PortDCB);
//set the param of the DCB
PortDCB.BaudRate = 115200; // baud
PortDCB.ByteSize = 8; // Number of bits/byte, 4-8
PortDCB.Parity = 0;
PortDCB.StopBits = 0;
PortDCB.fDtrControl = DTR_CONTROL_DISABLE;
PortDCB.fRtsControl = RTS_CONTROL_DISABLE;
if (!SetCommState(hComm, &PortDCB))
{
return false;
}
//set the timeout of COM1:
COMMTIMEOUTS CommTimeouts;
GetCommTimeouts(hComm, &CommTimeouts);
CommTimeouts.ReadIntervalTimeout = MAXDWORD;
CommTimeouts.ReadTotalTimeoutMultiplier = 10;
CommTimeouts.ReadTotalTimeoutConstant = 10;
CommTimeouts.WriteTotalTimeoutMultiplier = 50;
CommTimeouts.WriteTotalTimeoutConstant = 100;
if (!SetCommTimeouts(hComm, &CommTimeouts))
{
return false;
}
PurgeComm(hComm, PURGE_RXCLEAR | PURGE_RXABORT);
PurgeComm(hComm, PURGE_TXCLEAR | PURGE_TXABORT);
return true;
}
bool CSerialPort::Close()
{
if (hComm == INVALID_HANDLE_VALUE)
{
return true;
}
if (CloseHandle(hComm))
{
hComm = INVALID_HANDLE_VALUE;
return true;
}
else
{
return false;
}
}
InterLock serialSndLock;
bool CSerialPort::SndMessage(const unsigned char* buf, int buflen)
{
AutoLock<InterLock> autoLock(serialSndLock);
if (hComm == INVALID_HANDLE_VALUE)
{
return false;
}
COMSTAT ComStat;
int dwErrorFlags = 0;
PurgeComm(hComm, PURGE_TXCLEAR);
OVERLAPPED ovlCommPort;
bool bWriteResult;
DWORD dwNumBytesWritten = 0;
DWORD dwHaveNumWritten = 0; //已经写入多少
do
{
bWriteResult = WriteFile(hComm, buf, min(buflen - dwHaveNumWritten, 10000), &dwNumBytesWritten, &ovlCommPort);
if (bWriteResult && dwNumBytesWritten == min(buflen - dwHaveNumWritten, 10000))
{
dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten;
//写入完成
if (dwHaveNumWritten == buflen)
{
return true;
}
}
Sleep(5);
} while (true);
return false;
}
InterLock serialRcvLock;
bool CSerialPort::RcvMessage(unsigned char* buf, int buflen, int& rcvlen)
{
AutoLock<InterLock> autoLock(serialRcvLock);
if (hComm == INVALID_HANDLE_VALUE)
{
return false;
}
COMSTAT ComStat;
DWORD dwErrorFlags = 0;
ClearCommError(hComm, &dwErrorFlags, &ComStat);
if (dwErrorFlags != 0)
{
PurgeComm(hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
}
if (ComStat.cbInQue <= 0)
{
return false;
}
OVERLAPPED ovlCommPort;
rcvlen = min(ComStat.cbInQue, buflen);
DWORD BytesRead = 0;
bool bSuccess = ReadFile(hComm, buf, rcvlen, &BytesRead, &ovlCommPort);
if (!bSuccess || BytesRead != rcvlen)
{
return false;
}
return true;
}