// CommPort.cpp: implementation of the CCommPort class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CommPort.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCommPort::CCommPort()
{
m_hComm = NULL;
m_pThread= NULL;
m_bConnect = FALSE;
m_dwRInterval= MAXDWORD;
m_dwInQueue = 2048;
m_dwOutQueue = 2048;
HandSetEvent();
}
CCommPort::~CCommPort()
{
if(m_bConnect)
ClosePort();
if(m_hPostMsgEvent)
CloseHandle(m_hPostMsgEvent);
if(m_olRead.hEvent)
CloseHandle(m_olRead.hEvent);
if(m_olWrite.hEvent)
CloseHandle(m_olWrite.hEvent);
}
BOOL CCommPort::OpenPort(CString sPortName,HWND hWnd)
{
COMMTIMEOUTS TimeOuts;
if(IsWindow(hWnd))
m_hTermWnd=hWnd; //保存传递来的WM_COMMNOTIFY消息(即读取与处理数据消息)的所在窗口句柄
else
{
AfxMessageBox("传递的窗口句柄无效!");
return FALSE;
}
if(m_bConnect) //判断串口是否已打开
{
AfxMessageBox("串口已打开!");
return FALSE;
}
else
{
m_hComm=CreateFile(sPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, //以重叠I/O方式打开串口
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
if(m_hComm==INVALID_HANDLE_VALUE)
{
AfxMessageBox("串口已被占用或串口不存在!");
return FALSE;
}
SetupComm(m_hComm,m_dwInQueue,m_dwOutQueue); //设置串口接收和发送缓冲区的大小 :最大
SetCommMask(m_hComm,EV_RXCHAR); //设置串口事件 : 输入缓冲区有新字符
// 把间隔超时设为最大,把总超时设为 0 将导致 ReadFile 立即返回并完成操作
TimeOuts.ReadIntervalTimeout=m_dwRInterval;
TimeOuts.ReadTotalTimeoutMultiplier=0;
TimeOuts.ReadTotalTimeoutConstant=0;
// 设置写超时以指定 WriteComm 成员函数中的GetOverlappedResult 函数的等待时间
TimeOuts.WriteTotalTimeoutMultiplier=50;
TimeOuts.WriteTotalTimeoutConstant=2000;
SetCommTimeouts(m_hComm, &TimeOuts); //设置超时
}
return TRUE;
}
BOOL CCommPort::SetupPort(int nBaud, int nParity, int nDataBits, int nStop)
{
DCB dcb;
if(!GetCommState(m_hComm,&dcb))
{
CloseHandle(m_hComm); //关闭串口
AfxMessageBox("配置串口错误\r请检查参数设置");
return FALSE;
}
dcb.BaudRate= nBaud; //设置参数
dcb.ByteSize= nDataBits;
switch(nParity)
{
case 0:
dcb.Parity = NOPARITY;
break;
case 1:
dcb.Parity = ODDPARITY;
break;
case 2:
dcb.Parity = EVENPARITY;
break;
case 3:
dcb.Parity = MARKPARITY;
break;
case 4:
dcb.Parity = SPACEPARITY;
break;
default:
break;
}
switch(nStop)
{
case 0:
dcb.StopBits = ONESTOPBIT;
break;
case 1:
dcb.StopBits = ONE5STOPBITS;
break;
case 2:
dcb.StopBits = TWOSTOPBITS;
break;
default:
break;
}
if(!SetCommState(m_hComm,&dcb)) //配置串口
{
CloseHandle(m_hComm); //关闭串口
AfxMessageBox("配置串口错误\r请检查参数设置");
return FALSE;
}
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); //终止所有后台读写操作并清空缓冲区
return TRUE;
}
DWORD CCommPort::WritePort(int *buf,DWORD dwLength)
{
if(!m_bConnect)
{
AfxMessageBox("串口未连接,请连接!");
return 0;
}
BOOL bWriteState; //写入是否成功
COMSTAT ComStat; //包含了通信设备的信息
DWORD dwErrorFlags; //错误标示
DWORD length=dwLength; //写入字符长度
ClearCommError(m_hComm,&dwErrorFlags,&ComStat); //清空错误标示,报告错误
if(dwErrorFlags>0)
{
AfxMessageBox("写串口错误!");
PurgeComm(m_hComm,PURGE_TXABORT|PURGE_TXCLEAR); //清空缓冲区
return 0;
}
bWriteState=WriteFile(m_hComm,buf,length,&length,&m_olWrite); //写入数据
if(!bWriteState)
{
if(GetLastError()==ERROR_IO_PENDING) //判断是否因为写操作未完成
{
GetOverlappedResult(m_hComm,&m_olWrite,&length,TRUE); //等待写入完成
}
else
{
AfxMessageBox("写串口错误!");
return 0;
}
}
return length;
}
DWORD CCommPort::ReadPort(int *buf, DWORD dwLength)
{
if(!m_bConnect)
{
AfxMessageBox("串口未连接!");
return 0;
}
DWORD length=0;
COMSTAT ComStat;
DWORD dwErrorFlags;
ClearCommError(m_hComm,&dwErrorFlags,&ComStat); //获得当前通信串口状态,来确定接收缓区中处于等待的字节数。
length=min(dwLength, ComStat.cbInQue); //选择最小长度进行读取
if(!ReadFile(m_hComm,buf,length,&length,&m_olRead)) //如果串口读取成功,数据会存储在buf数组中
{
AfxMessageBox("读串口错误\r参数传递是否正确");
return 0;
}
return length; //返回实际读取字符的长度
}
void CCommPort::ClosePort()
{
if(!m_bConnect)
return;
m_bConnect=FALSE;
SetEvent(m_hPostMsgEvent); //结束 CommProc 线程中 WaitSingleObject 函数的等待
SetCommMask(m_hComm,0); //结束 CommProc 线程中 WaitCommEvent 的等待
WaitForSingleObject(m_pThread->m_hThread,INFINITE); //等待辅助线程终止
m_pThread=NULL; //清空
PurgeComm(m_hComm,PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);//终止所有后台读写操作并清空缓冲区
CloseHandle(m_hComm); //关闭串口
}
BOOL CCommPort::CreateThread()
{
m_pThread=AfxBeginThread(CommProcFun,this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED,NULL); //创建工作者线程,并挂起
if(m_pThread==NULL)
{
CloseHandle(m_hComm); //关闭串口
AfxMessageBox("线程创建失败");
return FALSE;
}
m_bConnect=TRUE; //标示串口已成功连接
m_pThread->ResumeThread(); //恢复线程
return TRUE;
}
BOOL CCommPort::HandSetEvent()
{
// 为 WM_COMMNOTIFY 消息创建事件对象,手工重置,初始化为有信号的
if((m_hPostMsgEvent=CreateEvent(NULL, TRUE, TRUE, NULL))==NULL)
return FALSE;
memset(&m_olRead, 0, sizeof(OVERLAPPED));
memset(&m_olWrite,0, sizeof(OVERLAPPED));
// 为重叠读创建事件对象,手工重置,初始化为无信号的
if((m_olRead.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL))==NULL)
return FALSE;
// 为重叠写创建事件对象,手工重置,初始化为无信号的
if((m_olWrite.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL))==NULL)
return FALSE;
return TRUE;
}
/************************************************************************/
/* 工作者线程,监视串口 */
/************************************************************************/
UINT CommProcFun(LPVOID pParam)
{
OVERLAPPED ol;
COMSTAT ComStat;
DWORD dwMask=0,dwTrans;
DWORD dwErrorFlags;
CCommPort *pCommPort=(CCommPort*)pParam; //获得串口类对象地址
memset(&ol,0,sizeof(OVERLAPPED));
ol.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL); //设置事件
if(ol.hEvent==NULL)
{
AfxMessageBox("设置事件对象失败");
return (UINT)-1;
}
while(pCommPort->m_bConnect)
{
ClearCommError(pCommPort->m_hComm,&dwErrorFlags,&ComStat); //获得缓冲区字节长度
if(ComStat.cbInQue) //如果不为0
{
WaitForSingleObject(pCommPort->m_hPostMsgEvent,INFINITE); //无限等待WM_COMMNOTIFY消息处理完成
ResetEvent(pCommPort->m_hPostMsgEvent); //设置事件为无信号
PostMessage(pCommPort->m_hTermWnd,WM_COMMNOTIFY,EV_RXCHAR,0); //发送读取与处理消息
// SendMessage(pCommPort->m_hTermWnd,WM_COMMNOTIFY,EV_RXCHAR,0);
continue;
} //跳出本次循环
if(!WaitCommEvent(pCommPort->m_hComm,&dwMask,&ol)) //如果缓冲区无字节,进行重叠操作
{
if(GetLastError()==ERROR_IO_PENDING)
GetOverlappedResult(pCommPort->m_hComm,&ol,&dwTrans,TRUE); //无限等待通信事件发生
else
{
CloseHandle(ol.hEvent);
return (UINT)-1;
}
}
}
Close
基于Win32的 串口通信操作类
5星 · 超过95%的资源 需积分: 9 47 浏览量
2010-07-26
13:01:40
上传
评论
收藏 4KB RAR 举报
li122478722
- 粉丝: 30
- 资源: 47