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

📄 comm.cpp

📁 各种打印机通用程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "StdAfx.h"
#include <stdio.h>
#include "COMM.h"
/**********************************************************************
Function:   ReadThread
Description:建立读串口线程,接收到字符时通知窗口或线程,线程结束
Input:      pParam -> CommDevice 类对象
***********************************************************************/
UINT ReadThread(LPVOID pParam)
{
	DWORD dwEventMask;
	BOOL Reading;
	HANDLEInfo *pc = (HANDLEInfo *)pParam;
	PurgeComm(pc->CommInfo,PURGE_RXCLEAR);
	if (!SetCommMask(pc->CommInfo, EV_RXCHAR)) return(FALSE);
	Reading = TRUE;
	while(pc->ThreadRun)
	{
		dwEventMask = 0;
		if(WaitCommEvent(pc->CommInfo, &dwEventMask, NULL))
		{
			if ((dwEventMask & EV_RXCHAR) == EV_RXCHAR)
			{
				Reading = FALSE;						//接收到字符
				pc->ThreadRun = FALSE;
			}
			else
				SetCommMask(pc->CommInfo, EV_RXCHAR);	//未接收到字符,置中断
		}
	}
	SetCommMask(pc->CommInfo,0);
	if(!Reading)	
		::PostMessage((HWND)pc->HwndInfo,WM_RECVCHAR,NULL,NULL);
	return(TRUE);
}
/**********************************************************************
Function:   TimeOutThread
Description:时间超时监控线程,将超时通知串口事件读
Input:      pParam -> CommDevice 类对象
***********************************************************************/
UINT  TimeOutThread(LPVOID pParam)
{
	DWORD endtime;
	HANDLEInfo* tmp = (HANDLEInfo *)pParam;
	endtime=GetTickCount()+(tmp->TimeOut);
	while (tmp->ThreadRun)
	{
		if(GetTickCount()>endtime)
		{
			tmp->ThreadRun=FALSE;
			SetCommMask( tmp->CommInfo, 0);
			break;
		}
	}
	return(TRUE);
}
/**********************************************************************
Function:   CCommDevice
Description:类析构
***********************************************************************/
CCommDevice::CCommDevice()
{
	memset(ComPort,0,sizeof(ComPort));
	hCom = NULL;
    fConnected = FALSE;
	CRead_Thread = NULL;
	CTimeOut = NULL;
//zrz mody	TraceFlag = FALSE;
	TraceFlag = TRUE;

	memset(Trace_File,0,sizeof(Trace_File));
	TraceMode = 0;
	HandleInfo.HwndInfo = NULL;
	HandleInfo.CommHwnd = NULL;
	HandleInfo.CommInfo = NULL;
	HandleInfo.TimeOut = 0;
	HandleInfo.ThreadRun  = FALSE;
}
/**********************************************************************
Function:   ~CCommDevice
Description:类解析,关闭串口
***********************************************************************/
CCommDevice::~CCommDevice()
{
    Close();
}
/**********************************************************************
Function:   Open
Description:打开串口
Input:      szPort-->串口设备逻辑名
return:     Fail-->false;Success-->true
***********************************************************************/
BOOL CCommDevice::Open(char *szPort)
{
	DCB dcb;
	char szErrorMsg[20];

	Close();
	ComPort[0]=0;
	fConnected = FALSE;
	sprintf(szErrorMsg, "不能打开%s口", szPort);

	/*
	if ((HANDLE)-1 == (hCom =
		CreateFile( szPort, GENERIC_READ | GENERIC_WRITE,
			0,                    // exclusive access
			NULL,                 // no security attrs
			OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL |
			FILE_FLAG_OVERLAPPED, // overlapped I/O
			NULL )))
	{
		//MessageBox(NULL, szErrorMsg, NULL, MB_OK|MB_ICONINFORMATION);
		return(FALSE);
	}
	*/

	if( (hCom=CreateFile(szPort,GENERIC_READ|
		GENERIC_WRITE,0,
		NULL,OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,NULL)) == INVALID_HANDLE_VALUE )
	{
		MessageBox(NULL, szErrorMsg, NULL, MB_OK|MB_ICONINFORMATION);
		return(FALSE);
	}

	HandleInfo.ThreadRun = FALSE;
	CRead_Thread = NULL;
	CTimeOut = NULL;
	SetCommMask( hCom, 0 );
	SetupComm( hCom, 4096, 4096 );
	PurgeComm( hCom, PURGE_TXABORT | PURGE_RXABORT |
						PURGE_TXCLEAR | PURGE_RXCLEAR );

	CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
	CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
	CommTimeOuts.ReadTotalTimeoutConstant = 1000;
	CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
	CommTimeOuts.WriteTotalTimeoutConstant = 1000;
	SetCommTimeouts( hCom, &CommTimeOuts);

	dcb.DCBlength = sizeof( DCB );
	GetCommState( hCom, &dcb );

	dcb.BaudRate = CBR_9600;
	dcb.ByteSize = 8;
	dcb.Parity = NOPARITY;
	dcb.StopBits = ONESTOPBIT;

	dcb.fOutxDsrFlow = FALSE;				// true or false
	dcb.fDtrControl = DTR_CONTROL_ENABLE;	// DTR_CONTROL_HANDSHAKE
	dcb.fOutxCtsFlow = FALSE;				// true or false
	dcb.fRtsControl = RTS_CONTROL_ENABLE;	// RTS_CONTROL_HANDSHAKE

	dcb.fInX = dcb.fOutX = FALSE;
	dcb.XonChar = 0x11;		//ASCII_XON ;
	dcb.XoffChar = 0x13;	//ASCII_XOFF ;
	dcb.XonLim = 100;
	dcb.XoffLim = 100;
	
	// other various settings
	dcb.fBinary = TRUE;
	dcb.fParity = TRUE;

	if(SetCommState( hCom, &dcb ))
	{
		EscapeCommFunction( hCom, SETDTR );
		fConnected = TRUE;
		strcpy(ComPort,szPort);
		HandleInfo.CommInfo=hCom;
	}
	else
	{
		CloseHandle( hCom );
		fConnected = FALSE;
		//MessageBox(NULL, szErrorMsg, NULL, MB_OK | MB_ICONINFORMATION);
	}
	return(fConnected);
}
/**********************************************************************
Function:   Open
Description:带设置参数打开串口
Input:      szPort-->串口设备逻辑名
			 dcb  -> 串口设置
return:     Fail-->false;Success-->true
***********************************************************************/
BOOL CCommDevice::Open(char *szPort,DCB *pdcb)
{
	DCB dcb;
	char szErrorMsg[20];

	Close();
	ComPort[0]=0;
	fConnected = FALSE;
	sprintf(szErrorMsg, "不能打开%s口", szPort);
	
	/*
	if ((HANDLE)-1 == (hCom =
		CreateFile( szPort, GENERIC_READ | GENERIC_WRITE,
			0,
			NULL,
			OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL |	FILE_FLAG_OVERLAPPED,
			NULL )))
	{
		//MessageBox(NULL, szErrorMsg, NULL, MB_OK | MB_ICONINFORMATION);
		return(FALSE);
	}*/


	if( (hCom=CreateFile(szPort,GENERIC_READ|
		GENERIC_WRITE,0,
		NULL,OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,NULL)) == INVALID_HANDLE_VALUE )
	{
		MessageBox(NULL, szErrorMsg, NULL, MB_OK|MB_ICONINFORMATION);
		return(FALSE);
	}

	HandleInfo.ThreadRun = FALSE;
	CRead_Thread = NULL;
	CTimeOut = NULL;
	SetCommMask( hCom, 0 );
	SetupComm( hCom, 4096, 4096 );
	PurgeComm( hCom, PURGE_TXABORT | PURGE_RXABORT |
		PURGE_TXCLEAR | PURGE_RXCLEAR );

	CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
	CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
	CommTimeOuts.ReadTotalTimeoutConstant = 1000;
	CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
	CommTimeOuts.WriteTotalTimeoutConstant = 1000;
	SetCommTimeouts( hCom, &CommTimeOuts );

	dcb.DCBlength = sizeof( DCB );
	GetCommState( hCom, &dcb );
	dcb.BaudRate = pdcb->BaudRate;
	dcb.ByteSize = pdcb->ByteSize;
	dcb.Parity = pdcb->Parity;
	dcb.StopBits = pdcb->StopBits;

	dcb.fOutxDsrFlow = pdcb->fOutxDsrFlow;			// true or false
	if( dcb.fOutxDsrFlow )
		dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;	// DTR_CONTROL_HANDSHAKE
	else
		dcb.fDtrControl = DTR_CONTROL_ENABLE;

	dcb.fOutxCtsFlow = pdcb->fOutxCtsFlow;			// truem or false
	if( dcb.fOutxCtsFlow )
		dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;	// RTS_CONTROL_HANDSHAKE
	else
		dcb.fRtsControl = RTS_CONTROL_ENABLE;

	dcb.fInX = dcb.fOutX = pdcb->fInX;
	dcb.XonChar = pdcb->XonChar;					//ASCII_XON
	dcb.XoffChar = pdcb->XoffChar;					//ASCII_XOFF
	dcb.XonLim = pdcb->XonLim;
	dcb.XoffLim = pdcb->XoffLim;

	// other various settings
	dcb.fBinary = pdcb->fBinary;
	dcb.fParity = pdcb->fParity;

	if(SetCommState( hCom, &dcb ))
	{
		EscapeCommFunction( hCom, SETDTR );
		fConnected = TRUE;
		strcpy(ComPort,szPort);
		HandleInfo.CommInfo=hCom;		
	}
	else
	{
		CloseHandle( hCom );
		fConnected = FALSE;
		//MessageBox(NULL, szErrorMsg, NULL, MB_OK | MB_ICONINFORMATION);		
	}
	return(fConnected);
}

/**********************************************************************
Function:   SetCommHwnd
Description:配置串口相关窗口句柄
***********************************************************************/
void CCommDevice::SetCommHwnd(HWND HwndParam)
{
    HandleInfo.CommHwnd=HwndParam;
}
/**********************************************************************
Function:   GetCommHwnd
Description:获取串口相关窗口句柄
***********************************************************************/
HWND CCommDevice::GetCommHwnd(void)
{
    return(HandleInfo.CommHwnd);
}
/**********************************************************************
Function:   SetReadTimeOut
Description:串口读超时设置,为异步读服务
Input:      dwTimeOuts-->串口读总超时
***********************************************************************/
void CCommDevice::SetReadTimeOut(DWORD dwTimeOuts)
{
	if(dwTimeOuts == 0) 
	{
		CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
		CommTimeOuts.ReadTotalTimeoutConstant = 0;
	}
	else
	{
		CommTimeOuts.ReadIntervalTimeout = 0;
		CommTimeOuts.ReadTotalTimeoutMultiplier = 10;
		CommTimeOuts.ReadTotalTimeoutConstant = dwTimeOuts;
	}
	SetCommTimeouts( hCom, &CommTimeOuts );
}
/**********************************************************************
Function:   Read
Description:串口异步读(非阻塞方式从串口读固定长度字符,但不阻塞其他线程
			 和消息,允许重叠超作),时间由SetReadTimeOut指定。
Input:		 lpszBlock-->串口数据缓冲指针;
			 nMaxLength-->串口需读数据个数;
return:     串口实际读入数据个数
***********************************************************************/
int CCommDevice::Read(char *lpszBlock, DWORD nMaxLength)
{
	COMSTAT ComStat;
	DWORD dwErrorFlags,dwLength,endtime;
	OVERLAPPED os_read;
	MSG MyMesg;

	if(!fConnected) return(0);
	os_read.Offset = 0;
	os_read.OffsetHigh = 0;
	os_read.hEvent = CreateEvent( NULL,	// no security
								TRUE,	// explicit reset req
								FALSE,	// initial event reset
								NULL );	// no name
	if(os_read.hEvent == NULL) return(0);
	ClearCommError( hCom, &dwErrorFlags, &ComStat);

	dwLength = 0;
	if(!ReadFile(hCom, lpszBlock, nMaxLength, &dwLength, &os_read))
	{
		dwLength=0;
		if(GetLastError() == ERROR_IO_PENDING)
		{
			if(GetCommHwnd()!=NULL)
			{
				endtime=GetTickCount()+CommTimeOuts.ReadTotalTimeoutMultiplier*nMaxLength+CommTimeOuts.ReadTotalTimeoutConstant;
				while(!GetOverlappedResult(hCom, &os_read, &dwLength, FALSE))
				{
					if(PeekMessage(&MyMesg,NULL,0,0,PM_REMOVE))
					{
						TranslateMessage(&MyMesg);
						DispatchMessage(&MyMesg);
					}
					if(GetTickCount()>(endtime+100))
					{
						dwLength = 0;
						break;
					}
					Sleep(20);
				}
			}
			else
			{
				while(!GetOverlappedResult( hCom, &os_read, &dwLength, TRUE))
				{
					if(GetLastError() == ERROR_IO_INCOMPLETE)
					{
						os_read.Offset += dwLength;
						continue;
					}
					else 
					{
						dwLength = 0;
						break;
					}
				}
			}
		}
		else dwLength = 0;
		ResetEvent(os_read.hEvent);
	}
	ClearCommError( hCom, &dwErrorFlags, &ComStat);
	CloseHandle(os_read.hEvent);
	lpszBlock[dwLength] = 0;
	if(TraceFlag) CommTrace(Trace_File,lpszBlock,dwLength,TraceMode,1);
	return(dwLength);
}
/**********************************************************************
Function:   Write
Description:串口异步写
Input:		 lpszBlock-->串口数据缓冲指针;nMaxLength-->串口需写数据个数
return:     Fail-->false;Success-->true
***********************************************************************/
BOOL CCommDevice::Write(char *lpszBlock, DWORD dwBytesToWrite)
{
	DWORD       dwBytesWritten;
	DWORD       dwErrorFlags;
	DWORD       dwBytesSent;
	COMSTAT     ComStat;
	OVERLAPPED  os_write;

	dwBytesSent=0;
	if(!fConnected) return(FALSE);
	if(!dwBytesToWrite) return(TRUE);
	if(TraceFlag) CommTrace(Trace_File,lpszBlock,dwBytesToWrite,TraceMode,0);
	SetCommMask(hCom,0);
	PurgeComm(hCom,PURGE_TXCLEAR | PURGE_RXCLEAR);

	os_write.Offset=0;
	os_write.OffsetHigh=0;
	os_write.hEvent = CreateEvent( NULL,	// no security
								TRUE,		// explicit reset req
								FALSE,		// initial event reset
								NULL );		// no name
	if (os_write.hEvent == NULL) return(FALSE);

	if(!WriteFile( hCom, lpszBlock, dwBytesToWrite, &dwBytesWritten, &os_write ))
	{
		if(GetLastError() == ERROR_IO_PENDING)
		{
			while(!GetOverlappedResult( hCom, &os_write, &dwBytesWritten, TRUE ))
			{
				if(GetLastError() == ERROR_IO_INCOMPLETE)
				{
					dwBytesSent += dwBytesWritten;
					continue;
				}
				else
				{
					ClearCommError( hCom, &dwErrorFlags, &ComStat ) ;
					break;
				}
			}
			ResetEvent(os_write.hEvent);
			CloseHandle(os_write.hEvent);
			dwBytesSent += dwBytesWritten;
			if( dwBytesSent == dwBytesToWrite ) return(TRUE);
			else return(FALSE);
		}
		else
		{
			ClearCommError(hCom, &dwErrorFlags, &ComStat);
			ResetEvent(os_write.hEvent);
			CloseHandle(os_write.hEvent);
			return(FALSE);
		}
	}
	CloseHandle(os_write.hEvent);
	return(TRUE);
}
/**********************************************************************
Function:   ReadBlock
Description:串口同步读(阻塞方式读串口,直到串口缓冲区中没有数据--->
			 靠字符间间隔超时确定没有数据)
Input:		 pReadBuf-->串口数据缓冲指针
			 str_room-->串口数据缓冲空间大小;
			 ByteTime-->字节间隔最大时间(1--10000,default--300)
return:     从串口实际读入的字节个数
***********************************************************************/
int  CCommDevice::ReadBlock(char *pReadBuf,unsigned int str_room,DWORD ByteTime)
{

⌨️ 快捷键说明

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