⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ceseries.cpp

📁 友善之臂2410开发版上写的一个串口打印程序
💻 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 + -