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

📄 ceseries.cpp

📁 实现了EVC操作串口的功能。比较不错的参考源码
💻 CPP
字号:
// CEseries.cpp : implementation file
//

#include "stdafx.h"
#include "CcerisePort.h"
#include "CEseries.h"

#ifdef _DEBUG
//#define new DEBUG_NEW@
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CCEseries
IMPLEMENT_DYNCREATE(CCEseries, CCmdTarget)

CCEseries::CCEseries()
{
	m_hcomm = INVALID_HANDLE_VALUE;
}

CCEseries::~CCEseries()
{
}


BEGIN_MESSAGE_MAP(CCEseries, CCmdTarget)
	//{{AFX_MSG_MAP(CCEseries)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCEseries message handlers


bool CCEseries::CloseProt()
{
	if(m_hcomm == INVALID_HANDLE_VALUE)
	{
		return TRUE;
	}
	CloseReadThread();
	//CloseWriteThread();
	if(!CloseHandle(m_hcomm))
	{
		return FALSE;
	}
	else
	{   m_hcomm = INVALID_HANDLE_VALUE;
		return TRUE;
	}

}

void CCEseries::CloseReadThread()
{
	
	SetEvent(m_hreadcloseEvent);

	SetCommMask(m_hcomm,0);
	PurgeComm(m_hcomm,PURGE_RXCLEAR);
	if(WaitForSingleObject(m_hreadThread,1000) == WAIT_TIMEOUT)
	{
		TerminateThread(m_hreadThread,0);
	}
	m_hreadThread = NULL;

}

bool CCEseries::OpenProt(CWnd *pProtOwner, UINT ProtNo, UINT baud,UINT parity,UINT databits,UINT stopBITS)
{
	DCB dcb;
	char szProt[15];
	
	//已经打开直接返回
	if(m_hcomm != INVALID_HANDLE_VALUE)
	{
		return TRUE;
	}
    
	ASSERT(pProtOwner != NULL);
	ASSERT(ProtNo>0 && ProtNo<5);

	//设置串口名字
	sprintf(szProt,"COM%d",ProtNo);

	//打开串口
	m_hcomm = CreateFile(
		szProt,
	    GENERIC_READ|GENERIC_WRITE,
        0,
		0,
		OPEN_EXISTING,
		FILE_FLAG_OVERLAPPED,
		0);
	   
		if(m_hcomm == INVALID_HANDLE_VALUE)
		{
			TRACE(_T("CreateFile返回无效句柄"));
			return FALSE;
		}
		dcb.BaudRate = baud;     //波特率
		dcb.fBinary  = TRUE;     //必须为TRUE,支持2进制
		dcb.fParity  = TRUE;     //支持校验
		dcb.ByteSize = databits;    //数据位
		dcb.Parity   = ODDPARITY;    //奇校验
		dcb.StopBits = stopBITS;    //停止位
		
		dcb.fOutxCtsFlow = FALSE;    // No CTS output flow control 
		dcb.fOutxDsrFlow = FALSE;    // No DSR output flow control 
		dcb.fDtrControl = DTR_CONTROL_ENABLE; // DTR flow control type 
		dcb.fDsrSensitivity = FALSE;   // DSR sensitivity 
		dcb.fTXContinueOnXoff = TRUE;   // XOFF continues Tx 
		dcb.fOutX = FALSE;      // No XON/XOFF out flow control 
		dcb.fInX = FALSE;      // No XON/XOFF in flow control 
		dcb.fErrorChar = FALSE;     // Disable error replacement 
		dcb.fNull = FALSE;      // Disable null stripping 
		dcb.fRtsControl = RTS_CONTROL_ENABLE; // RTS flow control 
		dcb.fAbortOnError = FALSE; // 当串口发生错误,并不终止串口读写


		if(!GetCommState(m_hcomm,&dcb))
		{
			int Error = GetLastError();
			TRACE(_T("SetCommState erroe"));
			return FALSE;
		}
		//设置串口读写时间
        COMMTIMEOUTS Commtimeouts;
		GetCommTimeouts(m_hcomm,&Commtimeouts);


		Commtimeouts.ReadIntervalTimeout = MAXDWORD;  
		Commtimeouts.ReadTotalTimeoutMultiplier = MAXDWORD;  
		Commtimeouts.ReadTotalTimeoutConstant = 50;    
		Commtimeouts.WriteTotalTimeoutMultiplier = 50;  
		Commtimeouts.WriteTotalTimeoutConstant = 2000;
		
		if(!SetCommTimeouts(m_hcomm,&Commtimeouts))
		{
			AfxMessageBox("设置超时失败");
			return FALSE;
		}


		m_portowner=pProtOwner;

		//指定端口事件
		SetCommMask(m_hcomm,EV_RXCHAR);

		//分配设备内存
		SetupComm(m_hcomm,4096,4096);

		//清除缓存信息
		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,ReadTheadFun,this,0,
	          	&m_hreadThreadID);
    
        //创建写线程
		//m_hwriteThread = CreateThread(NULL,0,WriteThreadFunc,this,0,
		//	&m_hwriteThreadID);

		TRACE(_T("串口打开成功"));

		return TRUE;

}

DWORD  CCEseries::WriteThreadFunc(LPVOID lparme)
{
	CCEseries *cEseries = (CCEseries*)lparme;
	MSG msg;
	DWORD dwWriteLen = 0;
	BYTE *buf = NULL;
	
	
	while(TRUE)
	{
		//得到线程消息
		
		if(PeekMessage(&msg,0,0,0,PM_NOREMOVE))
		{
			if(msg.hwnd != 0)
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
				continue;
			}
			if(msg.message == CM_THREADCOMMWRITE)
			{
				buf = (BYTE*)msg.lParam;
				dwWriteLen = msg.wParam;
				try 
				{
					WriteProt(cEseries->m_hcomm,buf,dwWriteLen);
				}catch(...)
				{
					//
				}
				//delete [] buf;
			}
		}
		if(WaitForSingleObject(cEseries->m_hreadcloseEvent,500) ==
			WAIT_OBJECT_0)
		{
			break;
		}
		cEseries->m_hreadThread = NULL;
	
	}
	return 0;

}

DWORD  CCEseries::ReadTheadFun(LPVOID lparam)
{
		
	CCEseries *Ceseries=(CCEseries*)lparam;
	
	DWORD evtMask = 0; 
	BYTE *Readbuf = NULL;//
	DWORD ActualReadLen = 0;
	DWORD WillReadLen;
	
	DWORD dwReadErrors;
	COMSTAT cmstate;
	OVERLAPPED osReader = {0};

	

   BOOL bResult = TRUE;
	

	
	
    ASSERT(Ceseries->m_hcomm != INVALID_HANDLE_VALUE);
	PurgeComm(Ceseries->m_hcomm,PURGE_TXCLEAR|PURGE_RXCLEAR);
	AfxMessageBox("串口没有数据1");

	Sleep(2000);
	
    
	SetCommMask(Ceseries->m_hcomm,EV_RXCHAR|EV_CTS|EV_DSR);

	osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (osReader.hEvent == NULL)
	{
		AfxMessageBox("错误");
	}
   // Error creating overlapped event; abort.
   ResetEvent(osReader.hEvent);
	
	

	while(TRUE)
		
	{  
		bResult = WaitCommEvent(Ceseries->m_hcomm,&evtMask,&osReader);
		
		if(!bResult)
		{   
			switch(dwReadErrors = GetLastError())
			{
			case  ERROR_IO_PENDING:
				{
					Sleep(2000);
					AfxMessageBox("串口没有数据");
					break;
				}
			case 87:
				{   Sleep(2000);
					
					AfxMessageBox("串口系统错误");
					break;
				}
			default:
				{
					AfxMessageBox("串口其他错误");
					Sleep(2000);
					
					break;
				}
			}
		}
		else
		{
		
			if((evtMask & EV_RXCHAR) == EV_RXCHAR)
			{
				ClearCommError(Ceseries->m_hcomm,&dwReadErrors,&cmstate);
				WillReadLen = cmstate.cbInQue;
				
				if(WillReadLen<=0)
				{
					continue;
				}
				
				Readbuf = new BYTE[WillReadLen];

			//	DWORD dwRead;
				DWORD dwRes;
                BOOL fWaitingOnRead = FALSE;
                OVERLAPPED asReader = {0};

				// Create the overlapped event. Must be closed before exiting
				// to avoid a handle leak.
				asReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
				ASSERT(osReader.hEvent != NULL);
                
				if (!fWaitingOnRead) 
				{
				 // Issue read operation.
					if (!ReadFile(Ceseries->m_hcomm, Readbuf, WillReadLen, &ActualReadLen, &osReader)) 
					{
					      if (GetLastError() != ERROR_IO_PENDING) 
						  {// read not delayed?
								// Error in communications; report it.
								AfxMessageBox("错误");
						  }
						  else
						  {
						     fWaitingOnRead = TRUE;
						  }
						
						
					}
					else
					{
						AfxMessageBox("成功读数据");
					}
				}
					
				if (fWaitingOnRead) 
				{
					dwRes = WaitForSingleObject(osReader.hEvent, 500);
					switch(dwRes)
					{
							// Read completed.
					    case WAIT_OBJECT_0:
							if (!GetOverlappedResult(Ceseries->m_hcomm, &osReader, &ActualReadLen, FALSE))
								// Error in communications; report it.
								AfxMessageBox("错误");
								else
								AfxMessageBox("成功");
								if(ActualReadLen>0)
								{
									//回调函数启动
									Ceseries->m_OnSeriseRead(Ceseries->m_portowner,Readbuf,
										ActualReadLen);
								}
								//  Reset flag so that another opertion can be issued.
								fWaitingOnRead = FALSE;
								break;
							
						case WAIT_TIMEOUT:
							// Operation isn't complete yet. fWaitingOnRead flag isn't
							// changed since I'll loop back around, and I don't want
							// to issue another read until the first one finishes.
							//
							// This is a good time to do some background work.
							break;                       
							
						default:
							// Error in the WaitForSingleObject; abort.
							// This indicates a problem with the OVERLAPPED structure's
							// event handle.
							break;
						}
					}
					
				}

				//ReadFile(Ceseries->m_hcomm,Readbuf,WillReadLen,&ActualReadLen,0);
				
				
			}
		

		//如果接收到读线程退出信号则退出
		if(WaitForSingleObject(Ceseries->m_hreadcloseEvent,500) ==
		   WAIT_OBJECT_0)
		{
			break;
		}
	}
	
	
	CloseHandle(osReader.hEvent);

 
	return 0;
}

BOOL CCEseries::WriteProt(HANDLE hcomm, const BYTE *buf, DWORD buflen)
{
	OVERLAPPED osWrite = {0};
	// Create this write operation's OVERLAPPED structure's hEvent.
	osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (osWrite.hEvent == NULL)
	{
		// error creating overlapped event handle
		return FALSE;
	}
	
	
	DWORD dwNumByteWrite =0;
	bool fRes;
	DWORD dwRes;
	DWORD dwHaveByteWrite = 0;
	ASSERT(hcomm != INVALID_HANDLE_VALUE);
	
    //AfxMessageBox("准备发送");
	if(!WriteFile(hcomm,buf,buflen,&dwNumByteWrite,&osWrite))
	{
		if(GetLastError() != ERROR_IO_PENDING) 
		{ 
			// WriteFile failed, but isn't delayed. Report error and abort.
			fRes = FALSE;
		}
		// // Write is pending
		else
		{
			dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);
			
			switch(dwRes)
			{
				// OVERLAPPED structure's event has been signaled. 
			case WAIT_OBJECT_0:
				if (!GetOverlappedResult(hcomm, &osWrite, &dwNumByteWrite, FALSE))
						fRes = FALSE;
				else
					// Write operation completed successfully.
					// dwHaveByteWrite = dwHaveByteWrite+dwNumByteWrite;
					//写入完成
				//AfxMessageBox("数据发送");
			//	Sleep(2000);
				fRes = TRUE;
				break;
				
            default:
				// An error has occurred in WaitForSingleObject.
				// This usually indicates a problem with the
                // OVERLAPPED structure's event handle.
				fRes = FALSE;
				break;
			}
		}
	}
	
	else
		fRes =  TRUE;
    

	CloseHandle(osWrite.hEvent);
	return fRes;		


}
 

 BOOL CCEseries::WritePort(const BYTE *buf, DWORD buflen)
{
		//将要发的消息传到消息队列中
	if(PostThreadMessage(m_hwriteThreadID,CM_THREADCOMMWRITE,
		WPARAM(buflen),WPARAM(buf)))
	{
		return TRUE;
	}
	//int Error =  GetLastError();
	return FALSE;
	

}

BOOL CCEseries::SetSeriesTimeout(COMMTIMEOUTS CommTimeout)
{
	
	ASSERT(m_hcomm = INVALID_HANDLE_VALUE);
	return SetCommTimeouts(m_hcomm,&CommTimeout);

}

void CCEseries::CloseWriteThread()
{
	SetEvent(m_hwritecloseEvent);
	//SetCommMask(m_hcomm,0);
	PurgeComm(m_hcomm,PURGE_RXCLEAR);
	if(WaitForSingleObject(m_hwriteThread,10000) == WAIT_TIMEOUT)
	{
		TerminateThread(m_hwriteThread,0);
	}
	m_hwriteThread = NULL;
}





BYTE *  CCEseries::CRC(BYTE CrcSrcCode[], int CodeLength)
{
	      
	        unsigned short CRC_Code[]={0x0000, 0x1189, 0x2312,
			0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a,
			0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393,
			0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb,
			0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210,
			0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58,
			0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291,
			0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9,
			0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116,
			0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e,
			0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197,
			0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf,
			0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014,
			0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c,
			0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095,
			0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd,
			0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a,
			0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52,
			0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b,
			0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3,
			0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618,
			0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50,
			0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699,
			0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1,
			0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e,
			0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956,
			0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704, 0xf59f,
			0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7,
			0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c,
			0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854,
			0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d,
			0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5,
			0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78}; //CRC_Code[]数组就是一个余数表
     
	WORD fcs = 0xFFFF;
	int i = 0;
	while (CodeLength > 2)
	{
		fcs = ((fcs >> 8) ^ CRC_Code[(fcs ^ CrcSrcCode[i]) & 0xff]);
		CodeLength--;
		i++;
	}
	fcs = ~fcs; // ---
	CrcSrcCode[i++] = (byte) (fcs & 0xFF);
	CrcSrcCode[i] = (byte) ((fcs >> 8) & 0xFF);
	
	return CrcSrcCode;
}

BYTE* CCEseries::GetaddtoCrc(BYTE *data, int len)
{

	BYTE *SendBuff = new BYTE[len+2];
	ZeroMemory(SendBuff, len+2);
	for(int i =0;i<len;i++)
	{
		SendBuff[i] = data[i];
	}
    BYTE * CommandAddCRC = NULL;
    CommandAddCRC  = CRC(SendBuff,len+2);
   
    return  CommandAddCRC; 

}


⌨️ 快捷键说明

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