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

📄 comportdlg.cpp

📁   本实例实现在VC下如何编写串口(com port)实例(与串口通信), 对初学者弄懂串口的实现过程是很好的一个实例.以及现实将串口读到的数据记录到一个testlog目录中,以做备份
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ComPortDlg.cpp : implementation file
//

#include "stdafx.h"
#include "ComPort.h"
#include "ComPortDlg.h"
#include "Setting.h"



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


/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CComPortDlg dialog

CComPortDlg::CComPortDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CComPortDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CComPortDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_bConnected = FALSE;
	m_strPort = "COM1";
	m_nDataBits = 8;
	m_nParity = 0;
	m_nBaud = 9600;
	m_nStopBits = 0;
	m_nFlowCtrl = 0;
	log.m_strlog = "";
	m_pThread = NULL;
	m_testreadthread = NULL;
	m_strrecordlog_temp = "";
	m_strbuffer = "";
	m_bbufferopen = TRUE;
	m_bisonchar = FALSE;
	m_stronchar = "";
	m_strtestbuffer ="";
	m_testfindstring = "";

	starttime = endtime = CTime::GetCurrentTime();
	m_bcalltestfindstring = FALSE;
	m_bsendonetime = FALSE;
	m_bcallexpectstring = FALSE;
	m_bexpectonetime = FALSE;

	m_testthread = NULL;

	starttest = FALSE;

	
	

	
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CComPortDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CComPortDlg)
	DDX_Control(pDX, IDC_edtlog, m_edtlog);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CComPortDlg, CDialog)
	//{{AFX_MSG_MAP(CComPortDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_btnOpen, OnbtnOpen)
	ON_BN_CLICKED(IDC_btnClosed, OnbtnClosed)
	ON_BN_CLICKED(IDC_btnSetting, OnbtnSetting)
	ON_BN_CLICKED(IDC_btnShowLog, OnbtnShowLog)
	ON_BN_CLICKED(IDC_btnlastlog, Onbtnlastlog)
	ON_BN_CLICKED(IDC_btnsendcommand, Onbtnsendcommand)
	ON_BN_CLICKED(IDC_btngetbuffer, Onbtngetbuffer)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CComPortDlg message handlers

BOOL CComPortDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	if((m_hPostMsgEvent = CreateEvent(NULL, TRUE, TRUE, NULL)) == NULL)
		return FALSE;
	memset(&m_osRead, 0, sizeof(OVERLAPPED));
	memset(&m_osWrite, 0, sizeof(OVERLAPPED));

	if((m_osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL))== NULL)
		return FALSE;
	if((m_osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
		return FALSE;


	
	
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}




void CComPortDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CComPortDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CComPortDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CComPortDlg::OnbtnOpen() 
{
	if(m_bConnected)
	{
		MessageBox("Com Port was opened!");
		return ;
	}	
	pcomopen = AfxBeginThread(comopenfunc,this,THREAD_PRIORITY_NORMAL,0, CREATE_SUSPENDED,NULL);
	if(pcomopen == NULL)
	{
		return ;
	}
	else
	{
		pcomopen->ResumeThread();
	}
}


UINT comopenfunc(LPVOID lParam)
{
	CComPortDlg* pcomportdlg = (CComPortDlg*)lParam;
	if(!pcomportdlg->ComOpen())
		AfxMessageBox("无法建立连接!");	
	return 1;
}


UINT ComPorc(LPVOID pParam)
{
	OVERLAPPED os;
	DWORD dwMask, dwTrans;
	COMSTAT ComStat;
	DWORD dwErrorFlags;
	
	CComPortDlg* pDlg = (CComPortDlg*)pParam;
	memset(&os, 0, sizeof(OVERLAPPED));
	os.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if(os.hEvent == NULL)
	{
		AfxMessageBox("无法创建事件对象!");
		return (UINT)-1;
	}
	while(pDlg->m_bConnected)
	{
		ClearCommError(pDlg->m_hCom, &dwErrorFlags, &ComStat);

		if(ComStat.cbInQue)//有ComPort中等待要取出来的字符数
		{
			WaitForSingleObject(pDlg->m_hPostMsgEvent, INFINITE);

			ResetEvent(pDlg->m_hPostMsgEvent);			
			pDlg->OnCom(EV_RXCHAR, 0);
			continue;
		}
		dwMask = 0;
		if(!WaitCommEvent(pDlg->m_hCom, &dwMask, &os))
		{
			if(GetLastError() == ERROR_IO_PENDING)
				GetOverlappedResult(pDlg->m_hCom, &os, &dwTrans, TRUE);
			else
			{
				CloseHandle(os.hEvent);
				return (UINT)-1;
			}
		}
	}
	CloseHandle(os.hEvent);
	return 0;
}


LRESULT CComPortDlg::OnCom(WPARAM wParam, LPARAM lParam)
{
	char buf[MAXBLOCK/4];
	CString str;
	int nLength, nTextLength;
	
	if(!m_bConnected || (wParam & EV_RXCHAR) != EV_RXCHAR)
	{
		SetEvent(m_hPostMsgEvent);
		return 0L;
	}
	nLength = ReadCom(buf, 100);	
	
	if(nLength)
	{
	//	recordlog(buf,nLength);  //记录 log.

		nTextLength = m_edtlog.GetWindowTextLength();
		m_edtlog.SetSel(nTextLength, nTextLength);
		for(int i=0; i<nLength; i++)
		{
			switch(buf[i])
			{
			case '\n':
				str += "\n";
				break;
			case '\b':
				m_edtlog.SetSel(-1, 0);
				m_edtlog.ReplaceSel(str);
				nTextLength = m_edtlog.GetWindowTextLength();
				m_edtlog.SetSel(nTextLength-1, nTextLength);
				m_edtlog.ReplaceSel("");
				str = "";
				break;
			case '\a':
				MessageBeep((UINT)-1);
				break;
			default:
				str += buf[i];
			}
		}
		m_edtlog.SetSel(-1, 0);
		m_edtlog.ReplaceSel(str);
		recordlog(str);

		getcomportbuffer(str);


//		m_strbuffer += str;
		
	}
	SetEvent(m_hPostMsgEvent);
	return 0L;
}

DWORD CComPortDlg::ReadCom(char *buf, DWORD dwLength)
{
	DWORD length = 0;
	COMSTAT ComStat;
	DWORD dwErrorFlags;
	ClearCommError(m_hCom, &dwErrorFlags, &ComStat);
	length = min(dwLength, ComStat.cbInQue);
	ReadFile(m_hCom, buf, length, &length, &m_osRead);
	return length;
}

BOOL CComPortDlg::comconfig()
{
	CString str;
	DCB dcb;
	if(!GetCommState(m_hCom, &dcb))
	{
		MessageBox("Return False!");
		return FALSE;
	}
	dcb.fBinary = TRUE;
	dcb.BaudRate = m_nBaud;
	CString str1;
	str1.Format("new BaudRate = %d", dcb.BaudRate);
	//MessageBox(str1);
	dcb.ByteSize = m_nDataBits;
	dcb.fParity = TRUE;
	m_nStopBits = 0;
	str.Format("m_strPort = %s, m_nBaud = %d, m_nDataBits = %d, \
		m_nParity = %d, m_nStopBits = %d, m_nFlowCtrl = %d",
		m_strPort, m_nBaud, m_nDataBits, m_nParity, m_nStopBits, m_nFlowCtrl);
	//MessageBox(str);

	switch(m_nParity)
	{
	case 0:
		dcb.Parity = NOPARITY;
		break;
	case 1:
		dcb.Parity = EVENPARITY;
		break;
	case 2:
		dcb.Parity = ODDPARITY;
		break;
	default:;
	}

	switch(m_nStopBits)
	{
	case 0:
		dcb.StopBits = ONESTOPBIT;
		break;
	case 1:
		dcb.StopBits = ONE5STOPBITS;
		break;
	case 2:
		dcb.StopBits = TWOSTOPBITS;
		break;
	default:;
	}
	str.Format("BaudRate= %d",dcb.BaudRate);
	//MessageBox(str);

	switch(m_nFlowCtrl)
	{
	case 0:
		//无,指无流量控制.
		dcb.fOutxCtsFlow = FALSE;  //打开硬件流控制
		dcb.fRtsControl = FALSE;   //打开硬件流控制
		dcb.fInX = dcb.fOutX = FALSE;  //关闭软件流控制		
		break;
	case 1:
		//RTS/CTS  硬件流控程
		dcb.fOutxCtsFlow = TRUE;  //打开硬件流控制
		dcb.fRtsControl = TRUE;   //打开硬件流控制
		dcb.fInX = dcb.fOutX = FALSE;  //关闭软件流控制
		break;
	case 2:
		//XON XOFF 软件流控制
		dcb.fOutxCtsFlow = FALSE;  //关闭硬件流控制
		dcb.fRtsControl = FALSE;   //关闭硬件流控制

		dcb.fInX = dcb.fOutX = TRUE;  //打开软件流控制
		dcb.XonChar = XON;	
		dcb.XoffChar = XOFF;
		dcb.XonLim = 50;
		dcb.XoffLim = 50;
		break;
	default:;
	}
	
	
	str.Format("m_strPort = %s, dcb.BaudRate = %d, m_nDataBits = %d, \
		m_nParity = %d, dcb.StopBits = %d, m_nFlowCtrl = %d",
		m_strPort, dcb.BaudRate, m_nDataBits, m_nParity, dcb.StopBits, m_nFlowCtrl);
	//MessageBox(str);
	return SetCommState(m_hCom, &dcb);
}

BOOL CComPortDlg::ComOpen()
{
	COMMTIMEOUTS TimeOuts;
	CString threadid;
	m_hCom = CreateFile(m_strPort,
	GENERIC_READ | GENERIC_WRITE,
	0,
	NULL,
	OPEN_EXISTING,
	FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
	NULL);
	if(m_hCom == INVALID_HANDLE_VALUE)
	{
		MessageBox("Com Port no existing");
		return FALSE;
	}
	SetupComm(m_hCom, MAXBLOCK, MAXBLOCK);
	SetCommMask(m_hCom, EV_RXCHAR | EV_CTS|EV_DSR|EV_RING);

	TimeOuts.ReadIntervalTimeout = MAXDWORD;
	TimeOuts.ReadTotalTimeoutMultiplier = 0;
	TimeOuts.ReadTotalTimeoutConstant = 0;

	TimeOuts.WriteTotalTimeoutMultiplier = 50;
	TimeOuts.WriteTotalTimeoutConstant = 2000;

	SetCommTimeouts(m_hCom, &TimeOuts);

	if(comconfig())
	{
		m_pThread = AfxBeginThread(
			ComPorc,
			this,
			THREAD_PRIORITY_NORMAL,
			0,
			CREATE_SUSPENDED,
			NULL);
		if(m_pThread == NULL)
		{
			CloseHandle(m_hCom);
			return FALSE;
		}
		else
		{
			m_bConnected = TRUE;
			m_pThread->ResumeThread();
		}

		CComPortDlg::testreadthread();
		CComPortDlg::testthread();
	}
	else
	{
		CloseHandle(m_hCom);
		return FALSE;
	}
	return TRUE;
}


DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
	CComPortDlg* pDlgtest = (CComPortDlg*)lpParameter;

	int i=0;
	//	FILE *tfile = fopen("test.log","a+");
	while(i<1000)
	{
		i++;

		
		pDlgtest->m_strtestbuffer= pDlgtest->m_strbuffer;
		//		Sleep(500);
		
		
//		AfxMessageBox(pDlgtest->m_strtestbuffer);
//		FILE *tfile = fopen("ding1.log","a+");
//		fwrite(pDlgtest->m_strtestbuffer,1, strlen(pDlgtest->m_strtestbuffer), tfile);
//		fclose(tfile);
		Sleep(1500);
		
	}
	return 1;
}


DWORD CComPortDlg::SendCom(char *buf, DWORD dwLength)
{
	BOOL fState;
	DWORD length = dwLength;
	COMSTAT ComStat;
	DWORD dwErrorFlags;
	CString charleng;
	
	if(m_bisonchar)  //如果是由OnChar传来的字符,将进行组合成字符串m_stronchar.
	{
		if(buf[0] != '\r')
			m_stronchar +=buf[0];
	}
	if(length)
	{
		//每一次对输入的字符进行分析,如果遇到回车或换行的时候,将把m_strbuffer进行清空,把*buf的字
		//符赋给m_strbuffer中.
		for(DWORD i=0; i<length; i++)
		{
			switch(buf[i])
			{
			case '\r':
				m_strbuffer = "";
				if(m_bisonchar)
				{					
					m_strbuffer += m_stronchar;				
					m_stronchar = "";
				}
				m_bbufferopen= TRUE;

				break;
			case '\n':
				m_strbuffer = "";
				m_bbufferopen= TRUE;
				break;
			default:
				m_strbuffer += buf[i];  //不放在这里后面会多带一个回车, 在Buffer中会多一行.
				break;				
			}			
		}		
	}

	//写入数据
	ClearCommError(m_hCom, &dwErrorFlags, &ComStat);
	fState = WriteFile(m_hCom, buf, length, &length, &m_osWrite);
	if(!fState)
	{
		if(GetLastError()==ERROR_IO_PENDING)
		{
			GetOverlappedResult(m_hCom, &m_osWrite, &length, TRUE);
		}
		else
		{
			length = 0;
		}
	}	
	return length;
}

void CComPortDlg::ComClose()
{
	SetEvent(m_hPostMsgEvent);
	SetCommMask(m_hCom,0);

	WaitForSingleObject(m_pThread->m_hThread, INFINITE);
	m_pThread = NULL;
	CloseHandle(m_hCom);
}

void CComPortDlg::OnbtnClosed() 
{
	thiscomclose();	
}

void CComPortDlg::OnbtnSetting() 
{
	CSetting comSetting;	
	CString str;	

	comSetting.m_strPort = m_strPort;
	str.Format("%d",m_nBaud);
	
	comSetting.m_strBaudRate =str; 
	str.Format("%d",m_nDataBits);
	comSetting.m_strDataBits = str;

	str.Format("m_nParity = %d, m_nFlowCtrl= %d",m_nParity,m_nFlowCtrl);
	switch(m_nParity)
	{
	case 0:
		comSetting.m_nParity = "NONE";
		break;
	case 1:
		comSetting.m_nParity = "EVEN";
		break;
	case 2:
		comSetting.m_nParity = "ODD";
		break;
	default:;
	}

⌨️ 快捷键说明

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