基于MFC的简单串口通信(针对单片机简单通信)

最近由于项目需要自学了MFC的界面设置(初学者),在基本功能设置完成之后,老大觉得并不需要了,也就没被采纳。但我觉得还是以博客的形式写出来,既能回顾一下学习过程,又能帮助大家。

开发环境

MFC的开发环境是Visual C++,也叫VC++。MFC(Microsoft Foundation Classes)是微软基础类库的简称,是一个微软实现的C++类库,主要封装大部分的Windows API函数,并且包含一个应用程序框架,以减少应用程序开发人员工作量。MFC除了是一个类库以外,还是一个框架,在vc++里新建一个MFC的工程,开发环境会自动帮你产生许多文件,同时它使用了mfcxx.dll。xx是版本,它封装了mfc内核,所以你在你的代码看不到原本的SDK编程中的消息循环等等东西,这样你就可以专心的考虑你程序的逻辑,而不是这些每次编程都要重复的东西,但是由于是通用框架,没有最好的针对性,当然也就丧失了一些灵活性和效率但是MFC的封装很浅,所以效率上损失不大,灵活性还可以,虽然也有很多缺陷,但还是一个比较好的东西。

附上vc++安装包以及其他资料
链接:https://pan.baidu.com/s/14lo6nnW7aficYnDEENWfqA
提取码:9ydy
复制这段内容后打开百度网盘手机App,操作更方便哦

控件布局与设置

解压缩完成并安装完成后,我们就开始建立MFC界面。

  1.双击Visual C++,出现如下窗口。

出现的每日提示你可以关掉也可以不关掉,在左下方的启动时显示提示前面方框里的对勾去掉,之后就不会再出现了。
2.关闭每日提示之后,点击file -> new(新建)会出现新建工程窗口。选择MFC AppWizard[exe],并为工程命名(例如:博客撰写),选择保存工程的位置,最后点击确定。
新建工程区窗口
3.点击确定之后出现MFC应用程序向导窗口
步骤一:在您要创建的应用程序类型是:基本对话框。其余默认,然后点击下一步(也可以直接点击完成)。
步骤1
步骤二:可以对对话框的标题进行修改(我这采用的默认)。其余默认,然后点击完成。(要是想看后面的步骤可以点击下一步)第二步
步骤三:出现一个新建工程的信息,包括工程的应用类型,被创建的类型以及特点。若是有问题点击取消,若是没有点击确定。
新建工程信息
4.点击确定之后会出现对话框。
对话框
界面上的按钮放置在如下对话框中。初始界面
可以删除上面的两个按键和一个静态文本。在控件工具栏中拖入三个静态文本框,三个编辑框,六个按钮。若是没有控件工具栏,就在菜单栏空白处右击鼠标,选择控件。布局之后的效果如下:
界面初始图
5.接下来就是设置每个编辑框,按钮的名称及其属性。
选中静态文本,右击鼠标->属性,在常规一项中ID不用改,标题修改为接受数据,按回车键确认。修改其余两个静态文本方法同上。效果图如下:
静态文本框的修改
选中按钮1(Button 1),右击鼠标->属性,常规一项中ID修改为IDC_BtnOpen,标题修改为打开串口。按照上述方法修改其余5个按钮(ID分别为IDC_BtnSave,IDC_BtnStart,IDC_BtnStop,IDC_BtnDlt,IDC_BtnSend。标题分别为保存数据,定时发送,停止,删除数据,发送数据,ID与标题一一对应是为了编程的方便)。效果图如下:
按钮的修改
选中接受数据静态文本框下面的编辑框,右击鼠标->属性,常规一项中ID修改为IDC_EditRxData,样式一项中选择–多行,垂直滚动,自动垂直滚动,需要返回,只读。
选中定时发送数据静态文本框下面的编辑框,右击鼠标->属性,常规一项中ID修改为IDC_EditSend,样式一项中选择–多行,垂直滚动,自动垂直滚动,需要返回。
选中发送数据静态文本框下面的编辑框,右击鼠标->属性,常规一项中ID修改为IDC_EditTxData,样式一项中选择–多行,垂直滚动,自动垂直滚动,需要返回。
效果图如下:
编辑框的修改
这些步骤完成之后,点击Build->组建或者直接点击键盘F7,编译一次,看是否出错,避免影响到后面的操作。
接下来是最重要的一步,决定了能否与单片机通讯:
对话框或者中间空白处右击鼠标->插入ActiveX控件,下拉,选择Microsoft Communication Control,ver…,就会在界面框出现黄色电话标志。效果图如下:
插入ActiveX控件
黄色电话图
选中该电话右击->建立类向导。效果图如下:
类向导框图
在Message Maps一项, 选择IDC_BtnOpen->BN_CLICKEN->Add Function,默认函数名就行,然后点击OK。效果图如下:
按键消息图
设置每个控件的变量。在Member Variables一项,IDC_BtnDlt->Add Variable,会弹出Add Member Variable,在Member Variable name一栏中填写与该按键ID相同的名字,只是为了方便记忆,可以随意写。 效果图如下:
设置每个控件的变量
同理添加其他控件的变量,在添加在添加MSCOMM1的变量时,会出现提示,选择“是”。设置变量名为m_Comm1,点击OK,点击确定。 提示
输入变量名
最终效果图
再次编译运行一次,确认是否有错。

代码的添加

添加代码的方式有两种:第一种,直接双击按钮,进入代码编辑区。第二种:选择左边信息栏的File View->双击CommTestDlg.cpp,在文件尾部可以看到刚刚添加的三个函数。效果图如下:代码编辑区
六个按钮的代码如下图:

void CTem_Dlg::OnBtnDlt() 
{
	// TODO: Add your control notification handler code here
	if(IDYES == AfxMessageBox("是否删除数据?",MB_YESNO))
	{
		SetDlgItemText(IDC_EditTxData," ");
		SetDlgItemText(IDC_EditRxData," ");
		GetDlgItem(IDC_EditTxData)->SetFocus();
	}
}

void CTem_Dlg::OnBtnOpen() 
{
	// TODO: Add your control notification handler code here
	if(m_Comm.GetPortOpen())
		m_Comm.SetPortOpen(FALSE);
	m_Comm.SetCommPort(4);
	m_Comm.SetInBufferSize(1024);
	m_Comm.SetOutBufferSize(1024);
	if(!m_Comm.GetPortOpen())
		m_Comm.SetPortOpen(TRUE);
	else
		AfxMessageBox("cannot open serial port");
	m_Comm.SetSettings("9600,n,8,1");
	m_Comm.SetInputMode(1);
	m_Comm.SetRThreshold(1);
	m_Comm.SetInputLen(0);
	m_Comm.GetInput();
}

void CTem_Dlg::OnBtnSave() 
{
	// TODO: Add your control notification handler code here
	CString PathName,str;
	CFileDialog fileDlg(FALSE,_T("txt"),NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
	_T("txt Files(*.txt)|*.txt|All Files(*.*)|*.*||"),NULL);
    CFile file;
	int nlen;

	fileDlg.m_ofn.lpstrTitle = "保存文件";
    
	if(fileDlg.DoModal()==IDOK)
	{
		/*char *pLocale=_strdup(setlocale(LC_CTYPE,NULL));
		setlocale(LC_CTYPE,"chs");*/
		PathName = fileDlg.GetPathName();
        file.Open(PathName,CFile::modeCreate|CFile::modeWrite|CFile::typeText);
		nlen = GetDlgItem(IDC_EditRxData)->GetWindowTextLength();
		GetDlgItemText(IDC_EditRxData,str);
		file.Write(str,nlen);
		file.Close();
	}
}

void CTem_Dlg::OnBtnSend() 
{

	UpdateData(TRUE);
	m_Comm.SetOutput(COleVariant(m_EditTxData));
	GetDlgItem(IDC_EditTxData)->SetFocus();
}

void CTem_Dlg::OnOnCommMscomm1() 
{
	// TODO: Add your control notification handler code here
    VARIANT variant_inp;
	COleSafeArray safearray_inp;
	BYTE rxdata[2048];
	LONG len,k;
	CString str;

	if(m_Comm.GetCommEvent() == 2)
	{
		variant_inp=m_Comm.GetInput();
		safearray_inp = variant_inp;
        len = safearray_inp.GetOneDimSize();
		for(k=0;k<len;k++)
		{
		  safearray_inp.GetElement(&k,rxdata+k);
		}
		for(k = 0;k<len;k++)
		{
           BYTE bt= *(char*)(rxdata+k);
		   str.Format("%c",bt);
		   m_EditRxData += str;
		   UpdateData(FALSE);
		   CEdit *pedit = (CEdit *)GetDlgItem(IDC_EditRxData);
		   int nline = pedit->GetLineCount();
		   pedit->LineScroll(nline-1);
		}
	}

}

//以上为Debug版本,需要使用release版本才能无错使用。

void CTem_Dlg::OnBtnStart() 
{
	
	SetTimer(1,5000,NULL);
}

void CTem_Dlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	UpdateData(TRUE);
    m_Comm.SetOutput(COleVariant(m_EditSend));
	CDialog::OnTimer(nIDEvent);
}

void CTem_Dlg::OnBtnStop() 
{

	KillTimer(1);
	GetDlgItem(IDC_EditSend)->SetFocus();
}

最终效果图如下:
最终效果图PS:上述过程只是完成了上位机的工作,要最终能够发送和接收数据,还需要单片机配合工作,因此单片机还是需要下载相对应的程序。

发布了1 篇原创文章 · 获赞 1 · 访问量 10

猜你喜欢

转载自blog.csdn.net/qq_31790697/article/details/103926414