VS2010 基于MFC 串口通信上位机,实现串口发送、接收数据及接收数据保存。
提示:不清楚的函数可在MSDN 内查询
打开VS2010 创建 MFC应用程序,选择基于对话框类 ,勾选最大化框、最小化框后 选择下一步完成。
将对话框上原有的控件删除,添加所需的控件。
发送部分: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");
}
}