#ifndef __SERIAL_H__
#define __SERIAL_H__
//#include "stdafx.h"
#include <windows.h>
#include <iostream>
//#include "mutex.h"
class CSerial
{
public:
CSerial(void);
virtual ~CSerial(void);
public:
BOOL Open(WCHAR *sName, BOOL bOverlapped=FALSE);
void Close(void);
BOOL isValid(void);
public:
int Write(BYTE *pBuf, DWORD nSize);
int Read(BYTE *pBuf, DWORD nSize);
void SetComm(DWORD BaudRate, BYTE ByteSize, BYTE Parity, BYTE StopBits);
void SetTimeOut(DWORD interval, DWORD rdmult, DWORD rdconst, DWORD wrmult, DWORD wrconst);
protected:
void ResetRx(void);
void ResetTx(void);
protected:
HANDLE _hCom;
HANDLE _hRdEvt, _hWrEvt;
BOOL _bOvlap;
};
#endif
//#include "stdafx.h"
#include "Serial.h"
CSerial::CSerial(void)
{
_bOvlap = FALSE;
_hCom = INVALID_HANDLE_VALUE;
_hRdEvt = INVALID_HANDLE_VALUE;
_hWrEvt = INVALID_HANDLE_VALUE;
}
BOOL CSerial::isValid(void)
{
return (_hCom != INVALID_HANDLE_VALUE);
}
CSerial::~CSerial(void)
{
Close();
}
BOOL CSerial::Open(WCHAR *name, BOOL bOverlapped)
{
DWORD flag = 0;
Close();
if(bOverlapped)
{
_bOvlap = TRUE;
flag = FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED;
}
_hCom = ::CreateFile(name, //COM1口
GENERIC_READ|GENERIC_WRITE, //允许读和写
0, //独占方式
NULL,
OPEN_EXISTING, //打开而不是创建
flag, //同步方式
NULL);
if(_hCom == INVALID_HANDLE_VALUE)
return FALSE;
//设置缓冲区大小
::SetupComm(_hCom,1200,1200);
SetComm(115200, 8, NOPARITY, ONESTOPBIT);
//SetTimeOut(MAXDWORD, 80, 10, 100, 500);
SetTimeOut(200, 80, 10, 100, 500);
if(_bOvlap)
{
_hRdEvt = ::CreateEvent(NULL,TRUE,FALSE,TEXT("read"));
_hWrEvt = ::CreateEvent(NULL,TRUE,FALSE,TEXT("write"));
if(_hRdEvt == INVALID_HANDLE_VALUE
|| _hWrEvt == INVALID_HANDLE_VALUE)
{
Close();
return FALSE;
}
}
return TRUE;
}
void CSerial::Close(void)
{
_bOvlap = FALSE;
if(_hCom != INVALID_HANDLE_VALUE)
{
::CloseHandle(_hCom);
_hCom = INVALID_HANDLE_VALUE;
}
if(_hRdEvt != INVALID_HANDLE_VALUE)
{
::CloseHandle(_hRdEvt);
_hRdEvt = INVALID_HANDLE_VALUE;
}
if(_hRdEvt != INVALID_HANDLE_VALUE)
{
::CloseHandle(_hWrEvt);
_hWrEvt = INVALID_HANDLE_VALUE;
}
}
void CSerial::ResetTx(void)
{
if(isValid())
::PurgeComm(_hCom, PURGE_TXABORT|PURGE_TXCLEAR);
}
void CSerial::ResetRx(void)
{
if(isValid())
::PurgeComm(_hCom, PURGE_RXABORT|PURGE_RXCLEAR);
}
void CSerial::SetComm(DWORD BaudRate, BYTE ByteSize, BYTE Parity, BYTE StopBits)
{
DCB dcb;
if(!isValid())
return;
::GetCommState(_hCom, &dcb);
dcb.BaudRate = BaudRate; //波特率为9600
dcb.ByteSize = ByteSize; //每个字节有8位
dcb.Parity = Parity; //无奇偶校验位
dcb.StopBits = StopBits; //两个停止位
::SetCommState(_hCom,&dcb);
ResetTx();
ResetRx();
}
void CSerial::SetTimeOut(DWORD interval, DWORD rdmult, DWORD rdconst, DWORD wrmult, DWORD wrconst)
{
COMMTIMEOUTS TimeOuts;
if(!isValid())
return;
//设定读超时
TimeOuts.ReadIntervalTimeout = interval;//MAXDWORD;
TimeOuts.ReadTotalTimeoutMultiplier = rdmult;//0;
TimeOuts.ReadTotalTimeoutConstant = rdconst;//0;
//设定写超时
TimeOuts.WriteTotalTimeoutMultiplier = wrmult;
TimeOuts.WriteTotalTimeoutConstant = wrconst;
::SetCommTimeouts(_hCom,&TimeOuts); //设置超时
}
/*
BOOL CSerial::WriteIO(BYTE *pBuf, DWORD nSize, DWORD *pWriteCnt, OVERLAPPED *lpOverlapped)
{
COMSTAT ComStat;
DWORD dwErrorFlags;
BOOL bWriteStat;
if(!isValid())
return FALSE;
::ClearCommError(_hCom,&dwErrorFlags,&ComStat);
bWriteStat = ::WriteFile(_hCom, pBuf, nSize, pWriteCnt, lpOverlapped);
return bWriteStat;
}
BOOL CSerial::ReadIO(BYTE *pBuf, DWORD nSize, DWORD *pReadCnt, OVERLAPPED *lpOverlapped)
{
COMSTAT ComStat;
DWORD dwErrorFlags;
BOOL bReadStatus;
if(!isValid())
return FALSE;
::ClearCommError(_hCom, &dwErrorFlags, &ComStat);
//if(!ComStat.cbInQue)
// return 0;
nSize = min(nSize, (DWORD)ComStat.cbInQue);
bReadStatus = ::ReadFile(_hCom, pBuf, nSize, pReadCnt, lpOverlapped);
return bReadStatus;
}
*/
int CSerial::Write(BYTE *pBuf, DWORD nSize)
{
COMSTAT ComStat;
DWORD dwErrorFlags;
DWORD dwBytesWritten;
OVERLAPPED osWrite;
BOOL bWriteStat;
DWORD dwEventStat;
memset(&osWrite, 0, sizeof(OVERLAPPED));
osWrite.hEvent = _hWrEvt;
::ClearCommError(_hCom,&dwErrorFlags,&ComStat);
bWriteStat = ::WriteFile(_hCom, pBuf, nSize, &dwBytesWritten, (_bOvlap ? (&osWrite) : NULL));
if(!bWriteStat)
{
if(_bOvlap && GetLastError()==ERROR_IO_PENDING)
{
do{
dwEventStat = ::WaitForSingleObject(osWrite.hEvent, 200);
}while(isValid() && dwEventStat == WAIT_TIMEOUT);
if(dwEventStat == WAIT_OBJECT_0) //write done.
{
if(::GetOverlappedResult(_hCom, &osWrite, &dwBytesWritten, TRUE))
{
return dwBytesWritten;
}
}
}
//Reset Send Error.
ResetTx();
return 0;
}
return dwBytesWritten;
}
int CSerial::Read(BYTE *pBuf, DWORD nSize)
{
COMSTAT ComStat;
DWORD dwEventStat;
DWORD dwBytesRead;
DWORD dwErrorFlags;
OVERLAPPED osRead;
BOOL bReadStatus;
if(!isValid())
return -1;
memset(&osRead,0,sizeof(OVERLAPPED));
osRead.hEvent = _hRdEvt;
::ClearCommError(_hCom,&dwErrorFlags,&ComStat);
if(!_bOvlap && !ComStat.cbInQue)
return 0;
dwBytesRead = nSize;
if(ComStat.cbInQue)
dwBytesRead = min(nSize, (DWORD)ComStat.cbInQue);
bReadStatus = ::ReadFile(_hCom, pBuf, dwBytesRead, &dwBytesRead, (_bOvlap ? (&osRead) : NULL));
if(!bReadStatus) //如果ReadFile函数返回FALSE
{
if(_bOvlap && GetLastError()==ERROR_IO_PENDING)
{
do{
dwEventStat = ::WaitForSingleObject(osRead.hEvent, 200);
}while(isValid() && dwEventStat == WAIT_TIMEOUT);
if(dwEventStat == WAIT_OBJECT_0) //write done.
{
if(::GetOverlappedResult(_hCom, &osRead, &dwBytesRead, TRUE))
{
return dwBytesRead;
}
}
}
ResetTx();
return 0;
}
return dwBytesRead;
}
Win32串口操作封装
最新推荐文章于 2021-11-15 22:28:58 发布