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

📄 mutithreadserial.cpp

📁 动态库(dll)中建立串口监视线程的实时串口通信
💻 CPP
字号:
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "MutithreadSerial.h"
//#include "O231BatteryDevDef.h"

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

MutithreadSerial::MutithreadSerial()
{
	bCommConnected = false;//端口连接标志
	iBaud = 9600;          //初始化波特率
	m_iWhichCommand = 0;   //初始化命令标志
	memset(this->m_bReData,0x00,sizeof(this->m_bReData));
	m_iRevLen = 0;         //初始化接收长度
	Com1IsOpen = false;
	Com2IsOpen = false;
	bCommRxSign = false;
	m_bShakeHandFlag = false;
}
MutithreadSerial::~MutithreadSerial()
{

}
UINT jThreadFunction(LPVOID lpParam) 
{
	//线程函数主体,监视串口
	MutithreadSerial *pComm = ( MutithreadSerial*)lpParam;
	OVERLAPPED os;
	DWORD dwEventMask, dwTransfer;
	DWORD dwErrorFlags;
	COMSTAT ComStat;
	memset(&os, 0, sizeof(OVERLAPPED));
	os.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //FALSE: nonsignaled
	if (os.hEvent == NULL)
	{
		return FALSE;
	}
	if (!SetCommMask(pComm->hCom, EV_RXCHAR)) 
		return FALSE;
	//Loop until user requests disconnect
	while (pComm->bCommConnected)
	{
		ClearCommError(pComm->hCom, &dwErrorFlags, &ComStat);
		if(ComStat.cbInQue)
		{
			pComm->bCommRxSign = true;
			ResetEvent(pComm->hPostMsgEvent);
			pComm->OnCommRecvNotify(0,0);
			WaitForSingleObject(pComm->hPostMsgEvent, 0xFFFFFFFF);
			continue;
		}
		dwEventMask = 0;
		if (!WaitCommEvent(pComm->hCom, &dwEventMask, &os))// dwEventMask: receive event
		{
			//WaitCommEvent()没有等到结果,如果ERROR_IO_PENDING == GetLastError()
			//就用GetOverlappedResult()来等待。
			if (ERROR_IO_PENDING == GetLastError())
			{
				GetOverlappedResult(pComm->hCom, &os, &dwTransfer, TRUE); //dwTransfer:actual bytes count
				//TRUE:If TRUE, the function does not return until the operation has been completed. 
			}
		}
		if ((dwEventMask & EV_RXCHAR) == EV_RXCHAR)
		{
			//Sets the state of the event to nonsignaled until explicitly set to signaled by the SetEvent member function. 
			pComm->bCommRxSign = true;
			ResetEvent(pComm->hPostMsgEvent);
			pComm->OnCommRecvNotify(0, 0);
			WaitForSingleObject(pComm->hPostMsgEvent, 0xFFFFFFFF);	
		}
	}
	CloseHandle(os.hEvent);
	return TRUE;
}

bool MutithreadSerial::InitComm(bool bDefault, int p_iCom , HWND p_hwnd)
{
  this->m_hwnd231 = p_hwnd; //是主程序的窗口句柄,此参数必须传入,否则数据不能
  //响应到主程序中去
  CString    l_sCommPort;
  l_sCommPort.Format( "COM%d", p_iCom );
  HANDLE l_hCom = CreateFile(l_sCommPort, GENERIC_READ|GENERIC_WRITE, 0, NULL,
		OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
		NULL); //以重叠I/O的形式打开串口
    this->hCom = l_hCom;
	if(hCom == INVALID_HANDLE_VALUE)
	{
		bCommOpenOk=false;
		return false;
	}
	SetupComm(hCom, 4096, 4096);
	COMMTIMEOUTS CommTimeOuts;
	GetCommTimeouts(hCom, &CommTimeOuts);
	if(!SetCommMask(hCom, EV_RXCHAR))
	{
		return false;
	}
	CommTimeOuts.ReadIntervalTimeout            =   MAXDWORD;
	CommTimeOuts.ReadTotalTimeoutMultiplier	    =	0;//20;
	CommTimeOuts.ReadTotalTimeoutConstant		=	0;//1000;
	CommTimeOuts.WriteTotalTimeoutMultiplier = 0;//20;
	CommTimeOuts.WriteTotalTimeoutConstant = 5000;//1000
	SetCommTimeouts(hCom, &CommTimeOuts);

    DCB Dcb;
	Dcb.DCBlength = sizeof(DCB);
	GetCommState(hCom, &Dcb);
	if(bDefault)
	{
		Dcb.BaudRate = iBaud;
		Dcb.ByteSize = 8;
		//注意:260是无校验,230是MARKPARITY
		Dcb.Parity = MARKPARITY;//NOPARITY;
		Dcb.StopBits = ONESTOPBIT;
		Dcb.fOutxDsrFlow = false;
		Dcb.fOutxCtsFlow = false;
		Dcb.fDtrControl = RTS_CONTROL_DISABLE;
		Dcb.fRtsControl = RTS_CONTROL_DISABLE;
		Dcb.fInX = false;
			Dcb.fOutX = false;
	}
	else
	{
		Dcb.BaudRate = CommDcb.BaudRate;
		Dcb.ByteSize = CommDcb.ByteSize;
		Dcb.Parity = CommDcb.Parity;
		Dcb.StopBits = CommDcb.StopBits;
	}
	Dcb.fBinary = TRUE;
	Dcb.fParity = TRUE;
	Dcb.wReserved  = 0;
	if(!SetCommState(hCom,&Dcb))
		return false;
	if((hPostMsgEvent = CreateEvent(NULL, TRUE, TRUE, NULL))==NULL) //有信号状态
		return FALSE;
	PurgeComm( hCom, PURGE_RXCLEAR | PURGE_TXABORT |PURGE_TXCLEAR| PURGE_RXABORT); 
	bCommOpenOk = true;
	if(p_iCom == 1)
	{
		Com1IsOpen = true;
	}
	if(p_iCom == 2)
	{
		Com2IsOpen = true;
	}
	return true;
}

DWORD MutithreadSerial::WriteComm(unsigned char *buf, DWORD dwLength)
{
	BOOL fState;
    DWORD l_dwRes; 
	DWORD length = dwLength;
	COMSTAT ComStat;
	DWORD dwErrorFlags = 0;
	OVERLAPPED  osWrite = {0} ; 
	if((osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL))==NULL)
	{
	    length = 0;
		return length;
	}
	ClearCommError(hCom, &dwErrorFlags, &ComStat);
	fState = WriteFile(hCom, buf, length, &length, &osWrite);
	if(!fState)
	{
		if(GetLastError() == ERROR_IO_PENDING)
		{
				l_dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);
				switch(l_dwRes)
				{
					case WAIT_OBJECT_0:	
						if (!GetOverlappedResult(hCom, &osWrite, &length, FALSE))
						{
							length = 0;                 
						}
						else
						{
							 
							 return length;

						}
						break;            
					default:
						length = 0;
						break;  
				}
		}
		else
		length = 0;
	}
	return length;	
}

DWORD MutithreadSerial::ReadComm(unsigned char *buf, DWORD dwLength)
{
	DWORD length = 0;
	COMSTAT ComStat;
	DWORD dwErrorFlags;
	Sleep(250);
	ClearCommError(hCom, &dwErrorFlags, &ComStat);
	length = min(dwLength, ComStat.cbInQue);
	ReadFile(hCom, buf, length, &length, &osRead);
	return length;
}
/////////////////////////////////////////////////////////////
void MutithreadSerial::CloseComm()
{
	bCommConnected = FALSE;
	bCommOpenOk = false;
	SetCommMask(hCom, 0);
	 
	EscapeCommFunction(hCom, CLRDTR);
	PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT |
						  PURGE_TXCLEAR | PURGE_RXCLEAR);
	CloseHandle(hCom);
	pThread = NULL;

}

bool MutithreadSerial::BeginComm()
{
	bool fRetVal;
	if (!bCommOpenOk) return false;
	bCommConnected = true;

	if((pThread = AfxBeginThread(jThreadFunction, this)) == NULL)
	{
		bCommConnected = false;
		CloseHandle(hCom);
		fRetVal = FALSE;
		return fRetVal;
	}
	else	
	{
		//函数会建立一个辅助线程并暂时将其挂起。
		//调用CWinThread:: ResumeThread使线程开始运行
		pThread->SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
		pThread->ResumeThread();
		EscapeCommFunction(hCom, SETDTR);
	}
		return TRUE;
}

bool MutithreadSerial::ChangeBaud()
{
	//此函数现在没有用到。
	if(hCom==NULL)
		return false;
	COMMTIMEOUTS CommTimeOuts;
	GetCommTimeouts(hCom, &CommTimeOuts);
	if(!SetCommMask(hCom, EV_RXCHAR))
	{
		return false;
	}
	SetupComm(hCom, 4096, 4096);
	CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
	CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
	CommTimeOuts.ReadTotalTimeoutConstant = 0;
	CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
	CommTimeOuts.WriteTotalTimeoutConstant = 5000;
	SetCommTimeouts(hCom, &CommTimeOuts);

	DCB Dcb;
	Dcb.DCBlength = sizeof(DCB);
	GetCommState(hCom,&Dcb);
	Dcb.BaudRate=iBaud;
	Dcb.ByteSize=8;
	Dcb.Parity=NOPARITY;
	Dcb.StopBits=ONESTOPBIT;
	Dcb.fOutxDsrFlow = false;
	Dcb.fOutxCtsFlow = false;
	Dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
	Dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
	Dcb.fInX = Dcb.fOutX = false;
	//Dcb.XonChar = ASCII_XON;
	//Dcb.XoffChar = ASCII_XOFF;
	Dcb.XonLim = 100;
	Dcb.XoffLim = 100;
	Dcb.fBinary = TRUE;
	Dcb.fParity = TRUE;
	if(!SetCommState(hCom,&Dcb))
		return false;
	return true;
}
void MutithreadSerial::OnCommRecvNotify(WPARAM wParam, LPARAM lParam)
{
	//取得数据缓冲
	this->iCommGetCounter = ReadComm((unsigned char *)sCommGetBuffer,COMM232GETDATAMAX);
	if(this->iCommGetCounter == 0)
    { 
		SetEvent(hPostMsgEvent);   //根本就没有取到数据,所以返回
		return;
	}
	MutithreadSerial *p_Comm = this;
	memset(m_bReData, 0x00, sizeof(m_bReData)); //每一次都必须初始化
    memcpy(this->m_bReData, sCommGetBuffer, this->iCommGetCounter*sizeof(BYTE)); 
	memset(sCommGetBuffer, 0x00, COMM232GETDATAMAX * sizeof(BYTE)); //清空接收缓冲
	if(this->m_bReData[2] == 0x88)//通信协议制定的。
	{
	   //是主动上传的数据
       ::SendMessage(p_Comm->m_hwnd231, WM_ACTIVE_TRANS, 0, 0);
	   Sleep(3);
	}
    else//查询方式的返回
	{   
   		::SendMessage(p_Comm->m_hwnd231, WM_SEND_AND_RETURN,  0, 0);
		Sleep(3);
	}
	//允许发送下一个WM_COMMNOTIFY消息
	SetEvent(hPostMsgEvent); 
}

⌨️ 快捷键说明

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