VS2010 基于MFC 的串口通信上位机总结

VS2010 基于MFC 串口通信上位机,实现串口发送、接收数据及接收数据保存。
提示:不清楚的函数可在MSDN 内查询

  1. 打开VS2010 创建 MFC应用程序,选择基于对话框类 ,勾选最大化框、最小化框后 选择下一步完成。

  2. 将对话框上原有的控件删除,添加所需的控件。
    发送部分:Radio Button、Combo Box
    接收部分:Edit Control
    选择串口、波特率:Combo Box
    按键:打开串口、发送数据、清除数据、保存数据、退出
    图标显示:指示串口打开、关闭状态
    Activex 串口控件:Microsoft Communications Control,Version 6.0
    提示:VS2010 内找不到此Activex 控件的解决方法 :https://blog.csdn.net/madao1234/article/details/82047796

3.为各控件添加控制程序
① 打开串口按钮 ,显示指示图标
提示:双击打开按钮 会直接跳转到 void C串口Dlg::OnBnClickedButtonOpen() 函数

void C串口Dlg::OnBnClickedButtonOpen()
{
	// TODO: 在此添加控件通知处理程序代码
	CString str,str1,n; //定义3个CString变量
	GetDlgItemText(IDC_BUTTON_OPEN,str); //获取打开串口按键的Caption,IDC_BUTTON_OPEN:打开串口按键的ID
	CWnd *h1;  //定义句柄类的指针
	h1 = GetDlgItem(IDC_BUTTON_OPEN); // h1 赋为 指向IDC_BUTTON_OPEN 按键的句柄

	if(!m_mscom.get_PortOpen()) //如果串口未打开
	{
		//m_comb3:波特率选择组合框的 成员变量
		m_comb3.GetLBText(m_comb3.GetCurSel(),str1); //取得波特率口当前的选择值,存放在str1里 
		
		str1 = str1 + _T(",n,8,1"); 
		m_mscom.put_Settings(str1);// 设置波特率、无校验,8数据位,1个停止位

		m_mscom.put_InBufferSize(1024); //接收缓冲区大小设置
		m_mscom.put_OutBufferSize(1024);//发送缓冲区大小设置

		m_mscom.put_CommPort((m_comb1.GetCurSel()+1)); //选择串口,m_comb1:串口选择组合框的 成员变量
		m_mscom.put_InputMode(1); //设置输入方式 二进制方式
		m_mscom.put_InputLen(0);// 设置当前接收区数据长度为0,表示全部读取
		m_mscom.put_RThreshold(2); // 缓冲区有2个字符引发OnComm事件

		m_mscom.put_PortOpen(true); //打开串口
		m_mscom.get_Input(); //先预读缓冲区以清除残留数据

		if(m_mscom.get_PortOpen()) //如果串口打开
		{
			str = _T("关闭串口"); // str打开按钮的Caption 赋为 “关闭串口”
			UpdateData(TRUE);//用于将屏幕上控件中的数据交换到变量中
			h1->SetWindowText(str); //打开串口按键 文本将被修改
			m_Icon.SetIcon(m_hIcon_Open); //显示打开图标
		}
	  }
	 else
	  {
		m_mscom.put_PortOpen(false); //关闭串口
		if(str != _T("打开串口"))  
		{
			str = _T("打开串口");
			UpdateData(TRUE);
			h1->SetWindowText(str); 
			m_Icon.SetIcon(m_hIcon_Close); //显示关闭图标
		}
	   }
}

② 串口打开、关闭 图标显示
首先,准备好2个Icon 图标, 在资源视图内右键—>添加资源—>导入 ,选择2个Icon。 导入后自动分配了ID: IDI_ICON1\ IDI_ICON2 .
在BOOL C串口Dlg::OnInitDialog() 内添加如下代码:

//m_hIcon_Open:串口打开图标的HICON 类型的成员变量
//m_hIcon_Close :串口关闭图标的HICON 类型的成员变量
//LoadIcon从与应用程序实例相关联的可执行文件(.EXE)文件中加载指定的图标资源
m_hIcon_Open = LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON1));

m_hIcon_Close = LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON2));

m_Icon.SetIcon(m_hIcon_Close); //设置初始显示为关闭图标

③选择串口 与 波特率 的 Combo Box 设置
在BOOL C串口Dlg::OnInitDialog() 内添加如下代码:

// 串口组合框:显示com1~com15
CString str;
for(i=0;i<15;i++) 
{
	str.Format(_T("com %d"),i+1);
	m_comb1.InsertString(i,str);
}
m_comb1.SetCurSel(0); 

//波特率组合框
CString str1[]={_T("4800"),_T("9600"),_T("19200"),_T("38400"),_T("43000"),_T("56000"),_T("57600"),_T("115200")};
for(int i = 0; i<8 ; i++)
{
	int judge_tf=m_comb3.AddString(str1[i]);
	if((judge_tf==CB_ERR)|(judge_tf==CB_ERRSPACE))
		MessageBox(_T("设置波特率错误"));
}
m_comb3.SetCurSel(7);

//运行次数选项框
int i;
CString str2[]={_T("1"),_T("2"),_T("3"),_T("4"),_T("5"),_T("6"),_T("7"),_T("8"),_T("9")};
for(int i = 0; i<9 ; i++)
{
	int judge_times=m_Runtime.AddString(str2[i]);
	if((judge_times==CB_ERR)|(judge_times==CB_ERRSPACE))
		MessageBox(_T("未设置运行次数"));
}
m_Runtime.SetCurSel(0);

④ Radio选择框设置,发送数据按钮
多个Radio Button 将第一个的Group改为True 按照Tab顺序会将其他Radio Button 分为一组,返回值分别为0,1,2 …
双击发送数据按钮,添加控制程序:

void C串口Dlg::OnBnClickedButtonSend()
{
	// TODO: 在此添加控件通知处理程序代码
	CString str,str1,SendData;
	UpdateData(TRUE); //将控件的状态传给其关联的变量
	str.Format(_T("%d"),m_MMSet);  //将 单选按钮的 int变量值强制转换成CString类型

	m_Runtime.GetLBText(m_Runtime.GetCurSel(),str1);//运行次数选择框返回值
	SendData = str + str1; //发送的数据 
	//UpdateData(TRUE);
	m_mscom.put_Output(COleVariant(SendData)); //数据发送

}

⑤清除数据按钮

void C串口Dlg::OnBnClickedButtonClean()
{
	// TODO: 在此添加控件通知处理程序代码
	m_Edit1_Rev1 = _T(""); //给接收编辑框发送空格符
	m_Edit1_Rev2 = _T(""); 
	m_Edit1_Rev3 = _T(""); 
	m_Edit1_Rev4 = _T(""); 
	m_Edit1_Rev5 = _T("");

	UpdateData(FALSE);//将数据在屏幕中对应控件中显示出来
}

⑥ 关闭按钮

void C串口Dlg::OnBnClickedButtonClose()
{
	// TODO: 在此添加控件通知处理程序代码
	if(m_mscom.get_PortOpen())
		m_mscom.put_PortOpen(FALSE);

	CDialogEx::OnCancel();
}

⑦ 串口控件程序:点击Activex 控件,右键 为控件添加处理程序
功能 :多个接收编辑框分别显示接收数据

void C串口Dlg::OnCommMscomm1()
{
	// TODO: 在此处添加消息处理程序代码
	CString strtemp;
	if(m_mscom.get_CommEvent()==2)  //事件值为2 表示接收缓存区内有字符
	{
		BYTE str[2048]={0};
		long len,k;
		COleSafeArray fs;
		int flag,i=0;
		
		VARIANT InputData = m_mscom.get_Input(); //读缓冲区
		fs = InputData;  //Variant类型变量转换成 COleSafeArray型变量
		len = fs.GetOneDimSize(); //得到有效数据长度
		for(k = 0;k < len;k++)
			fs.GetElement(&k,str+k); //转换成BYTE型数组
		for(k = 0;k < len;k++)  //将数组转换为CString型变量
		{
			BYTE bt=*(char*)(str+k); //字符型
			strtemp.Format(_T("%c"),bt); //将字符输入临时变量strtemp
//输出为多个显示框,显示位置标志			
			if(strtemp == 'a') 
			{
				flag = 0;
			}
			else if(strtemp == 'b') 
			{
				flag = 1;
			}
			else if(strtemp == 'c') 
			{
				flag = 2;
			}
			.....
//显示数据写入
			switch(flag)
			{
			case 0:
				m_Edit1_Rev1 = _T(""); //清空显示
				for(k=1;k

⑧ 数据保存按键
将数据保存为csv格式

void C串口Dlg::OnBnClickedButtonSave()
{
	// TODO: 在此添加控件通知处理程序代码
	CString str,str1,str2,str3,str4;
	//构建文件保存为对话框,默认扩展名为.csv,初始文件名为空...
	CFileDialog fg(false,_T("*.csv"),NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
		_T("Text File(*.txt)|*.txt|Excel CSV File(*.csv)|*.csv|All Flie(*.*)|*.*||"),NULL);


	str1 = _T("文本,");//文本为行标题,换单元格
	str2 = _T("文本,");
	str3 = _T("文本,");
	str4 = _T("文本,");
	str8 = _T(",文本,文本,文本\n"); // 文本为列标题
	
	if(fg.DoModal()==IDOK) //创建对话框成功
	{
		CString filename = fg.GetPathName(); //文件的完整路径
		CStdioFile mFile(filename,CFile::modeCreate|CFile::modeWrite); //指定文件路径、创建只写模式
		//写入第1个 Radio Button控制的数据

		switch (m_MMSet)
		{ 
		case 0:
			mFile.Write(str1,str1.GetLength());
			GetDlgItemText(IDC_RADIO1,str);  
			mFile.WriteString(str+"\n"); 
			break;
		case 1:
			mFile.Write(str1,str1.GetLength());
			GetDlgItemText(IDC_RADIO2,str); 
			mFile.WriteString(str+"\n");
			break;
		case 2:
			mFile.Write(str1,str1.GetLength());
			GetDlgItemText(IDC_RADIO3,str); 
			mFile.WriteString(str+"\n");
			break;
		default:
			break;
		}
		//写入第2个文本 的数据
		mFile.Write(str2,str2.GetLength());
		GetDlgItemText(IDC_COMBO1,str);
		mFile.WriteString(str+"\n");

		mFile.Write(str8,str8.GetLength()); //写列标题

		//写入接收框1的数据
		
		mFile.Write(str3,str3.GetLength());
		GetDlgItemText(IDC_EDIT1_Rev1,str); //写入接收框数据
		mFile.WriteString(str);//指定一个指向包含空终止文本字符串的缓冲区的指针。
		GetDlgItemText(IDC_EDIT2_Rev1,str);
		mFile.WriteString(",");
		mFile.WriteString(str);
		GetDlgItemText(IDC_EDIT3_Rev1,str);
		mFile.WriteString(",");
		mFile.WriteString(str+"\n");
	
		//写入接收框2的数据
		mFile.Write(str4,str4.GetLength());
		GetDlgItemText(IDC_EDIT1_Rev2,str); 
		mFile.WriteString(str); 
		GetDlgItemText(IDC_EDIT2_Rev2,str);
		mFile.WriteString(",");
		mFile.WriteString(str);
		GetDlgItemText(IDC_EDIT3_Rev2,str);
		mFile.WriteString(",");
		mFile.WriteString(str+"\n");
	}

}

VS2010 基于MFC 的串口通信上位机总结_第1张图片
使用虚拟串口测试,可以实现 数据发送、接收、保存 。

你可能感兴趣的:(编写上位机,VS2010,MFC,串口通信)