<Header File>
#ifndef __SERIALPORTTOOL_H__
#define __SERIALPORTTOOL_H__
#define WM_COMM_BREAK_DETECTED WM_USER+1
#define WM_COMM_CTS_DETECTED WM_USER+2
#define WM_COMM_DSR_DETECTED WM_USER+3
#define WM_COMM_ERR_DETECTED WM_USER+4
#define WM_COMM_RING_DETECTED WM_USER+5
#define WM_COMM_RLSD_DETECTED WM_USER+6
#define WM_COMM_RXCHAR WM_USER+7
#define WM_COMM_RXFLAG_DETECTED WM_USER+8
#define WM_COMM_TXEMPTY_DETECTED WM_USER+9
class CSerialPort
{
public:
CSerialPort();
virtual ~CSerialPort();
BOOL InitPort(CWnd* pPortOwner,UINT portnr=1,UINT baud=57600,char parity='N',
UINT databits=8,UINT stopbits=1,DWORD dwCommEvents=EV_RXCHAR|EV_CTS,
UINT nBufferSize=2048);
BOOL StartMonitoring();
BOOL RestartMonitoring();
BOOL StopMonitoring();
DWORD GetWriteBufferSize();
DWORD GetCommEvents();
DCB GetDCB();
void WriteToPort(unsigned char* string);
void WriteToPort(unsigned char* string,int n);
void WriteToPort(LPCTSTR string);
void WriteToPort(LPCTSTR string,int n);
UINT m_nWriteSize;
protected:
void ProcessErrorMessage(char* ErrorText);
static UINT CommThread(LPVOID pParam);
static void ReceiveChar(CSerialPort* port,COMSTAT comstat);
static void WriteChar(CSerialPort* port);
//thread
CWinThread* m_Thread;
//synchronisation objects
CRITICAL_SECTION m_csCommunicationSync;
BOOL m_bThreadAlive;
//handles
HANDLE m_hShutdownEvent;
HANDLE m_hComm;
HANDLE m_hWriteEvent;
HANDLE m_hEventArray[3];
//structures
OVERLAPPED m_ov;
COMMTIMEOUTS m_CommTimeOuts;
DCB m_dcb;
//owner window
CWnd* m_pOwner;
//misc
UINT m_nPortNr;
unsigned char* m_szWriteBuffer;
DWORD m_dwCommEvents;
DWORD m_nWriteBufferSize;
};
#endif __SERIALPORTTOOL_H__
</Header File>
<Source File>
#include "stdafx.h"
#include "SerialPortTool.h"
#include <assert.h>
//Constructor
CSerialPort::CSerialPort()
{
m_hComm=NULL;
m_Thread = NULL;
m_ov.Offset=0;
m_ov.OffsetHigh=0;
m_ov.hEvent=NULL;
m_hWriteEvent=NULL;
m_hShutdownEvent=NULL;
m_szWriteBuffer=NULL;
m_bThreadAlive=FALSE;
m_nWriteSize =0;
//handles
m_hShutdownEvent=NULL;
m_hComm=NULL;
m_hWriteEvent=NULL;
m_nPortNr=0;
m_szWriteBuffer=NULL;
//m_dwCommEvents=0xffffffff;
//m_nWriteBufferSize=0xffffffff;
}
CSerialPort::~CSerialPort()
{
do
{
SetEvent(m_hShutdownEvent);
}while(m_bThreadAlive);
if(m_hComm!=NULL)
{
CloseHandle(m_hComm);
m_hComm=NULL;
}
if(m_hShutdownEvent!=NULL)
CloseHandle(m_hShutdownEvent);
if(m_ov.hEvent=!NULL)
CloseHandle(m_ov.hEvent);
if(m_hWriteEvent!=NULL)
CloseHandle(m_hWriteEvent);
TRACE("Thread ended/n");
delete [] m_szWriteBuffer;
}
BOOL CSerialPort::InitPort(CWnd* pPortOwner,
UINT portnr,
UINT baud,
char parity,
UINT databits,
UINT stopbits,
DWORD dwCommEvents,
UINT writebuffersize)
{
// assert(portnr>0 && portnr<5);
// assert(pPortOwner!=NULL);
//if the thread is alive :kill
if(m_bThreadAlive)
{
do
{
SetEvent(m_hShutdownEvent);
}while(m_bThreadAlive);
//TRACE("Thread ended/n");
}
//create events
if(m_ov.hEvent!=NULL)
ResetEvent(m_ov.hEvent);
else
m_ov.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(m_hWriteEvent!=NULL)
ResetEvent(m_hWriteEvent);
else
m_hWriteEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(m_hShutdownEvent!=NULL)
ResetEvent(m_hShutdownEvent);
else
m_hShutdownEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
m_hEventArray[0]=m_hShutdownEvent;
m_hEventArray[1]=m_ov.hEvent;
m_hEventArray[2]=m_hWriteEvent;
//initialize critical section
InitializeCriticalSection(&m_csCommunicationSync);
//set buffersize for writing and save the owner
m_pOwner=pPortOwner;
if(m_szWriteBuffer!=NULL)
delete [] m_szWriteBuffer;
m_szWriteBuffer=new unsigned char[writebuffersize];
m_nPortNr=portnr;
m_nWriteBufferSize=writebuffersize;
m_dwCommEvents=dwCommEvents;
BOOL bResult=FALSE;
char *szPort=new char[50];
char *szBaud=new char[50];
//now it critical!
EnterCriticalSection(&m_csCommunicationSync);
//if the port is already opened:close it
if(m_hComm!=NULL)
{
CloseHandle(m_hComm);
m_hComm=NULL;
}
//prepare port strings
sprintf(szPort,"COM%d",portnr);
sprintf(szBaud,"baud=%d parity=%c data=%d stop=%d",baud,parity,databits,stopbits);
//get handle to the port
m_hComm=CreateFile(szPort,
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if(m_hComm==INVALID_HANDLE_VALUE)
{
delete [] szPort;
delete [] szBaud;
return FALSE;
}
//set the timeout values
m_CommTimeOuts.ReadIntervalTimeout=1000;
m_CommTimeOuts.ReadTotalTimeoutConstant=1000;
m_CommTimeOuts.ReadTotalTimeoutMultiplier=1000;
m_CommTimeOuts.WriteTotalTimeoutConstant=1000;
m_CommTimeOuts.WriteTotalTimeoutMultiplier=1000;
//configure
/* SetCommTimeouts(m_hComm,&m_CommTimeOuts);
SetCommMask(m_hComm,dwCommEvents);
GetCommState(m_hComm,&m_dcb);
m_dcb.fRtsControl=RTS_CONTROL_ENABLE;
BuildCommDCB(szBaud,&m_dcb);
SetCommState(m_hComm,&m_dcb);
*/
if(SetCommTimeouts(m_hComm,&m_CommTimeOuts))
{
if(SetCommMask(m_hComm,dwCommEvents))
{
if(GetCommState(m_hComm,&m_dcb))
{
m_dcb.fRtsControl=RTS_CONTROL_ENABLE;//set RTS bit high
if(BuildCommDCB(szBaud,&m_dcb))
{
if(SetCommState(m_hComm,&m_dcb))
;
else
ProcessErrorMessage("SetCommState()");
}
else
ProcessErrorMessage("BuildCommDCB()");
}
else
ProcessErrorMessage("GetCommState()");
}
else
ProcessErrorMessage("SetCommMask()");
}
else
ProcessErrorMessage("SetCommTimeouts()");
delete [] szPort;
delete [] szBaud;
//flush the port
PurgeComm(m_hComm,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
//release critical section
LeaveCriticalSection(&m_csCommunicationSync);
TRACE("Initialisation for communicationport %d completed./nUse Startmonitor to communicate./n",portnr);
return TRUE;
}
UINT CSerialPort::CommThread(LPVOID pParam)
{
CSerialPort *port=(CSerialPort*)pParam;
port->m_bThreadAlive=TRUE;
DWORD BytesTransfered=0;
DWORD Event=0;
DWORD CommEvent=0;
DWORD dwError=0;
COMSTAT comstat;
BOOL bResult=TRUE;
if(port->m_hComm)
PurgeComm(port->m_hComm,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
//begin forever loop.
for(;;)
{
bResult=WaitCommEvent(port->m_hComm,&Event,&port->m_ov);
if(!bResult)
{
switch(dwError=GetLastError())
{
case ERROR_IO_PENDING:
{
break;
}
case 87:
{
break;
}
default:
{
port->ProcessErrorMessage("WaitCommEvent()");
break;
}
}
}
else
{
bResult=ClearCommError(port->m_hComm,&dwError,&comstat);
if(comstat.cbInQue==0)
continue;
}
Event=WaitForMultipleObjects(3,port->m_hEventArray,FALSE,INFINITE);
switch(Event)
{
case 0:
{
port->m_bThreadAlive=FALSE;
AfxEndThread(100);
break;
}
case 1:
{
GetCommMask(port->m_hComm,&CommEvent);
/*if(CommEvent&EV_CTS)
::SendMessage(port->m_pOwner->m_hWnd,WM_COMM_CTS_DETECTED,(WPARAM)0,(LPARAM)port->m_nPortNr);
if(CommEvent&EV_RXFLAG)
::SendMessage(port->m_pOwner->m_hWnd,WM_COMM_RXFLAG_DETECTED,(WPARAM)0,(LPARAM)port->m_nPortNr);
if(CommEvent&EV_BREAK)
::SendMessage(port->m_pOwner->m_hWnd,WM_COMM_BREAK_DETECTED,(WPARAM)0,(LPARAM)port->m_nPortNr);
if(CommEvent&EV_ERR)
::SendMessage(port->m_pOwner->m_hWnd,WM_COMM_ERR_DETECTED,(WPARAM)0,(LPARAM)port->m_nPortNr);
if(CommEvent&EV_RING)
::SendMessage(port->m_pOwner->m_hWnd,WM_COMM_RING_DETECTED,(WPARAM)0,(LPARAM)port->m_nPortNr);
*/
if(CommEvent&EV_RXFLAG)
::SendMessage(port->m_pOwner->m_hWnd,WM_COMM_RXFLAG_DETECTED,(WPARAM)0,(LPARAM)port->m_nPortNr);
if(CommEvent&EV_RXCHAR)
ReceiveChar(port,comstat);
break;
}
case 2:
{
WriteChar(port);
break;
}
}
}
return 0;
}
BOOL CSerialPort::StartMonitoring()
{
if(!(m_Thread=AfxBeginThread(CommThread,this)))
return FALSE;
m_Thread->SetThreadPriority(THREAD_PRIORITY_TIME_CRITICAL);
//TRACE("Thread started/n");
return TRUE;
}
BOOL CSerialPort::RestartMonitoring()
{
TRACE("Thread resumed/n");
m_Thread->ResumeThread();
return TRUE;
}
BOOL CSerialPort::StopMonitoring()
{
TRACE("Thread suspended/n");
m_Thread->SuspendThread();
return TRUE;
}
void CSerialPort::ProcessErrorMessage(char* ErrorText)
{
char *temp=new char[200];
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
(LPTSTR)& lpMsgBuf,
0,
NULL
);
sprintf(temp,"WARNING:%s Failed with the following error:/n%s/nPort:%d/n",
(char*)ErrorText,lpMsgBuf,m_nPortNr);
MessageBox(NULL,temp,"Application Error",MB_ICONSTOP);
LocalFree(lpMsgBuf);
if(temp)
delete [] temp;
return;
}
void CSerialPort::WriteChar(CSerialPort* port)
{
BOOL bWrite =TRUE;
BOOL bResult=TRUE;
DWORD BytesSent=0;
ResetEvent(port->m_hWriteEvent);
EnterCriticalSection(&port->m_csCommunicationSync);
if(bWrite)
{
port->m_ov.Offset=0;
port->m_ov.OffsetHigh=0;
PurgeComm(port->m_hComm,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
bResult=WriteFile(port->m_hComm,
port->m_szWriteBuffer,
// strlen((char*)port->m_szWriteBuffer),
port->m_nWriteSize,
&BytesSent,
&port->m_ov);
if(!bResult)
{
DWORD dwError=GetLastError();
switch(dwError)
{
case ERROR_IO_PENDING:
{
BytesSent=0;
bWrite=FALSE;
break;
}
default:
{
port->ProcessErrorMessage("WriteFile()");
}
}
}
else
{
LeaveCriticalSection(&port->m_csCommunicationSync);
}
}
if(!bWrite)
{
bWrite=TRUE;
bResult=GetOverlappedResult(port->m_hComm,
&port->m_ov,
&BytesSent,
TRUE);
if(!bResult)
{
port->ProcessErrorMessage("GetOverlappedResults() in WriteFile()");
}
}
//if(BytesSent!=strlen((char*)port->m_szWriteBuffer))
if(BytesSent!=port->m_nWriteSize)
{
TRACE("WARNING:WriteFile() error..Bytes Sent:%d; Message Length: %d/n",BytesSent,strlen((char*)port->m_szWriteBuffer));
}
return;
}
void CSerialPort::ReceiveChar(CSerialPort* port,COMSTAT comstat)
{
BOOL bRead=TRUE;
BOOL bResult=TRUE;
DWORD dwError=0;
DWORD BytesRead=0;
unsigned char RXBuff;
for(;;)
{
EnterCriticalSection(&port->m_csCommunicationSync);
bResult=ClearCommError(port->m_hComm,&dwError,&comstat);
LeaveCriticalSection(&port->m_csCommunicationSync);
if(comstat.cbInQue==0)
{
break;
}
EnterCriticalSection(&port->m_csCommunicationSync);
if(bRead)
{
bResult=ReadFile(port->m_hComm,
&RXBuff,
1,
&BytesRead,
&port->m_ov);
if(!bResult)
{
switch(dwError=GetLastError())
{
case ERROR_IO_PENDING:
{
bRead=FALSE;
break;
}
default:
{
port->ProcessErrorMessage("ReadFile()");
break;
}
}
}
else
{
bRead=TRUE;
}
}
if(!bRead)
{
bRead=TRUE;
bResult=GetOverlappedResult(port->m_hComm,
&port->m_ov,
&BytesRead,
TRUE);
/* if(!bResult)
{
port->ProcessErrorMessage("GetOverlappedResult() in ReadFile()");
}*/
}
LeaveCriticalSection(&port->m_csCommunicationSync);
::SendMessage((port->m_pOwner)->m_hWnd,WM_COMM_RXCHAR,(WPARAM)RXBuff,(LPARAM)port->m_nPortNr);
}
return;
}
void CSerialPort::WriteToPort(unsigned char* string)
{
assert(m_hComm!=0);
memset(m_szWriteBuffer,0,sizeof(m_szWriteBuffer));
memcpy(m_szWriteBuffer,string,1);
m_nWriteSize=1;
SetEvent(m_hWriteEvent);
return;
}
void CSerialPort::WriteToPort(unsigned char* string,int n)
{
assert(m_hComm!=0);
memset(m_szWriteBuffer,0,sizeof(m_szWriteBuffer));
memcpy(m_szWriteBuffer,string,n);
m_nWriteSize=n;
SetEvent(m_hWriteEvent);
return;
}
void CSerialPort::WriteToPort(LPCTSTR string)
{
assert(m_hComm!=0);
memset(m_szWriteBuffer,0,sizeof(m_szWriteBuffer));
memcpy(m_szWriteBuffer,string,1);
m_nWriteSize=1;
SetEvent(m_hWriteEvent);
return;
}
void CSerialPort::WriteToPort(LPCTSTR string,int n)
{
assert(m_hComm!=0);
memset(m_szWriteBuffer,0,sizeof(m_szWriteBuffer));
memcpy(m_szWriteBuffer,string,n);
m_nWriteSize=n;
SetEvent(m_hWriteEvent);
return;
}
DCB CSerialPort::GetDCB()
{
return m_dcb;
}
DWORD CSerialPort::GetCommEvents()
{
return m_dwCommEvents;
}
DWORD CSerialPort::GetWriteBufferSize()
{
return m_nWriteBufferSize;
}
</Source File>
正所谓:多情不义易自闭,路边的野花别乱采;飘然牡丹花下死,化作春泥更护花!实在是字字猪鸡(珠玑)啊!
另附狼酒CCTB,我最喜欢的冷笑话一则,说:计划生育部长下乡普查,问老农:你知道近亲为什么不能结婚吗?老农憨厚地笑答:呵呵……太熟了,不好意思下手。
警:这里有人就要问了,什么是CCTB?既然你诚心诚意的请教我,那我就大发慈悲的告诉你:C(姓)C(名)T(特别)B(变态)
转载自原文链接, 如需删除请联系管理员。
原文链接:串口类CSerialPort(2010-03-05),转载请注明来源!