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

📄 portctl.cpp

📁 一个简单实用的串口类
💻 CPP
字号:
// SerialCtl.cpp: implementation of the SerialCtl class.
//
//////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "PortCtl.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

SerialCtl::SerialCtl()
{
	hCom             = NULL;
	hCommWatchThread = NULL;
	memset(Data, 0, MAXNUM);
	DelayRead        = 1;
    CircleTimeSpan   = 1;
	OPEN_FLAG        = false;
	m_lParam         = 0;
}

void SerialCtl::SetSerial(CString Com, long Baud,  int Data, int End, CString Parity)
{	
	strcpy(Serial.COM, Com);
	Serial.BAUD = Baud;
	Serial.DATA = Data;
    Serial.END  = End-1;
	if ( Parity == "NONE" || Parity == "none" )
       Serial.PARITY = NOPARITY;
	else if ( Parity == "EVEN" || Parity == "even" )
       Serial.PARITY = EVENPARITY;
	else if ( Parity == "ODD" || Parity == "odd" )
       Serial.PARITY = ODDPARITY;
    else
       Serial.PARITY = NOPARITY;
}

void SerialCtl::CloseSerial()
{
	if ( m_OverWrite.hEvent != NULL )
	    CloseHandle(m_OverWrite.hEvent);
	if ( m_OverRead.hEvent != NULL )
	    CloseHandle(m_OverRead.hEvent);
	if ( hCommWatchThread != NULL )
	{
        TerminateThread(hCommWatchThread, 1);
		hCommWatchThread = NULL;
	}
	if ( hCom )
	{
       CloseHandle(hCom);
	   hCom = NULL;
	}
	OPEN_FLAG = false;
}

void SerialCtl::OpenSerial()
{
    DWORD ErrorFlag;

    memset(&m_OverWrite, 0, sizeof(OVERLAPPED));
    m_OverWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    memset(&m_OverRead, 0, sizeof(OVERLAPPED));
    m_OverRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);


    hCom = CreateFile(Serial.COM,
		              GENERIC_READ | GENERIC_WRITE,
		              0,
			          NULL,
			          OPEN_EXISTING,
			          FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
			          NULL
			         );
	if ( hCom == INVALID_HANDLE_VALUE )
	{
     //   AfxMessageBox("打开错误,看检查串口是否已经打开。");
		OPEN_FLAG = false;
	    return;
	}
	

	SetCommMask(hCom, EV_RXCHAR | EV_TXEMPTY); 
	PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
	SetupComm(hCom, INBUF, OUTBUF);
	GetCommState(hCom, &dcb);
//	dcb.fDtrControl = 0;
//	dcb.fRtsControl = 0;
//	dcb.fTXContinueOnXoff = 0;
    dcb.StopBits = Serial.END;
	dcb.BaudRate = Serial.BAUD;
	dcb.ByteSize = Serial.DATA;
    dcb.Parity   = Serial.PARITY;
    if ( !SetCommState(hCom, &dcb) )
	{
		AfxMessageBox("串口设置错误!");
		if ( hCom )
		{
			CloseHandle(hCom);
			hCom = NULL;
		}
		OPEN_FLAG = false;
		return;
	}

	ClearCommError(hCom, &ErrorFlag, &ComStat);

/*    memset(&m_OverWrite, 0, sizeof(OVERLAPPED));
    m_OverWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    memset(&m_OverRead, 0, sizeof(OVERLAPPED));
    m_OverRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
*/
	OPEN_FLAG = true;
}

void SerialCtl::ListenSerial(long delayRead, long circleTimeSpan)
{
	DelayRead      = delayRead;
	CircleTimeSpan = circleTimeSpan;
	hCommWatchThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
		                            0,
									(LPTHREAD_START_ROUTINE)hCommWatchPro,
                                    (LPVOID)this,
									0,
									(LPDWORD)&hCommWatchThread
								   );
    if ( hCommWatchThread == NULL )
	{
		AfxMessageBox("串口线程建立失败!");
		return;
	}
}

void SerialCtl::StopListenSerial()
{
    if ( hCommWatchThread != NULL )
	{
        TerminateThread(hCommWatchThread, 1);
		hCommWatchThread = NULL;
	}
}

BOOL SerialCtl::WriteSerial(const BYTE * SendData, const DWORD SendLen)
{
    BOOL   WriteFlag2;
	BOOL   bError = TRUE;
	DWORD  ErrorFlag;
	DWORD  ecode1, ecode2;
    DWORD  Len = SendLen;

//  while ( !HasOverlappedIoCompleted(&m_OverWrite) );
//	while ( ComStat.cbOutQue != 0 ){}
	ClearCommError(hCom, &ErrorFlag, &ComStat);
	WriteFlag2 = WriteFile(hCom, SendData, SendLen, 0, &m_OverWrite);
	if ( !WriteFlag2 )
	{
		ecode1 = GetLastError();
		if ( ecode1 == ERROR_IO_PENDING )
		{
			DWORD l;
			BOOL  f = FALSE;
			while ( !GetOverlappedResult(hCom, &m_OverWrite, &l, TRUE ) )
			{
				ecode2 = GetLastError();
			/*	if ( ecode2 == ERROR_OPERATION_ABORTED )
				{
                    TRACE("995\n");
					PurgeComm(hCom, PURGE_TXABORT|PURGE_TXCLEAR);
					f = TRUE;
					break;
				}
			*/	if ( ecode2 == ERROR_IO_INCOMPLETE )
				{
					f = FALSE;
					continue;
				}
				else
				{
					PurgeComm(hCom, PURGE_TXABORT|PURGE_TXCLEAR);
					f = TRUE;
					break;
				}
			//	Sleep(1);
			}
			if ( f == FALSE )
			{
				bError = FALSE;
			}
			else
			{
				bError = TRUE;
			}
		}
	}
	else
	{
		bError = FALSE;
	}
//	PurgeComm(hCom, PURGE_TXABORT|PURGE_TXCLEAR);
    return TRUE;
}
/*
void SerialCtl::ReadSerial(BYTE * resData, long * length)
{
	 DWORD ErrorFlag;
   	 DWORD      dwErrorFlags;
	 BOOL  ReadFlag = FALSE;
     int   len = 0;
	 memset(Data, 0, MAXNUM);
//     ClearCommError(hCom, &ErrorFlag, &ComStat);
//	 if ( ReadNum > 0 )
//	    len = ReadNum;
//	 else
	 {
	    if ( ComStat.cbInQue )
		    len = ComStat.cbInQue;
		else
		{
            resData = NULL;
			length = 0;
			return;
		}
    //  len = READBUFLEN;
	 }
	 * length = len;
     ReadFlag = ReadFile(hCom, Data, len, 0, &m_OverRead);
//	 TRACE("%ld\r\n",len);
     if ( !ReadFlag )
	 {
//		PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
        return;
	 }
	 memcpy(resData, Data, len);
 //	 ClearCommError(hCom, &dwErrorFlags, &ComStat);
//	 PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
//	 ComStat.cbInQue = 0;
	 // return &Data[0];
}
*/
int SerialCtl::ReadSerial2(BYTE * resData, int length)
{
     DWORD ErrorFlag;
     ClearCommError(hCom, &ErrorFlag, &ComStat);
	 if ( ComStat.cbInQue )
	 {
		 if ( ComStat.cbInQue >= length )
		 {
			 ReadFile(hCom, resData, length, 0, &m_OverRead);
			 return length;
		 }
		 else
		 {
			 int k=ComStat.cbInQue;
             ReadFile(hCom, resData, k, 0, &m_OverRead);
			 return k;
		 }
	 }
	 else
	 {
         resData = NULL;
	     return 0;
	 }     
}

void SerialCtl::ReadSerial(BYTE * resData, int * length)
{
	DWORD dwBytesRead;
    DWORD dwError;
    DWORD ErrorFlag;
	 BOOL  ReadFlag = FALSE;
     int   len = 0;
	 memset(Data, 0, MAXNUM);

     ClearCommError(hCom, &ErrorFlag, &ComStat);

	 if ( ComStat.cbInQue )
	     len = ComStat.cbInQue;
	 else
	 {
         resData = NULL;
	     length = 0;
		 return;
	 }
	 * length = len;
     ReadFlag = ReadFile(hCom, Data, len, 0, &m_OverRead);
     if ( !ReadFlag )
	 {
         if ( GetLastError() == ERROR_IO_PENDING )
		 {
             while ( !GetOverlappedResult(hCom, &m_OverRead, &dwBytesRead, TRUE ))
			 {
                 dwError = GetLastError();
                 if ( dwError == ERROR_IO_INCOMPLETE )
                    continue;
			 }
		 }
        return;
	 }
	 memcpy(resData, Data, len);
}

void SerialCtl::ClearSerialBuf()
{
//	DWORD      dwErrorFlags;
//	 ClearCommError(hCom, &dwErrorFlags, &ComStat);
     PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
     ComStat.cbInQue = 0;
}

bool SerialCtl::IsSerialOpen()
{
	return OPEN_FLAG;
}

CString SerialCtl::GetVersion()
{
    return "当前串口通讯模块版本:2.0   2004-2005 RT-Hou.Ke";
}

float SerialCtl::GetVer()
{
    return 2.0f;
}

BOOL SerialCtl::isCanSend()
{	
    if ( ComStat.cbOutQue )
		return TRUE;
	else
		return FALSE;
}

/*
UINT hCommWatchPro(LPVOID pParam)
{
	SerialCtl * wnd = (SerialCtl *)pParam;
    OVERLAPPED os;
	DWORD      dwMask = 0,
		       dwTrans;
	DWORD      dwErrorFlags;
	DCB        dcb;

	memset(&os, 0, sizeof(OVERLAPPED));
	os.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if ( os.hEvent == NULL )
	{
		AfxMessageBox("辅助线程事件建立错误!");
        return -1;
	}
	while ( wnd->hCom != INVALID_HANDLE_VALUE )
	{
        //GetCommState(wnd->hCom, &dcb);
        //if ( dcb.fAbortOnError )
		ClearCommError(wnd->hCom, &dwErrorFlags, &wnd->ComStat);

        if ( wnd->ComStat.cbInQue )
		{
	//		ClearCommError(wnd->hCom, &dwErrorFlags, &wnd->ComStat);
			if ( !WaitCommEvent(wnd->hCom, &dwMask, &os) )
			{
                if ( GetLastError() == ERROR_IO_PENDING )
				    GetOverlappedResult(wnd->hCom, &os, &dwTrans, TRUE);
			    //else
				//{
				 //   AfxMessageBox("GetLastError() != ERROR_IO_PENDING");
                 //   CloseHandle(os.hEvent);
				 //   return -1;
			//	}/
			}
		    Sleep(1000);//wnd->DelayRead);

		    AfxGetMainWnd()->PostMessage(WM_SERIALGET, 0, wnd->m_lParam);

//			ClearCommError(wnd->hCom, &dwErrorFlags, &wnd->ComStat);

		//	static long i=0;
		//	TRACE("..................%d...................\r\n", ++i);
		//	if (i>10000) i = 0;
		}
		Sleep(wnd->CircleTimeSpan);
	}
	CloseHandle(os.hEvent);
	return 0;
}
*/


UINT hCommWatchPro(LPVOID pParam)
{
	SerialCtl * wnd = (SerialCtl *)pParam;
    OVERLAPPED os;
	DWORD      dwMask = 0;
    DWORD      dwErrorFlags; 
	DWORD      dwEvtMask = 0;

	memset(&os, 0, sizeof(OVERLAPPED));
	os.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if ( os.hEvent == NULL )
	{
		AfxMessageBox("辅助线程事件建立错误!");
        return -1;
	}

    SetCommMask(wnd->hCom, EV_RXCHAR|EV_TXEMPTY); // 串口事件监视

	while ( wnd->hCom != INVALID_HANDLE_VALUE )
	{
		WaitCommEvent(wnd->hCom, &dwEvtMask, &os);  // 等待串口通信事件的发生
        if ( (dwEvtMask & EV_RXCHAR) == EV_RXCHAR ) // 缓冲区有数据
		{
            ClearCommError(wnd->hCom, &dwErrorFlags, &wnd->ComStat);
            if ( wnd->ComStat.cbInQue ) // 缓冲区数据个数
			{
		        Sleep(wnd->DelayRead);
		        AfxGetMainWnd()->PostMessage(WM_SERIALGET, 0, wnd->m_lParam);
			}
		}
	    Sleep(wnd->CircleTimeSpan);
	}
	CloseHandle(os.hEvent);
	return 0;
}

⌨️ 快捷键说明

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