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

📄 ceseries.cpp

📁 EVC环境下通过串行口对GPS以及GPRS信息读写
💻 CPP
字号:
// CESeries.cpp: implementation of the CCESeries class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "GPSCOM.h"
#include "CESeries.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//定义向写线程发送的消息常量
const CM_THREADCOMMWRITE = WM_USER+110;
//#define CM_THREADCOMMWRITE                32772
CCESeries::CCESeries()
{
	m_hComm=INVALID_HANDLE_VALUE;
	m_hComm1=INVALID_HANDLE_VALUE;
}

CCESeries::~CCESeries()
{

}
BOOL CCESeries::OpenPort()
{
	// 已经打开的话,直接返回
	if (m_hComm != INVALID_HANDLE_VALUE)
	{
		return TRUE;
	}
	
	//以同步读取方式打开串口COM1
	m_hComm = CreateFile(_T("COM1:"), 
		GENERIC_READ, //允许读
		0, //独占方式
		NULL,
		OPEN_EXISTING, //打开而不是创建
		0, 
		NULL);

	if (m_hComm == INVALID_HANDLE_VALUE)
	{
		// 无效句柄,返回。		
		return FALSE;
	}
	
	// 配置串口,得到打开串口的当前属性参数,修改后再重新设置串口。
	DCB portDCB;
	portDCB.DCBlength=sizeof(DCB); //DCB结构大小
	//默认串口参数
	if(!GetCommState(m_hComm,&portDCB))
	{		
		return FALSE;
	}
	portDCB.BaudRate=9600;  //波特率
	portDCB.ByteSize=8;     //字符位
	portDCB.Parity=NOPARITY; //奇偶校验位
	portDCB.StopBits=ONESTOPBIT;//停止位
	if (!SetCommState(m_hComm,&portDCB))
	{
		//配置串口失败
		return FALSE;
	}
	
    //设置串口读写时间
	//配置超时
	COMMTIMEOUTS CommTimeouts;
	GetCommTimeouts(m_hComm,&CommTimeouts);
	CommTimeouts.ReadIntervalTimeout = MAXDWORD; 
	CommTimeouts.ReadTotalTimeoutMultiplier = 0; 
	CommTimeouts.ReadTotalTimeoutConstant = 0; 
	CommTimeouts.WriteTotalTimeoutMultiplier = 10;  
	CommTimeouts.WriteTotalTimeoutConstant = 1000;  
	if (!SetCommTimeouts(m_hComm,&CommTimeouts))
	{
		//不能设置超时参数
		return FALSE;
	}
	

	//指定端口监测的事件集
	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_dwReadThreadID);
	//创建写串口线程
	m_hWriteThread = CreateThread(NULL,0,WriteThreadFunc,this,0,&m_dwWriteThreadID);
	
	return TRUE;
}
//串口读线程函数
DWORD CCESeries::ReadThreadFunc(LPVOID lparam)
{
	CCESeries *ceSeries = (CCESeries*)lparam;
	
	DWORD	evtMask;
	//BYTE * readBuf = NULL;//读取的字节
	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;
				}
				//willReadLen=4;
				//willReadLen=willReadLen/2+1;
				readBuf = new BYTE[willReadLen+1];
		
				ReadFile(ceSeries->m_hComm, readBuf, willReadLen, &actualReadLen,0);
				readBuf[willReadLen]=0;
				//BYTE * Buf1 = NULL;
				//Buf1 = new BYTE[actualReadLen+1];
				//memcpy(Buf1,readBuf,actualReadLen);
				//Buf1[actualReadLen]=0;
				//如果读取的数据大于0,
				if (actualReadLen>0)
				{
					//触发读取回调函数
					ceSeries->m_OnSeriesRead(ceSeries->m_pPortOwner,readBuf,actualReadLen);
				}
			}
		}
		//如果收到读线程退出信号,则退出线程
		if (WaitForSingleObject(ceSeries->m_hReadCloseEvent,500) == WAIT_OBJECT_0)
		{
			break;
		}
	}
	return 0;
}
void CCESeries::ClosePort()
{
	//表示串口还没有打开
	if (m_hComm == INVALID_HANDLE_VALUE)
	{
		return ;
	}

	//关闭读线程
	CloseReadThread();
	//关闭写线程
	CloseWriteThread();
	//关闭串口
	if (!CloseHandle (m_hComm))
	{
		m_hComm = INVALID_HANDLE_VALUE;
		return ;
	}
}

void CCESeries::CloseReadThread()
{
	SetEvent(m_hReadCloseEvent);
	//设置所有事件无效无效
	SetCommMask(m_hComm, 0);
	//清空所有将要读的数据
    PurgeComm( m_hComm,  PURGE_RXCLEAR );
    //等待10秒,如果读线程没有退出,则强制退出
    if (WaitForSingleObject(m_hReadThread,10000) == WAIT_TIMEOUT)
	{
		TerminateThread(m_hReadThread,0);
	}
	m_hReadThread = NULL;
}

BOOL CCESeries::WritePort(BYTE *buf, int bufLen)
{
	//将要发送的数据传递到写线程消息队列
	if (PostThreadMessage(m_dwWriteThreadID,CM_THREADCOMMWRITE,
		WPARAM(bufLen), LPARAM(buf)))
	{
		return TRUE;
	}
	
	return FALSE;
}

BOOL CCESeries::WritePort(HANDLE hComm, BYTE *buf, int 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 ==(DWORD) bufLen)
			{
				
				break;
			}
			Sleep(10);
		}
		else
		{
			return FALSE;
		}
	}while (TRUE);
	
	return TRUE;

}

void CCESeries::CloseWriteThread()
{
	SetEvent(m_hWriteCloseEvent);
	
	//清空所有将要写的数据
    PurgeComm( m_hComm1,  PURGE_TXCLEAR );
	
    //等待10秒,如果读线程没有退出,则强制退出
    if (WaitForSingleObject(m_hWriteThread,10000) == WAIT_TIMEOUT)
	{
		TerminateThread(m_hWriteThread,0);
	}
	m_hWriteThread = NULL;
}

DWORD CCESeries::WriteThreadFunc(LPVOID lparam)
{
	CCESeries *ceSeries = (CCESeries*)lparam;
	MSG msg;
	DWORD dwWriteLen = 0;
	
	BYTE * buf1;
	while (TRUE)
	{
		//如果捕捉到线程消息
		if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
		{
			if (msg.hwnd != 0 )
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
				continue;
			}
			if (msg.message == CM_THREADCOMMWRITE)
			{
			
				//向串口写
				buf1 = (BYTE*)msg.lParam;
					
				dwWriteLen = msg.wParam;
				
				//向串口写
				WritePort(ceSeries->m_hComm1,buf1,dwWriteLen);
			//	delete[] buf1;
				Sleep(10);
			}
		}
		//如果收到写线程退出信号,则退出线程
		if (WaitForSingleObject(ceSeries->m_hWriteCloseEvent,500) == WAIT_OBJECT_0)
		{
			break;
		}
		
		ceSeries->m_hWriteThread = NULL;
		
	}
	
	return 0;
}

BOOL CCESeries::OpenPort1()
{
	// 已经打开的话,直接返回
	if (m_hComm1 != INVALID_HANDLE_VALUE)
	{
		return TRUE;
	}
	
	//以同步读取方式打开串口COM1
	m_hComm1 = CreateFile(_T("COM1:"), 
		GENERIC_READ| GENERIC_WRITE, //允许读写
		0, //独占方式
		NULL,
		OPEN_EXISTING, //打开而不是创建
		0, 
		NULL);

	if (m_hComm1 == INVALID_HANDLE_VALUE)
	{
		// 无效句柄,返回。		
		return FALSE;
	}
	
	// 配置串口,得到打开串口的当前属性参数,修改后再重新设置串口。
	DCB portDCB;
	portDCB.DCBlength=sizeof(DCB); //DCB结构大小
	//默认串口参数
	if(!GetCommState(m_hComm1,&portDCB))
	{		
		return FALSE;
	}
	portDCB.BaudRate=9600;  //波特率
	portDCB.ByteSize=8;     //字符位
	portDCB.Parity=NOPARITY; //奇偶校验位
	portDCB.StopBits=ONESTOPBIT;//停止位
	if (!SetCommState(m_hComm1,&portDCB))
	{
		//配置串口失败
		return FALSE;
	}
	
    //设置串口读写时间
	//配置超时
	COMMTIMEOUTS CommTimeouts;
	GetCommTimeouts(m_hComm1,&CommTimeouts);
	CommTimeouts.ReadIntervalTimeout = MAXDWORD; 
	CommTimeouts.ReadTotalTimeoutMultiplier = 0; 
	CommTimeouts.ReadTotalTimeoutConstant = 0; 
	CommTimeouts.WriteTotalTimeoutMultiplier = 10;  
	CommTimeouts.WriteTotalTimeoutConstant = 1000;  
	if (!SetCommTimeouts(m_hComm1,&CommTimeouts))
	{
		//不能设置超时参数
		return FALSE;
	}
	

	//指定端口监测的事件集
	SetCommMask (m_hComm1, EV_RXCHAR);
	
	//分配设备缓冲区
	SetupComm(m_hComm1,512,512);
	
	//初始化缓冲区中的信息
	PurgeComm(m_hComm1,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_dwReadThreadID);
	//创建写串口线程
	m_hWriteThread = CreateThread(NULL,0,WriteThreadFunc,this,0,&m_dwWriteThreadID);
	
	return TRUE;
}

void CCESeries::ClosePort1()
{
	//表示串口还没有打开
	if (m_hComm1 == INVALID_HANDLE_VALUE)
	{
		return ;
	}

	//关闭写线程
	CloseWriteThread();
	//关闭串口
	if (!CloseHandle (m_hComm1))
	{
		m_hComm1 = INVALID_HANDLE_VALUE;
		return ;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -