📄 serialprot.cpp
字号:
// Comm.cpp: implementation of the CSerialPort class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "../HSDPA.h"
#include "../HSDPADlg.h"
#include "SerialPort.h"
#include "../resource.h"
#include "../Ds.h"
#include "Winioctl.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
void AfxErrorMsg(DWORD dwError)
{
CString str;
str.Format(_T("%d"), dwError);
AfxMessageBox(str);
}
#ifdef _DEBUG
struct {
char snd[512];
char rcv[512];
} gStAtMsg;
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSerialPort::CSerialPort()
{
//数据成员初始化
m_hComm = NULL;
m_ReadThread = NULL;
m_WriteThread = NULL;
m_DetectThread = NULL;
m_ReadThread = NULL;
m_bOverlapped = FALSE;
m_bIsConnect = FALSE;
m_dwEvtMask = 0;
m_SerialState = SERIAL_STATE_INI;
memset(&m_ReadOvlp,0,sizeof(OVERLAPPED));
memset(&m_WriteOvlp,0,sizeof(OVERLAPPED));
memset(&m_WaitOvlp,0,sizeof(OVERLAPPED));
memset(&m_IoCtrlOvlp,0,sizeof(OVERLAPPED));
#ifdef FEATURE_SERIAL_ASYNWRITE
for(int i = 0; i < SERAIL_EVENTARRAYNUM; i++)
{
m_hEventArray[i] = NULL;
}
//创建自动重置事件
m_hWriteEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
m_hIoCtrlEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
m_hCloseWriteEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
m_hEventArray[SERAIL_WRITEEVENT] = m_hWriteEvent;
m_hEventArray[SERAIL_IOCTRLEVENT] = m_hIoCtrlEvent;
m_hEventArray[SERAIL_CLOSEEVENT] = m_hCloseWriteEvent;
#endif
#ifndef FEATURE_SERIAL_QUEUE
InitializeCriticalSection(&m_csRxQueue);
#ifdef FEATURE_SERIAL_ASYNWRITE
InitializeCriticalSection(&m_csTxBuff);
#endif
#endif
}
CSerialPort::~CSerialPort()
{
StopPort();
#ifdef FEATURE_SERIAL_ASYNWRITE
for(int i = 0; i < SERAIL_EVENTARRAYNUM; i++)
{
if(m_hEventArray[i] != NULL)
::CloseHandle(m_hEventArray[i]);
}
#endif
#ifndef FEATURE_SERIAL_QUEUE
DeleteCriticalSection(&m_csRxQueue);
#ifdef FEATURE_SERIAL_ASYNWRITE
DeleteCriticalSection(&m_csTxBuff);
#endif
#endif
}
BOOL CSerialPort::Open(LPCTSTR lpszCommName, BOOL bOverlapped)
{
// Check if the port isn't already opened
ASSERT(!IsOpen());
m_bOverlapped = bOverlapped;
m_hComm = ::CreateFile(lpszCommName,
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
bOverlapped ? FILE_FLAG_OVERLAPPED : 0,
NULL);
if(m_hComm == INVALID_HANDLE_VALUE)
{
m_hComm = NULL;
m_bOverlapped = FALSE;
return FALSE;
}
return TRUE;
}
void CSerialPort::Close()
{
if(IsOpen())
{
m_bIsConnect = FALSE;
SetCommMask(m_hComm,0);
EscapeCommFunction(m_hComm,CLRDTR);
Purge(PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
::CloseHandle(m_hComm);
m_hComm = NULL;
m_bOverlapped = FALSE;
}
Sleep(100);
}
inline BOOL CSerialPort::IsOpen() const
{
return (m_hComm != NULL);
}
inline HANDLE CSerialPort::GetCommHandle() const
{
return m_hComm;
}
DWORD CSerialPort::GetLastError() const
{
return ::GetLastError();
}
//直接从串口读数据
DWORD CSerialPort::Read(LPVOID lpBuffer, DWORD dwToRead, DWORD dwTimeout)
{
ASSERT(IsOpen());
DWORD dwRead = 0;
//同步读
if(!m_bOverlapped)
{
// Read the data
if(!::ReadFile(m_hComm, lpBuffer, dwToRead, &dwRead, 0))
dwRead = 0;
}
else //异步读
{
// Wait for the event to happen
memset(&m_ReadOvlp,0,sizeof(OVERLAPPED));
m_ReadOvlp.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
// Write the data
if(!::ReadFile(m_hComm, lpBuffer, dwToRead, &dwRead, &m_ReadOvlp))
{
m_dwLastError = ::GetLastError();
// Overlapped operation in progress is not an actual error
if(m_dwLastError == ERROR_HANDLE_EOF)
NULL;
else if(m_dwLastError != ERROR_IO_PENDING)
dwRead = 0;
else
{
// Wait for the overlapped operation to complete
switch(::WaitForSingleObject(m_ReadOvlp.hEvent, dwTimeout))
{
case WAIT_OBJECT_0:
// The overlapped operation has completed
if(!::GetOverlappedResult(m_hComm, &m_ReadOvlp, &dwRead, FALSE))
{
if(::GetLastError() != ERROR_HANDLE_EOF)
dwRead = 0;
}
break;
case WAIT_TIMEOUT:
// Cancel the I/O operation
::CancelIo(m_hComm);
default:
dwRead = 0;
}
}
}
::CloseHandle(m_ReadOvlp.hEvent);
}
return dwRead;
}
//直接向串口写数据
DWORD CSerialPort::Write(LPCVOID lpBuffer, DWORD dwToWrite, DWORD dwTimeout)
{
ASSERT(IsOpen());
DWORD dwWrite = 0;
//同步写
if(!m_bOverlapped)
{
// Write the data
if(!::WriteFile(m_hComm, lpBuffer, dwToWrite, &dwWrite, 0))
dwWrite = 0;
}
else //异步写
{
// Wait for the event to happen
memset(&m_WriteOvlp,0,sizeof(OVERLAPPED));
m_WriteOvlp.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
// Write the data
if(!::WriteFile(m_hComm, lpBuffer, dwToWrite, &dwWrite, &m_WriteOvlp))
{
// Overlapped operation in progress is not an actual error
if(::GetLastError() != ERROR_IO_PENDING)
dwWrite = 0;
else
{
// Wait for the overlapped operation to complete
switch(::WaitForSingleObject(m_WriteOvlp.hEvent, dwTimeout))
{
case WAIT_OBJECT_0:
// The overlapped operation has completed
if(!::GetOverlappedResult(m_hComm, &m_WriteOvlp, &dwWrite, FALSE))
dwWrite = 0;
break;
case WAIT_TIMEOUT:
// Cancel the I/O operation
::CancelIo(m_hComm);
default:
dwWrite = 0;
}
}
}
::CloseHandle(m_WriteOvlp.hEvent);
}
return dwWrite;
}
BOOL CSerialPort::WaitEvent(DWORD dwTimeout)
{
ASSERT(IsOpen());
m_dwEvtMask = 0;
BOOL bRet = FALSE;
DWORD dwTrans;
// Wait for the COM event
if(!m_bOverlapped) //同步
{
if(!::WaitCommEvent(m_hComm, LPDWORD(&m_dwEvtMask), 0))
bRet = FALSE;
}
else //异步
{
// Wait for the event to happen
memset(&m_WaitOvlp,0,sizeof(OVERLAPPED));
m_WaitOvlp.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
// Wait for the COM event
if(!::WaitCommEvent(m_hComm, LPDWORD(&m_dwEvtMask), &m_WaitOvlp))
{
// Overlapped operation in progress is not an actual error
if(::GetLastError() != ERROR_IO_PENDING)
bRet = FALSE;
else
{
// Wait for the overlapped operation to complete
switch (::WaitForSingleObject(m_WaitOvlp.hEvent,dwTimeout))
{
case WAIT_OBJECT_0:
if(!::GetOverlappedResult(m_hComm, &m_WaitOvlp, &dwTrans, FALSE))
bRet = FALSE;
else
bRet = TRUE;
break;
case WAIT_TIMEOUT:
// Cancel the I/O operation
::CancelIo(m_hComm);
default:
bRet = FALSE;
}
}
}
::CloseHandle(m_WaitOvlp.hEvent);
}
return bRet;
}
BOOL CSerialPort::Purge(DWORD dwFlags)
{
ASSERT(IsOpen());
return ::PurgeComm(m_hComm, dwFlags);
}
BOOL CSerialPort::IoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, DWORD dwTimeout)
{
ASSERT(IsOpen());
BOOL bRet = FALSE;
//同步控制
if(!m_bOverlapped)
{
if(!::DeviceIoControl(m_hComm,
dwIoControlCode,
lpInBuffer,
nInBufferSize,
lpOutBuffer,
nOutBufferSize,
lpBytesReturned,
0))
bRet = FALSE;
}
else //异步控制
{
// Wait for the event to happen
memset(&m_IoCtrlOvlp,0,sizeof(OVERLAPPED));
m_IoCtrlOvlp.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
if(!::DeviceIoControl(m_hComm,
dwIoControlCode,
lpInBuffer,
nInBufferSize,
lpOutBuffer,
nOutBufferSize,
lpBytesReturned,
&m_IoCtrlOvlp))
{
// Overlapped operation in progress is not an actual error
if(::GetLastError() != ERROR_IO_PENDING)
bRet = FALSE;
else
{
// Wait for the overlapped operation to complete
switch(::WaitForSingleObject(m_IoCtrlOvlp.hEvent, dwTimeout))
{
case WAIT_OBJECT_0:
// The overlapped operation has completed
if(!::GetOverlappedResult(m_hComm, &m_IoCtrlOvlp, lpBytesReturned, FALSE))
bRet = FALSE;
else
bRet = TRUE;
break;
case WAIT_TIMEOUT:
// Cancel the I/O operation
::CancelIo(m_hComm);
default:
bRet = FALSE;
}
}
}
::CloseHandle(m_IoCtrlOvlp.hEvent);
}
// Return successfully
return bRet;
}
#ifdef FEATURE_SERIAL_ASYNWRITE
UINT CSerialPort::CommWriteThreadProc(LPVOID pParam)
{
DWORD dwWrite;
DWORD dwEvent;
CSerialPort *pComm = (CSerialPort*)pParam;
// AfxMessageBox("Serial Write Thread Start!");
for(;;)
{
dwEvent = ::WaitForMultipleObjects(SERAIL_EVENTARRAYNUM, pComm->m_hEventArray, FALSE, INFINITE);
dwEvent -= WAIT_OBJECT_0;
switch(dwEvent) {
case SERAIL_WRITEEVENT:
pComm->Purge(PURGE_TXCLEAR);
dwWrite = 0;
#ifdef FEATURE_SERIAL_QUEUE
CSerialBuffer *buf;
while(buf = pComm->m_WriteBufQueue.GetFromHead())
{
dwWrite = 0;
dwWrite = pComm->Write(buf->m_szBuffer, buf->m_dwBytes);
delete buf;
}
#else
EnterCriticalSection(&pComm->m_csTxBuff);
dwWrite = pComm->Write(pComm->m_TxBuff, pComm->m_wTxCount);
LeaveCriticalSection(&pComm->m_csTxBuff);
#endif
break;
case SERAIL_IOCTRLEVENT:
// pComm->IoControl();
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -