![]() |
#2
ml2325282012-09-12 17:06
这里有一些源代码
![]() #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; } |
网上的例子,就是读取不到数据 ,请高手指点,谢谢!!!!
void CRS485CommDlg::OnReceive()
{
OVERLAPPED m_osRead;
memset(&m_osRead,0,sizeof(OVERLAPPED));
m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
COMSTAT ComStat;
DWORD dwErrorFlags;
char str[100];
memset(str,'\0',100);
DWORD dwBytesRead=100;//读取的字节数
BOOL bReadStat;
ClearCommError(hCom,&dwErrorFlags,&ComStat);
dwBytesRead = min(dwBytesRead, (DWORD)ComStat.cbInQue);
bReadStat = ReadFile(hCom,str,dwBytesRead,&dwBytesRead,&m_osRead);
if(!bReadStat)
{
if(GetLastError()==ERROR_IO_PENDING)
{
WaitForSingleObject(m_osRead.hEvent, 2000);
}
}
PurgeComm(hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
m_disp = str;
UpdateData(FALSE);
}