这里有一些源代码
程序代码:
#pragma once
class CMyCom
{
public:
CMyCom();
~CMyCom();
public:
BOOL IsStart();
unsigned long WriteComm(void const *buff,unsigned long const &dwLen);
unsigned long ReadComm(void *buff,unsigned long const &dwLen);
void SetComParam(DCB const &dcb,CString const &sPort){memcpy(&m_ComDcb,&dcb,sizeof(m_ComDcb));m_sPort = sPort;}
void SetMsgHwnd(HWND const &msghwnd,unsigned const &msgID){m_msghwnd = msghwnd;m_msgID = msgID;}
BOOL Start();
BOOL Stop();
public:
void StartRead();
private:
void Clear();
BOOL CreateRes();
private:
unsigned long const m_nMaxBuff;//串口读写最大的缓冲区设置
struct sMsgHead
{
unsigned long size;//读取到的消息长度
};
void *m_pBuff;//消息内容
HANDLE m_hMutexBuff;
BOOL m_bStart;//是否在连接中
HWND m_msghwnd;//可读时发送的窗口
unsigned m_msgID;//可读是发送的消息
int m_err;
HANDLE m_hCom;//串口句柄;
OVERLAPPED m_osWrite;//写事件等待
OVERLAPPED m_osRead;//读事件等待
CString m_sPort;//串口名字
DCB m_ComDcb;//串口参数
HANDLE m_hThread;//读线程
HANDLE m_ReadEvent;//读线程等待 主线程操作完成
unsigned long m_nNotifyNum; //大于该个数是才发送消息
private:
CMyCom(CMyCom const &it);
CMyCom &operator = (CMyCom const &it);
};
#include <process.h>
CMyCom::CMyCom()
:m_err(0),m_hCom(INVALID_HANDLE_VALUE),m_bStart(false),m_hThread(0),m_ReadEvent(0)
,m_nNotifyNum(0)
,m_nMaxBuff(1024)
,m_hMutexBuff(NULL)
{
memset(&m_osWrite,0,sizeof(m_osWrite));
memset(&m_osRead,0,sizeof(m_osRead));
memset(&m_ComDcb,0,sizeof(m_ComDcb));
m_ComDcb.DCBlength = sizeof(m_ComDcb);
m_pBuff = new char[m_nMaxBuff + sizeof(sMsgHead)];
memset(m_pBuff,0,m_nMaxBuff + sizeof(sMsgHead));
}
CMyCom::~CMyCom()
{
Stop();
Clear();
}
void CMyCom::Clear()
{
if(m_ReadEvent)
{
CloseHandle(m_ReadEvent);
m_ReadEvent = NULL;
}
if(m_osWrite.hEvent)
{
CloseHandle(m_osWrite.hEvent);
m_osWrite.hEvent = NULL;
}
if(m_osRead.hEvent)
{
CloseHandle(m_osRead.hEvent);
m_osRead.hEvent = NULL;
}
if(m_hMutexBuff)
{
CloseHandle(m_hMutexBuff);
m_hMutexBuff = NULL;
}
if(m_pBuff)
{
delete m_pBuff;
m_pBuff = NULL;
}
}
unsigned long CMyCom::WriteComm(void const *buff,unsigned long const &dwLen)
{
if(!IsStart())
{
ASSERT(0);
return 0;
}
if(NULL == buff)
{
ASSERT(0);
return 0;
}
BOOL fstate = FALSE;
COMSTAT ComStat = {0};
DWORD dwErrorFlags = 0;
ClearCommError(m_hCom,&dwErrorFlags,&ComStat);
unsigned long len = dwLen;
fstate = WriteFile(m_hCom,buff,len,&len,&m_osWrite);
if(!fstate)
{
if(ERROR_IO_PENDING == GetLastError())
{
GetOverlappedResult(m_hCom,&m_osWrite,&len,true);
}
else
{
len = 0;
}
}
return len;
}
unsigned long CMyCom::ReadComm(void *buff,unsigned long const &dwLen)
{
if(!IsStart())
{
ASSERT(0);
return 0;
}
if(NULL == buff)
{
ASSERT(0);
return 0;
}
sMsgHead *pHead = (sMsgHead *)m_pBuff;
ASSERT(m_pBuff);
unsigned long len = min(dwLen,pHead->size);
WaitForSingleObject(m_hMutexBuff,INFINITE);
memcpy(buff,(char*)m_pBuff+sizeof(sMsgHead),len);
pHead->size -= len;
if(pHead->size)memcpy((char*)m_pBuff+sizeof(sMsgHead),(char*)m_pBuff+sizeof(sMsgHead)+len,pHead->size);
ReleaseMutex(m_hMutexBuff);
return len;
}
static UINT WINAPI ReadComThread(void *param)
{
// 注意 该线程不能 return STILL_ACTIVE 因为使用了GetExitCodeThread判断线程是否正在运行
CMyCom *dlg = reinterpret_cast<CMyCom*>(param);
if(0==dlg)//不肯能为空
{
ASSERT(0);
return 0;
}
dlg->StartRead();
return 0;
}
void CMyCom::StartRead()
{
OVERLAPPED os = {0};
DWORD dwMark = 0,dwTrans = 0;
COMSTAT ComStat = {0};
DWORD dwErrorFlags = 0;
os.hEvent = m_ReadEvent;
BOOL fstate = FALSE;
unsigned long len = 0;
void* buff = new char[m_nMaxBuff];
sMsgHead *pHead = (sMsgHead *)m_pBuff;
if(0==os.hEvent)//系统资源耗尽
{
ASSERT(0);
return ;
}
while(m_bStart)//主线程要求结束
{
dwMark = 0;
if(!WaitCommEvent(m_hCom,&dwMark,&os))//等待是否有EV_RXCHAR|EV_ERR事件
{
if(ERROR_IO_PENDING==GetLastError())// I/O操作还没完成
{
GetOverlappedResult(m_hCom,&os,&dwTrans,true);//无限等待EV_RXCHAR|EV_ERR
}
else
{
break;
}
}
if(dwMark & EV_ERR) // == EV_ERR
{
ClearCommError(m_hCom, &dwErrorFlags, &ComStat);
}
if(dwMark & EV_RXCHAR) // == EV_RXCHAR //有数据可读
{
ClearCommError(m_hCom, &dwErrorFlags, &ComStat);//取得可读数据个数
if(ComStat.cbInQue)
{
len = ComStat.cbInQue>m_nMaxBuff?m_nMaxBuff:ComStat.cbInQue;
memset(buff,0,len);
fstate = ReadFile(m_hCom,buff,len,&len,&m_osRead);
if(!fstate)
{
if(ERROR_IO_PENDING == GetLastError())
{
GetOverlappedResult(m_hCom,&m_osRead,&len,true);
}
else
{
PurgeComm(m_hCom, PURGE_RXABORT | PURGE_RXCLEAR); /*清除输入缓冲区*/
}
}
if(len)
{
if(pHead->size+len<m_nMaxBuff)
{
WaitForSingleObject(m_hMutexBuff,INFINITE);
memcpy((char*)m_pBuff+sizeof(sMsgHead)+pHead->size,buff,len);
pHead->size += len;
ReleaseMutex(m_hMutexBuff);
}
else
{
TRACE(_T("串口数据爆满\n"));
}
if(m_msghwnd&&pHead->size&&pHead->size>m_nNotifyNum)
{
PostMessage(m_msghwnd,m_msgID,EV_RXCHAR,pHead->size);
}
}
}
}
}
delete[] buff;
}
BOOL CMyCom::CreateRes()
{
if(0==m_osWrite.hEvent)
{
m_osWrite.hEvent = CreateEvent(0,true,0,0);
}
if(0==m_osRead.hEvent)
{
m_osRead.hEvent = CreateEvent(0,true,0,0);
}
if(0==m_ReadEvent)
{
m_ReadEvent = CreateEvent(0,true,0,0);
}
if(0==m_hMutexBuff)
{
m_hMutexBuff = CreateMutex(NULL,FALSE,NULL);
}
if(0==m_pBuff)
{
m_pBuff = new char[m_nMaxBuff + sizeof(sMsgHead)];
}
if(m_pBuff)
{
memset(m_pBuff,0,m_nMaxBuff + sizeof(sMsgHead));
}
return m_osWrite.hEvent&&m_osRead.hEvent&&m_ReadEvent&&m_pBuff&&m_hMutexBuff;
}
BOOL CMyCom::Start()
{
//if(0<IsStart())
{
if(!Stop())
{
return FALSE;
}
}
if(!CreateRes())
{
return FALSE;
}
COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 2000;
BOOL bStart = FALSE;
__try
{
m_hCom = CreateFile(m_sPort,
GENERIC_READ|GENERIC_WRITE, //允许读和写操作
0, //独占方式
NULL,
OPEN_EXISTING, //打开一个存在的串口
FILE_FLAG_OVERLAPPED|FILE_ATTRIBUTE_NORMAL, //启用事件通知
NULL);
if(INVALID_HANDLE_VALUE == m_hCom)__leave;
SetupComm(m_hCom,m_nMaxBuff,m_nMaxBuff);//设置缓冲区大小
if(!SetCommMask(m_hCom,EV_RXCHAR|EV_ERR))__leave; //设置等待事件
if(!SetCommState(m_hCom,&m_ComDcb))__leave;
SetCommTimeouts(m_hCom,&timeouts); //设置等待超时时间
m_bStart = TRUE;
m_hThread = (HANDLE)_beginthreadex(0,0,ReadComThread,this,0,0);
if(m_hThread)
{
bStart = TRUE;
}
}
__finally
{
if(!bStart)//操作失败
{
m_bStart = FALSE;
m_err = GetLastError();
if(m_hThread)
{
CloseHandle(m_hThread);
m_hThread = 0;
}
if(INVALID_HANDLE_VALUE!=m_hCom)
{
CloseHandle(m_hCom);
m_hCom = INVALID_HANDLE_VALUE;
}
}
}
return bStart;
}
BOOL CMyCom::Stop()
{
m_bStart = FALSE;
if(INVALID_HANDLE_VALUE!=m_hCom)PurgeComm(m_hCom, PURGE_RXABORT | PURGE_TXABORT | PURGE_RXABORT | PURGE_RXCLEAR); /*清除输入缓冲区*/
if(0!=m_hThread)
{
SetEvent(m_ReadEvent);
WaitForSingleObject(m_hThread,INFINITE);
CloseHandle(m_hThread);
m_hThread = 0;
}
if(INVALID_HANDLE_VALUE!=m_hCom)
{
CloseHandle(m_hCom);
m_hCom = INVALID_HANDLE_VALUE;
}
return 0==m_hThread && INVALID_HANDLE_VALUE == m_hCom;
}
BOOL CMyCom::IsStart()
{
DWORD dwExitCode = 0;
if(m_hThread)
{
GetExitCodeThread(m_hThread,&dwExitCode);
}
return 0<m_hThread && m_bStart && 0<m_hCom && STILL_ACTIVE == dwExitCode;
}