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

📄 chuankoudlg.cpp

📁 自己做的EVC下串口调试软件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
}


BOOL CChuankouDlg::OpenPort2(CWnd* pPortOwner,
						 UINT portNo	,			/*串口号*/
						 UINT baud		,			/*波特率*/
						 UINT parity	,			/*奇偶校验*/
						 UINT databits	,			/*数据位*/
						 UINT stopbits			   /*停止位*/
						 )
{
	
	DCB commParam;
	TCHAR szPort[15];	
	
	// 已经打开的话,直接返回
	if (m_hComm2 != INVALID_HANDLE_VALUE)
	{
		return TRUE;
	}
	ASSERT(pPortOwner != NULL);
	ASSERT(portNo > 0 && portNo < 5);
	
	//设置串口名
	wsprintf(szPort, L"COM%d:", portNo);
	//打开串口
	m_hComm2 = CreateFile(
		szPort,
		GENERIC_READ | GENERIC_WRITE,	//允许读和写
		0,								//独占方式(共享模式)
		NULL,
		OPEN_EXISTING,					//打开而不是创建(创建方式)
		0,
		NULL 
		);
	
	if (m_hComm2 == INVALID_HANDLE_VALUE)
	{
		// 无效句柄,返回。		
		TRACE(_T("CreateFile 返回无效句柄"));
		return FALSE;
		
	}
	
	// 得到打开串口的当前属性参数,修改后再重新设置串口。
	// 设置串口的超时特性为立即返回。
	
	if (!GetCommState(m_hComm2,&commParam))
	{		
		return FALSE;
	}
	
	commParam.BaudRate = baud;					// 设置波特率 
	commParam.fBinary = TRUE;					// 设置二进制模式,此处必须设置TRUE
	commParam.fParity = TRUE;					// 支持奇偶校验 
	commParam.ByteSize = databits;				// 数据位,范围:4-8 
	commParam.Parity = NOPARITY;				// 校验模式
	commParam.StopBits = stopbits;			  	// 停止位 
	
	commParam.fOutxCtsFlow = FALSE;				// No CTS output flow control 
	commParam.fOutxDsrFlow = FALSE;				// No DSR output flow control 
	commParam.fDtrControl = DTR_CONTROL_ENABLE; 
	// DTR flow control type 
	commParam.fDsrSensitivity = FALSE;			// DSR sensitivity 
	commParam.fTXContinueOnXoff = TRUE;			// XOFF continues Tx 
	commParam.fOutX = FALSE;					// No XON/XOFF out flow control 
	commParam.fInX = FALSE;						// No XON/XOFF in flow control 
	commParam.fErrorChar = FALSE;				// Disable error replacement 
	commParam.fNull = FALSE;					// Disable null stripping 
	commParam.fRtsControl = RTS_CONTROL_ENABLE; 
	// RTS flow control 
	commParam.fAbortOnError = FALSE;			// 当串口发生错误,并不终止串口读写
	
	if (!SetCommState(m_hComm2, &commParam))
	{
		TRACE(_T("SetCommState error"));		
		return FALSE;
	}
	
	
    //设置串口读写时间
	COMMTIMEOUTS CommTimeOuts;
	GetCommTimeouts (m_hComm2, &CommTimeOuts);
	CommTimeOuts.ReadIntervalTimeout = MAXDWORD;  
	CommTimeOuts.ReadTotalTimeoutMultiplier = 0;  
	CommTimeOuts.ReadTotalTimeoutConstant = 0;    
	CommTimeOuts.WriteTotalTimeoutMultiplier = 10;  
	CommTimeOuts.WriteTotalTimeoutConstant = 1000;  
	
	if(!SetCommTimeouts( m_hComm2, &CommTimeOuts ))
	{
		TRACE( _T("SetCommTimeouts 返回错误") );
		return FALSE;
	}
	
	m_pPortOwner = pPortOwner;	
	
	//指定端口监测的事件集
	SetCommMask (m_hComm2, EV_RXCHAR);
	
	//分配设备缓冲区
	SetupComm(m_hComm2,1024,1024);
	
	//初始化缓冲区中的信息
	PurgeComm(m_hComm2,PURGE_TXCLEAR|PURGE_RXCLEAR);
	
	m_hReadCloseEvent2 = CreateEvent(NULL,TRUE,FALSE,NULL);
//	m_hWriteCloseEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
	//创建读串口线程
	m_hReadThread2 = CreateThread(NULL,0,ReadThreadFunc2,this,0,&m_dwReadThreadID);
	//创建写串口线程
//	m_hWriteThread = CreateThread(NULL,0,WriteThreadFunc,this,0,&m_dwWriteThreadID);
	
	TRACE(_T("串口打开成功"));
	
	return TRUE;
}




//串口读线程函数
DWORD CChuankouDlg::ReadThreadFunc1(LPVOID lparam)
{
	CChuankouDlg *ceSeries = (CChuankouDlg*)lparam;
	
	DWORD	evtMask;
	BYTE * readBuf = NULL;//读取的字节
	DWORD actualReadLen=0;//实际读取的字节数
	DWORD willReadLen;
	
	DWORD dwReadErrors;
	COMSTAT	cmState;
	
	// 清空缓冲,并检查串口是否打开。
	ASSERT(ceSeries->m_hComm1 !=INVALID_HANDLE_VALUE); 
	
//	AfxMessageBox(_T("1"));
	//清空串口
	PurgeComm(ceSeries->m_hComm1, PURGE_RXCLEAR | PURGE_TXCLEAR );
	
	SetCommMask (ceSeries->m_hComm1, EV_RXCHAR | EV_CTS | EV_DSR );
	while (TRUE)
	{   	
		if (WaitCommEvent(ceSeries->m_hComm1,&evtMask,0))
		{			
			SetCommMask (ceSeries->m_hComm1, EV_RXCHAR | EV_CTS | EV_DSR );
			//表示串口收到字符		
			if (evtMask & EV_RXCHAR) 
			{
			//	AfxMessageBox(_T("3"));
				ClearCommError(ceSeries->m_hComm1,&dwReadErrors,&cmState);
				willReadLen = cmState.cbInQue ;
				if (willReadLen <= 0)
				{
					continue;
				}
				
				readBuf = new BYTE[willReadLen];
				ReadFile(ceSeries->m_hComm1, readBuf, willReadLen, &actualReadLen,0);
				
				//如果读取的数据大于0,
				if (actualReadLen>0)
				{
				//	ceSeries->read(ceSeries->m_pPortOwner,readBuf,actualReadLen);
				//	AfxMessageBox(_T("ol"));
					//触发读取回调函数
					ceSeries->OnSeriesRead1(ceSeries->m_pPortOwner,readBuf,actualReadLen);
				//	AfxMessageBox(_T("ol"));
				}
			}
		}
		//如果收到读线程退出信号,则退出线程
		if (WaitForSingleObject(ceSeries->m_hReadCloseEvent1,500) == WAIT_OBJECT_0)
		{//	AfxMessageBox(_T("exit"));
			break;
		}
	}
	return 0;
}





//串口读线程函数
DWORD CChuankouDlg::ReadThreadFunc2(LPVOID lparam)
{
	CChuankouDlg *ceSeries = (CChuankouDlg*)lparam;
	
	DWORD	evtMask;
	BYTE * readBuf = NULL;//读取的字节
	DWORD actualReadLen=0;//实际读取的字节数
	DWORD willReadLen;
	
	DWORD dwReadErrors;
	COMSTAT	cmState;
	
	// 清空缓冲,并检查串口是否打开。
	ASSERT(ceSeries->m_hComm2 !=INVALID_HANDLE_VALUE); 
	
//	AfxMessageBox(_T("1"));
	//清空串口
	PurgeComm(ceSeries->m_hComm2, PURGE_RXCLEAR | PURGE_TXCLEAR );
	
	SetCommMask (ceSeries->m_hComm2, EV_RXCHAR | EV_CTS | EV_DSR );
	while (TRUE)
	{   	
		if (WaitCommEvent(ceSeries->m_hComm2,&evtMask,0))
		{			
			SetCommMask (ceSeries->m_hComm2, EV_RXCHAR | EV_CTS | EV_DSR );
			//表示串口收到字符		
			if (evtMask & EV_RXCHAR) 
			{
			//	AfxMessageBox(_T("3"));
				ClearCommError(ceSeries->m_hComm2,&dwReadErrors,&cmState);
				willReadLen = cmState.cbInQue ;
				if (willReadLen <= 0)
				{
					continue;
				}
				
				readBuf = new BYTE[willReadLen];
				ReadFile(ceSeries->m_hComm2, readBuf, willReadLen, &actualReadLen,0);
				
				//如果读取的数据大于0,
				if (actualReadLen>0)
				{
				//	ceSeries->read(ceSeries->m_pPortOwner,readBuf,actualReadLen);
				//	AfxMessageBox(_T("ol"));
					//触发读取回调函数
					ceSeries->OnSeriesRead2(ceSeries->m_pPortOwner,readBuf,actualReadLen);
				//	AfxMessageBox(_T("ol"));
				}
			}
		}
		//如果收到读线程退出信号,则退出线程
		if (WaitForSingleObject(ceSeries->m_hReadCloseEvent2,500) == WAIT_OBJECT_0)
		{//	AfxMessageBox(_T("exit"));
			break;
		}
	}
	return 0;
}





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

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

void CChuankouDlg::ClosePort1()
{	
	//表示串口还没有打开
	if (m_hComm1 == INVALID_HANDLE_VALUE)
	{
		return ;
	}
	//关闭读线程
	CloseReadThread1();
	//关闭串口
	if (!CloseHandle (m_hComm1))
	{
		m_hComm1 = INVALID_HANDLE_VALUE;
		return ;
	}
	m_hComm1 = INVALID_HANDLE_VALUE;

//	AfxMessageBox(_T("ClosePort"));
}


void CChuankouDlg::ClosePort2()
{	
	//表示串口还没有打开
	if (m_hComm2 == INVALID_HANDLE_VALUE)
	{
		return ;
	}
	//关闭读线程
	CloseReadThread2();
	//关闭串口
	if (!CloseHandle (m_hComm2))
	{
		m_hComm2 = INVALID_HANDLE_VALUE;
		return ;
	}
	m_hComm2 = INVALID_HANDLE_VALUE;

//	AfxMessageBox(_T("ClosePort"));
}




//私用方法,用于向串口写数据,被写线程调用
BOOL CChuankouDlg::WritePort(HANDLE hComm,const BYTE *buf,DWORD bufLen)
{
//	AfxMessageBox( _T("WritePort") );
	DWORD dwNumBytesWritten;
	DWORD dwHaveNumWritten =0 ; //已经写入多少
	
	ASSERT(hComm != INVALID_HANDLE_VALUE);
	do
	{
	//	AfxMessageBox( _T("gogo") );
		if (WriteFile (hComm,					//串口句柄 
			buf+dwHaveNumWritten,				//被写数据缓冲区 
			bufLen- dwHaveNumWritten,          //被写数据缓冲区大小
			&dwNumBytesWritten,					//函数执行成功后,返回实际向串口写的个数	
			NULL))								//此处必须设置NULL
		{
			dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten;
			//写入完成
			if (dwHaveNumWritten == bufLen)
			{
			//	AfxMessageBox( _T("yes ok") );
				return TRUE;
			}
		//	Sleep(10);
		}
		else
		{
			return FALSE;
		}
	}while (TRUE);
	
	return TRUE;	
}

void CChuankouDlg::OpenThind1(CWnd* pPortOwner)
{	m_pPortOwner = pPortOwner;	
	m_hReadCloseEvent1 = CreateEvent(NULL,TRUE,FALSE,NULL);
	//创建读串口线程
	m_hReadThread1 = CreateThread(NULL,0,ReadThreadFunc1,this,0,&m_dwReadThreadID);

}


void CChuankouDlg::OpenThind2(CWnd* pPortOwner)
{	m_pPortOwner = pPortOwner;	
	m_hReadCloseEvent2 = CreateEvent(NULL,TRUE,FALSE,NULL);
	//创建读串口线程
	m_hReadThread2 = CreateThread(NULL,0,ReadThreadFunc2,this,0,&m_dwReadThreadID);

}

void CChuankouDlg::OnCheck1() 
{
	UpdateData(true);
	if(m_16)
	{
	m_dis=true;
	}
	else{
	m_dis=false;
	}
}

void CChuankouDlg::OnSetfocusEdit2() 
{
	SipShowIM(SIPF_ON);
	
}

void CChuankouDlg::OnKillfocusEdit2() 
{
	SipShowIM(SIPF_OFF);
	
}

void CChuankouDlg::OnSetfocusEdit5() 
{
	SipShowIM(SIPF_ON);
	
}

void CChuankouDlg::OnKillfocusEdit5() 
{
	SipShowIM(SIPF_OFF);
	
}

void CChuankouDlg::OnTimer(UINT nIDEvent) 
{
	//ShowWindow(false);
	KillTimer(1);
	
	CDialog::OnTimer(nIDEvent);
}

void CChuankouDlg::OnButton5() 
{
	((CEdit*)GetDlgItem(IDC_EDIT1))->SetWindowText(_T(""));	
	
}

void CChuankouDlg::OnButton6() 
{
	((CEdit*)GetDlgItem(IDC_EDIT2))->SetWindowText(_T(""));
	
}

void CChuankouDlg::OnButtonSend2() 
{
	// TODO: Add your control notification handler code here
	if(!m_Cortrol2)
	{
		AfxMessageBox(_T("串口没有打开!"));
		return;
	}
	BYTE *pData;
	UpdateData(true);
	((CEdit*)GetDlgItem(IDC_EDIT5))->GetWindowText(m_strSend);
	if(m_strSend==_T(""))
	{
	return;
	}
	if(m_16)
	{
		CByteArray hexdata;
		int len=String2Hex(m_strSend,hexdata); 
		bufLen=len;
		pData=new BYTE[len];
		for(int k=0;k<len;k++)
		{
			pData[k]=	hexdata[k];			
		}	
	}else{
	bufLen = m_strSend.GetLength()*2;
	pData = new BYTE(bufLen);
	CopyMemory(pData,m_strSend.GetBuffer(m_strSend.GetLength()),bufLen);
	}
	con2+=bufLen;
	if (!WritePort(m_hComm2,pData,bufLen))
	{
		AfxMessageBox(L"写串口失败\r\n\r请检查串口连接!");
		ClosePort2();
		return;
	}
	delete pData;
	pData=NULL;
	CString LEN;
	LEN.Format(_T("%d"),con2);
	((CEdit*)GetDlgItem(IDC_EDIT6))->SetWindowText(LEN);
	//ReadPort();
	
}

⌨️ 快捷键说明

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