串口通讯类

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;
}

你可能感兴趣的:(串口通讯类)