/*
Module : SERIALPORT.CPP
Purpose: Implementation for an MFC wrapper class for serial ports
Created: PJN / 31-05-1999
History: PJN / 03-06-1999 1. Fixed problem with code using CancelIo which does not exist on 95.
2. Fixed leaks which can occur in sample app when an exception is thrown
PJN / 16-06-1999 1. Fixed a bug whereby CString::ReleaseBuffer was not being called in
CSerialException::GetErrorMessage
PJN / 29-09-1999 1. Fixed a simple copy and paste bug in CSerialPort::SetDTR
Copyright (c) 1999 by PJ Naughter.
All rights reserved.
*/
///////////////////////////////// Includes //////////////////////////////////
#include "stdafx.h"
#include "serialport.h"
#include "winerror.h"
///////////////////////////////// defines /////////////////////////////////////
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//////////////////////////////// Implementation ///////////////////////////////
//Class which handles CancelIo function which must be constructed at run time
//since it is not imeplemented on NT 3.51 or Windows 95. To avoid the loader
//bringing up a message such as "Failed to load due to missing export...", the
//function is constructed using GetProcAddress. The CSerialPort::CancelIo
//function then checks to see if the function pointer is NULL and if it is it
//throws an exception using the error code ERROR_CALL_NOT_IMPLEMENTED which
//is what 95 would have done if it had implemented a stub for it in the first
//place !!
class _SERIAL_PORT_DATA
{
public:
//Constructors /Destructors
_SERIAL_PORT_DATA();
~_SERIAL_PORT_DATA();
HINSTANCE m_hKernel32;
typedef BOOL (CANCELIO)(HANDLE);
typedef CANCELIO* LPCANCELIO;
LPCANCELIO m_lpfnCancelIo;
};
_SERIAL_PORT_DATA::_SERIAL_PORT_DATA()
{
m_hKernel32 = LoadLibrary(_T("KERNEL32.DLL"));
VERIFY(m_hKernel32 != NULL);
m_lpfnCancelIo = (LPCANCELIO) GetProcAddress(m_hKernel32, "CancelIo");
}
_SERIAL_PORT_DATA::~_SERIAL_PORT_DATA()
{
FreeLibrary(m_hKernel32);
m_hKernel32 = NULL;
}
//The local variable which handle the function pointers
_SERIAL_PORT_DATA _SerialPortData;
////////// Exception handling code
void AfxThrowSerialException(DWORD dwError /* = 0 */)
{
if (dwError == 0)
dwError = ::GetLastError();
CSerialException* pException = new CSerialException(dwError);
TRACE(_T("Warning: throwing CSerialException for error %d\n"), dwError);
THROW(pException);
}
BOOL CSerialException::GetErrorMessage(LPTSTR pstrError, UINT nMaxError, PUINT pnHelpContext)
{
ASSERT(pstrError != NULL && AfxIsValidString(pstrError, nMaxError));
if (pnHelpContext != NULL)
*pnHelpContext = 0;
LPTSTR lpBuffer;
BOOL bRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, m_dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
(LPTSTR) &lpBuffer, 0, NULL);
if (bRet == FALSE)
*pstrError = '\0';
else
{
lstrcpyn(pstrError, lpBuffer, nMaxError);
bRet = TRUE;
LocalFree(lpBuffer);
}
return bRet;
}
CString CSerialException::GetErrorMessage()
{
CString rVal;
LPTSTR pstrError = rVal.GetBuffer(4096);
GetErrorMessage(pstrError, 4096, NULL);
rVal.ReleaseBuffer();
return rVal;
}
CSerialException::CSerialException(DWORD dwError)
{
m_dwError = dwError;
}
CSerialException::~CSerialException()
{
}
IMPLEMENT_DYNAMIC(CSerialException, CException)
#ifdef _DEBUG
void CSerialException::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << "m_dwError = " << m_dwError;
}
#endif
////////// The actual serial port code
CSerialPort::CSerialPort()
{
m_hComm = INVALID_HANDLE_VALUE;
m_bOverlapped = FALSE;
}
CSerialPort::~CSerialPort()
{
Close();
}
IMPLEMENT_DYNAMIC(CSerialPort, CObject)
#ifdef _DEBUG
void CSerialPort::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << _T("m_hComm = ") << m_hComm << _T("\n");
dc << _T("m_bOverlapped = ") << m_bOverlapped;
}
#endif
void CSerialPort::Open(int nPort, DWORD dwBaud, Parity parity, BYTE DataBits, StopBits stopbits, FlowControl fc, BOOL bOverlapped)
{
//Validate our parameters
ASSERT(nPort>0 && nPort<=255);
//Call CreateFile to open up the comms port
CString sPort;
sPort.Format(_T("\\\\.\\COM%d"), nPort);
m_hComm = CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, bOverlapped ? FILE_FLAG_OVERLAPPED : 0, NULL);
if (m_hComm == INVALID_HANDLE_VALUE)
{
TRACE(_T("Failed to open up the comms port\n"));
AfxThrowSerialException();
}
m_bOverlapped = bOverlapped;
//Get the current state prior to changing it
DCB dcb;
GetState(dcb);
//Setup the baud rate
dcb.BaudRate = dwBaud;
//Setup the Parity
switch (parity)
{
case EvenParity: dcb.Parity = EVENPARITY; break;
case MarkParity: dcb.Parity = MARKPARITY; break;
case NoParity: dcb.Parity = NOPARITY; break;
case OddParity: dcb.Parity = ODDPARITY; break;
case SpaceParity: dcb.Parity = SPACEPARITY; break;
default: ASSERT(FALSE); break;
}
//Setup the data bits
dcb.ByteSize = DataBits;
//Setup the stop bits
switch (stopbits)
{
case OneStopBit: dcb.StopBits = ONESTOPBIT; break;
case OnePointFiveStopBits: dcb.StopBits = ONE5STOPBITS; break;
case TwoStopBits: dcb.StopBits = TWOSTOPBITS; break;
default: ASSERT(FALSE); break;
}
//Setup the flow control
dcb.fDsrSensitivity = FALSE;
switch (fc)
{
case NoFlowControl:
{
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
break;
}
case CtsRtsFlowControl:
{
dcb.fOutxCtsFlow = TRUE;
dcb.fOutxDsrFlow = FALSE;
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
break;
}
case CtsDtrFlowControl:
{
dcb.fOutxCtsFlow = TRUE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
break;
}
case DsrRtsFlowControl:
{
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = TRUE;
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
break;
}
case DsrDtrFlowControl:
{
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = TRUE;
dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
break;
}
case XonXoffFlowControl:
{
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;
dcb.XoffLim = 100;
dcb.XonLim = 100;
break;
}
default:
{
ASSERT(FALSE);
break;
}
}
//Now that we have all the settings in place, make the changes
SetState(dcb);
}
void CSerialPort::Close()
{
if (IsOpen())
{
BOOL bSuccess = CloseHandle(m_hComm);
m_hComm = INVALID_HANDLE_VALUE;
if (!bSuccess)
TRACE(_T("Failed to close up the comms port, GetLastError:%d\n"), GetLastError());
m_bOverlapped = FALSE;
}
}
void CSerialPort::Attach(HANDLE hComm)
{
Close();
m_hComm = hComm;
}
HANDLE CSerialPort::Detach()
{
HANDLE hrVal = m_hComm;
m_hComm = INVALID_HANDLE_VALUE;
return hrVal;
}
DWORD CSerialPort::Read(void* lpBuf, DWORD dwCount)
{
ASSERT(IsOpen());
ASSERT(!m_bOverlapped);
DWORD dwBytesRead = 0;
if (!ReadFile(m_hComm, lpBuf, dwCount, &dwBytesRead, NULL))
{
VC 串口通讯类,支持异常处理
3星 · 超过75%的资源 需积分: 11 115 浏览量
2009-05-16
21:11:51
上传
评论
收藏 18KB ZIP 举报
Jlins
- 粉丝: 5880
- 资源: 173
最新资源
- NetOps-py通过sftp替换网络设备启动文件
- STM32单片机FPGA毕设电路原理论文报告任务驱动教学法在单片机课程教学中的应用
- STM32单片机FPGA毕设电路原理论文报告任务驱动法在单片机教学中的应用
- STM32单片机FPGA毕设电路原理论文报告人造金刚石压机智能化压力测控系统设计
- 以某列为依据匹配多项(Excel版)
- STM32单片机FPGA毕设电路原理论文报告人体短臂离心机实验台的显示控制系统
- STM32单片机FPGA毕设电路原理论文报告人工气候室监控系统的环境控制器研究
- STM32单片机FPGA毕设电路原理论文报告染整自动线张力控制系统的设计
- 数据挖掘与机器学习-实验
- 基于Linux系统Nginx的动态网站的LNMP环境源码包
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈