📄 sh_serial.cpp
字号:
// Serial.cpp: implementation of the SH_Serial class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "SH_Serial.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#include "SH_List.h"
static UINT SH_SerialTimerID = 0;
static SH_List<SH_Serial *> SH_SerialList;
static VOID CALLBACK SH_SerialTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
{
SH_Position pos;
SH_Serial * pSerial;
pos = SH_SerialList.GetHeadPosition();
while(pos)
{
pSerial = (SH_Serial*)SH_SerialList.GetNext(pos);
if(pSerial && pSerial->IsOpen())
{
pSerial->RRecv();
if(pSerial->GetBufferLength() > 0)
pSerial->OnRead();
else
pSerial->OnIdle();
}
}
}
//////////////////////////////////////////////////////////////////////
// SH_Serial Construction/Destruction
//////////////////////////////////////////////////////////////////////
VOID SH_Serial::Initialize()
{
if(SH_SerialTimerID)
return;
SH_SerialTimerID = ::SetTimer(NULL,0x01,100,SH_SerialTimerProc);
SH_SerialList.RemoveAll();
}
VOID SH_Serial::Uninitialize()
{
if(SH_SerialTimerID)
{
::KillTimer(NULL,SH_SerialTimerID);
SH_SerialTimerID = 0;
}
}
VOID SH_Serial::AddToQueue()
{
SH_Position pos;
SH_Serial * pSerial;
pos = SH_SerialList.GetHeadPosition();
while(pos)
{
pSerial = SH_SerialList.GetNext(pos);
if(pSerial == this && pSerial->GetPort() == GetPort())
return;
}
SH_SerialList.AddTail(this);
}
VOID SH_Serial::RemoveFromQueue()
{
SH_Position oldpos,pos;
SH_Serial * pSerial;
pos = SH_SerialList.GetHeadPosition();
while(pos)
{
oldpos = pos;
pSerial = SH_SerialList.GetNext(pos);
if(pSerial == this && pSerial->GetPort() == GetPort())
{
SH_SerialList.RemoveAt(oldpos);
return;
}
}
}
SH_Serial::SH_Serial()
{
Initialize();
m_hSerial = INVALID_HANDLE_VALUE;
memset(&m_RO,0,sizeof(OVERLAPPED));
memset(&m_SO,0,sizeof(OVERLAPPED));
m_RO.hEvent = CreateEvent(NULL, true, false, NULL);
m_SO.hEvent = CreateEvent(NULL, true, false, NULL);
m_pBuffer = NULL;
}
VOID SH_Serial::Default(UINT uPort,DWORD dwBaud,BYTE btByteSize,char chParity,BYTE btStopBit,int nBufSiz)
{
m_nPort = uPort;
m_dwBaudRate = dwBaud;
m_btStopBit = btStopBit;
m_chParify = chParity;
m_btByteSize = btByteSize;
if(m_pBuffer == NULL)
{
m_pBuffer = new SH_Buffer(nBufSiz);
ASSERT(m_pBuffer != NULL);
}
}
LPCTSTR SH_Serial::MakeDef()
{
static CString strDef;
strDef.Format("baud=%d parity=%c data=%d stop=%d",
m_dwBaudRate,
m_chParify,
m_btByteSize,
m_btStopBit);
return strDef;
}
SH_Serial::~SH_Serial()
{
Close();
if(m_RO.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(m_RO.hEvent);
if(m_SO.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(m_SO.hEvent);
SAFE_DELETE(m_pBuffer);
if(SH_SerialList.GetCount() == 0)
{
Uninitialize();
}
}
BOOL SH_Serial::Open(UINT uPort,DWORD dwBaud/*=9600*/,BYTE btByteSize/*=8*/,char chParity/*=*'N'*/,BYTE btStopBit/*=1*/,int nBufSiz/*=4096*/)
{
CString strCom,strDef;
if(IsOpen())
{
TRACE("ERROR:Port %d has already open\n",uPort);
return FALSE;
}
Default(uPort,dwBaud,btByteSize,chParity,btStopBit,nBufSiz);
strCom.Format("\\.\\COM%d",m_nPort);
m_hSerial = CreateFile(
strCom,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
NULL
);
if(m_hSerial == INVALID_HANDLE_VALUE)
goto SERIAL_OPEN_FAIL;
if(!SetupComm(m_hSerial, 4096, 4096))
goto SERIAL_OPEN_FAIL;
if(!GetCommState(m_hSerial, &m_DCB))
goto SERIAL_OPEN_FAIL;
strDef = MakeDef();
if(!BuildCommDCB(strDef,&m_DCB))
goto SERIAL_OPEN_FAIL;
if(!SetCommState(m_hSerial, &m_DCB))
goto SERIAL_OPEN_FAIL;
if(!PurgeComm(m_hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ))
goto SERIAL_OPEN_FAIL;
AddToQueue();
return TRUE;
SERIAL_OPEN_FAIL:
Close();
TRACE("Comm Port Open Failed.Error no is %d\n",GetLastError());
return FALSE;
}
BOOL SH_Serial::IsOpen()
{
return (m_hSerial != INVALID_HANDLE_VALUE);
}
VOID SH_Serial::Close()
{
if(m_hSerial != INVALID_HANDLE_VALUE)
{
RemoveFromQueue();
CloseHandle(m_hSerial);
m_hSerial = INVALID_HANDLE_VALUE;
}
}
int SH_Serial::RRecv()
{
int len;
char pBuffer[4096];
len = RRecv(pBuffer,sizeof(pBuffer));
if(len >0 && m_pBuffer)
{
len = m_pBuffer->Write(pBuffer,len);
}
return len;
}
int SH_Serial::RRecv(char * pBuffer, int nBufLen)
{
COMSTAT stat;
DWORD error;
if(!IsOpen())
return 0;
if(ClearCommError(m_hSerial, &error, &stat) && error > 0)
{
PurgeComm(m_hSerial, PURGE_RXABORT | PURGE_RXCLEAR);
return 0;
}
if(stat.cbInQue < 1)
return 0;
unsigned long nRecvLen = 0;
nBufLen = min((int)(nBufLen - 1), (int)stat.cbInQue);
if(!ReadFile(m_hSerial, pBuffer, nBufLen, &nRecvLen, &m_RO))
{
if(GetLastError() == ERROR_IO_PENDING)
{
if(!GetOverlappedResult(m_hSerial, &m_RO, &nRecvLen, FALSE))
{
if(GetLastError() != ERROR_IO_INCOMPLETE)
nRecvLen = 0;
}
}
else
nRecvLen = 0;
}
return (int)nRecvLen;
}
int SH_Serial::RSend(const char * pBuffer, int nBufLen)
{
ULONG uSendLen = 0;
DWORD error;
COMSTAT stat;
if(!IsOpen())
return 0;
if(ClearCommError(m_hSerial, &error, &stat) && error > 0)
PurgeComm(m_hSerial, PURGE_TXABORT | PURGE_TXCLEAR);
if(!WriteFile(m_hSerial, pBuffer, nBufLen, &uSendLen, &m_SO))
{
if( GetLastError() != ERROR_IO_PENDING)
{
uSendLen = 0;
}
else
{
/*Wait for transfer complete*/
if(!GetOverlappedResult(m_hSerial,&m_SO,&uSendLen,TRUE))
{
TRACE("Send data failed\n");
uSendLen = 0;
}
}
}
return (int)uSendLen;
}
int SH_Serial::Read(char * pBuffer,int nBufLen)
{
return (int)(m_pBuffer?m_pBuffer->Read(pBuffer,nBufLen):0);
}
int SH_Serial::PseudoRead(char * pBuffer,int nBufLen)
{
return (int)(m_pBuffer?m_pBuffer->PseudoRead(pBuffer,nBufLen):0);
}
int SH_Serial::GetBufferLength()
{
return (int)(m_pBuffer?m_pBuffer->GetLength():0);
}
int SH_Serial::Write(const char * pBuffer,int nBufLen)
{
return (int)RSend(pBuffer,nBufLen);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -