📄 ceseries.cpp
字号:
// CESeries.cpp: implementation of the CCESeries class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Printer.h"
#include "CESeries.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCESeries::CCESeries()
{
m_hComm = INVALID_HANDLE_VALUE;
}
CCESeries::~CCESeries()
{
}
BOOL CCESeries::WritePort(HANDLE hComm, const BYTE *buf, DWORD bufLen)
{
DWORD dwNumBytesWritten;
DWORD dwHaveNumWritten = 0;//已写入的数据量
ASSERT(hComm != INVALID_HANDLE_VALUE);
do {
if (WriteFile(hComm, //串口句柄
buf+dwHaveNumWritten, //被写数据缓冲区
bufLen - dwHaveNumWritten, //被写数据缓冲区大小
&dwNumBytesWritten, //返回实际向串口写数据的个数
NULL)) //此处必须设置为NULL
{
dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten;
//写入完成
if (dwHaveNumWritten == bufLen)
{
break;
}
Sleep(10);
}
else
{
return FALSE;
}
} while(TRUE);
return true;
}
DWORD WINAPI CCESeries::ReadThreadFunc(LPVOID lparam)
{
CCESeries *ceSeries = (CCESeries*) lparam;
DWORD evtMask;
BYTE * readBuf = NULL ;//读取的字节
DWORD actualReadLen = 0; //实际读取的字节数
DWORD willReadLen;
DWORD dwReadErrors;
COMSTAT cmState;
//清空缓冲,并检查串口是否打开
ASSERT(ceSeries->m_hComm !=INVALID_HANDLE_VALUE);
//清空串口
PurgeComm(ceSeries->m_hComm,PURGE_RXCLEAR | PURGE_TXCLEAR);
SetCommMask(ceSeries->m_hComm,EV_RXCHAR | EV_CTS | EV_DSR);
while(true)
{
if(WaitCommEvent(ceSeries->m_hComm,&evtMask,0))
{
SetCommMask(ceSeries->m_hComm,EV_RXCHAR |EV_CTS |EV_DSR);
//表示串口收到字符
if(evtMask & EV_RXCHAR)
{
ClearCommError(ceSeries->m_hComm,&dwReadErrors,&cmState);
willReadLen = cmState.cbInQue;
if(willReadLen <= 0)
{
continue;
}
readBuf = new BYTE[willReadLen];
ReadFile(ceSeries->m_hComm,readBuf,willReadLen,
&actualReadLen,0);
//如果读取数据大于0
if(actualReadLen>0)
{
//触发读取回调
ceSeries->m_OnSeriersRead(ceSeries->m_pPortOwner,
readBuf,actualReadLen);
}
}
}
//如果收到读线程退出信号,则退出线程
if(WaitForSingleObject(ceSeries->m_hReadCloseEvent,300) == WAIT_OBJECT_0)
{
break;
}
}
return 0;
}
DWORD WINAPI CCESeries::WriteThreadFunc(LPVOID lparam)
{
CCESeries *ceSeries = (CCESeries*)lparam;
MSG msg;
DWORD dwWriteLen = 0;
BYTE * buf = NULL;
while(true)
{
//如果捕捉到线程消息
if(PeekMessage(&msg,0,0,0,PM_REMOVE))
{
if(msg.hwnd != 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
if(msg.message == CM_THREADCOMMWRITE)
{
//向串口写
buf = (BYTE*)msg.lParam;
dwWriteLen = msg.wParam;
//向串口写
WritePort(ceSeries->m_hComm,buf,dwWriteLen);
//删除动态分配的内存
delete[] buf;
}
}
//如果收到写线程退出信号,则退出线程
if(WaitForSingleObject(ceSeries->m_hWriteCloseEvent,500) ==
WAIT_OBJECT_0)
{
break;
}
ceSeries->m_hWriteThread = NULL;
}
return 0;
}
void CCESeries::CloseReadThread()
{
SetEvent(m_hReadCloseEvent);
//设置所有事件无效
SetCommMask(m_hComm,0);
//清空所有将要读的数据
PurgeComm(m_hComm,PURGE_RXCLEAR);
//等待10秒,如果写线程没有退出,则强制退出
if(WaitForSingleObject(m_hReadCloseEvent,100) == WAIT_TIMEOUT)
{
TerminateThread(m_hReadCloseEvent,0);
}
m_hReadCloseEvent = NULL;
}
void CCESeries::CloseWriteThread()
{
SetEvent(m_hWriteCloseEvent);
//清空所有将要写的数据
PurgeComm(m_hComm,PURGE_TXCLEAR);
//等待10秒,如果写线程没有退出,则强制退出
if(WaitForSingleObject(m_hWriteThread,100) == WAIT_TIMEOUT)
{
TerminateThread(m_hWriteThread,0);
}
m_hWriteThread = NULL;
}
BOOL CCESeries::OpenPort(CWnd *pPortOwner, //使用此串口类的窗体句柄
UINT portNo, //串口号
UINT baud, //波特率
UINT parity, //奇偶校验
UINT databits, //数据位
UINT stopbits //停止位
)
{
DCB commParam;
TCHAR szPort[15];
memset(szPort,0,sizeof(szPort));
//如果已经打开,则直接返回
if (m_hComm != INVALID_HANDLE_VALUE)
{
return true;
}
ASSERT(pPortOwner != NULL);
ASSERT(portNo > 0 && portNo<5);
//设置串口名
wsprintf(szPort,L"COM%d:",portNo);
//打开串口
m_hComm = CreateFile(
szPort,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL
);
if(m_hComm == INVALID_HANDLE_VALUE)
{
//无效句柄,返回
TRACE(_T("CreateFile返回无效句柄"));
return false;
}
//得到打开串口的当前属性参数,修改后再重新设置串口
//设置串口的超时推行为立即返回
if(!GetCommState(m_hComm,&commParam))
{
return true;
}
commParam.BaudRate = baud;
commParam.fBinary = TRUE;
commParam.fParity = TRUE;
commParam.ByteSize = databits;
commParam.Parity = NOPARITY;
commParam.StopBits = stopbits;
commParam.fOutxCtsFlow = FALSE;
commParam.fOutxDsrFlow = FALSE;
//DTR flow control type
commParam.fDtrControl = DTR_CONTROL_ENABLE;
commParam.fDsrSensitivity = false;
commParam.fTXContinueOnXoff = true;
commParam.fOutX = false;
commParam.fInX = false;
commParam.fErrorChar = false;
commParam.fNull = false;
commParam.fRtsControl = RTS_CONTROL_ENABLE;
//RTS flow control
commParam.fAbortOnError = false;
if(!SetCommState(m_hComm,&commParam))
{
TRACE(_T("SetCommState error"));
return false;
}
//设置串口读写时间
COMMTIMEOUTS CommTimeOuts;
GetCommTimeouts(m_hComm,&CommTimeOuts);
CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 10;
CommTimeOuts.WriteTotalTimeoutConstant = 1000;
if (!SetCommTimeouts(m_hComm,&CommTimeOuts))
{
TRACE(_T("SetCommTimeouts返回错误"));
return false;
}
m_pPortOwner = pPortOwner;
//指定端口监测事件集
SetCommMask(m_hComm,EV_RXCHAR);
//分配设备缓冲区
SetupComm(m_hComm,512,512);
//初始化缓冲区中的信息
PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);
m_hReadCloseEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
m_hWriteCloseEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
//创建读串口线程
m_hReadThread = CreateThread(NULL,0,ReadThreadFunc,this,0,&m_dwWriteThreadID);
//创建写串口线程
m_hWriteThread = CreateThread(NULL,0,WriteThreadFunc,this,0,&m_dwWriteThreadID);
TRACE(_T("串口打开成功"));
return true;
}
void CCESeries::ClosePort()
{
if(m_hComm == INVALID_HANDLE_VALUE)
{
return;
}
//关闭读线程
CloseReadThread();
//关闭写线程
CloseWriteThread();
//关闭串口
if (!CloseHandle(m_hComm))
{
m_hComm = INVALID_HANDLE_VALUE;
return;
}
}
BOOL CCESeries::WritePort(const BYTE *buf, DWORD bufLen)
{
if(!PostThreadMessage(m_dwWriteThreadID,CM_THREADCOMMWRITE,
WPARAM(bufLen),LPARAM(buf)))
{
return true;
}
return false;
}
BOOL CCESeries::SetSeriersTimeouts(COMMTIMEOUTS CommTimeOuts)
{
ASSERT(m_hComm !=INVALID_HANDLE_VALUE);
return SetCommTimeouts(m_hComm,&CommTimeOuts);
}
BOOL CCESeries::PrintString(CString string)
{
BYTE buf[1024];
int len =0;
memset(buf,0,1024);
while(len<1025 && string[len])
{
buf[len] = string[len];
len++;
}
return WritePort(this->m_hComm,buf,len);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -