C++ MFC 简单 串口通信

本文转载连接: https://blog.youkuaiyun.com/Peter_JJH/article/details/77294592

 

说来惭愧,自己看别人的API说明,想要鼓捣出一个串口通讯界面,结果失败了,最后还是看的教程。。。。

使用MFC进行串口通讯的上位机的软件编程,教程网址如下,十分简单。

http://download.youkuaiyun.com/download/peter_jjh/9938549

1. 程序框架及代码分析:
1.1 程序框架:
(1) 初始化界面
(2) 打开串口 (读取串口号,初始化串口参数(波特率、校验位、数据位等),若串口已经打开则关闭串口)
(3) 发送数据 (更新控件状态,进入MSComm事件驱动函数,读缓冲区,数据转换,更新编辑框成员函数,更新编辑框内容)
(4) 退出界面 (检测串口是否开启,若开启则关闭串口,再进行退出)
1.2 关键代码分析:
代码下载地址:http://download.youkuaiyun.com/download/peter_jjh/9938503


(1)初始化界面:除却MFC自动生成的界面初始化代码,这里的关键在于初始化参数,在BOOL xxxxx:OnInitDialog()中添加部分代码

// 串口选择组合框
    CString str;
    int i;
    for (i = 0; i<30; i++)
    {
        str.Format(_T("com %d"), i + 1);
        m_ComNum.InsertString(i, str);
    }
    m_ComNum.SetCurSel(0);//预置COM口
 
    //波特率选择组合框
    CString str1[] = { _T("300"), _T("600"), _T("1200"), _T("2400"), _T("4800"), _T("9600"),
        _T("19200"), _T("38400"), _T("43000"), _T("56000"), _T("57600"), _T("115200") };
    
    for (int i = 0; i<12; i++)    //使用AddString会无序排列,在Dialog中把这一ComboBox的Sorted改为False即可
    {
        int judge_tf = m_BaudRate.AddString(str1[i]);
        if ((judge_tf == CB_ERR) || (judge_tf == CB_ERRSPACE))    
            MessageBox(_T("build baud error!"));
    }
    /*for (int i = 0; i<12; i++)        //更换为使用InsertString
    {
        m_BaudRate.InsertString(i, str1[i]);        
    }*/
 
    m_BaudRate.SetCurSel(5);//预置波特率为"9600"

(2) 打开串口:
void CComCommunicateDlg::OnBnClickedButtonOpen()    //打开串口按钮
{
    CString str, str1, n;                    //定义字符串
    GetDlgItemText(IDC_BUTTON_OPEN, str);
    CWnd *h1;
    h1 = GetDlgItem(IDC_BUTTON_OPEN);        //指向控件的caption
 
    if (!m_mscom.get_PortOpen())            
    {
        m_BaudRate.GetLBText(m_BaudRate.GetCurSel(), str1);//取得所选的字符串,并存放在str1里面
        str1 = str1 + ',' + 'n' + ',' + '8' + ',' + '1';            //这句话很关键
 
        m_mscom.put_CommPort((m_ComNum.GetCurSel() + 1));    //选择串口
        m_mscom.put_InputMode(1);            //设置输入方式为二进制方式
        m_mscom.put_Settings(str1);        //波特率为(波特率组Á合框)无校验,8数据位,1个停止位
        m_mscom.put_InputLen(1024);        //设置当前接收区数据长度为1024
        m_mscom.put_RThreshold(1);            //缓冲区一个字符引发事件
        m_mscom.put_RTSEnable(1);            //设置RT允许
 
        m_mscom.put_PortOpen(true);        //打开串口
        if (m_mscom.get_PortOpen())
        {
            str = _T("关闭串口");
            UpdateData(true);
            h1->SetWindowText(str);            //改变按钮名称为‘’关闭串口”
        }
    }
 
    else
    {
        m_mscom.put_PortOpen(false);        //关闭串口
        if (str != _T("打开串口"))
        {
            str = _T("打开串口");
            UpdateData(true);                //将控件的状态传给其关联的变量
            h1->SetWindowText(str);            //改变按钮名称为打开串口
        }
    }
 
}

(3) 发送数据 
void CComCommunicateDlg::OnBnClickedButtonSend()
{
    UpdateData(true);                            //将控件的状态传给其关联的变量
    m_mscom.put_Output(COleVariant(m_EditSend));//把发送编辑框的数据发送出去,跳转到OnCommMscomm1中
}
void CComCommunicateDlg::OnCommMscomm1()    //事件驱动
{
    if (m_mscom.get_CommEvent() == 2)    //事件值为2表示接收缓冲区内有字符
    {
        char str[1024] = { 0 };
        long k;
        VARIANT InputData = m_mscom.get_Input();    //读缓冲区
        COleSafeArray fs;
        fs = InputData;    //VARIANT型变量转换为COleSafeArray型变量
        for (k = 0; k<fs.GetOneDimSize(); k++)
            fs.GetElement(&k, str + k);    //转换为BYTE型数组
 
        m_EditReveive += str;      //    接收到编辑框里面
        //SetTimer(1,10,NULL);        //延时10ms
        UpdateData(false);
    }
 
}

(4) 退出界面

void CComCommunicateDlg::OnBnClickedButtonClose()
{
    if (m_mscom.get_PortOpen())
        m_mscom.put_PortOpen(false);    //先关闭串口再退出,否则串口一直被占用
    CDialogEx::OnCancel();
 
}

2. 遇到的问题:
2.1 缺少Microsoft Communications Control 控件
MSComm 控件是一个串行通讯控件,作用为替程序员串口通讯编程节省时间,有关于MSComm空间的介绍可以参考这篇博客:串口通信-MSComm控件使用详解

这一问题的解决方式很简单,下载压缩包解压复制就可以,下载网址:

http://download.youkuaiyun.com/download/peter_jjh/9937696

1.解压缩压缩包内包含3个文件:

MSCOMM.SRG
MSCOMM32.DEP
mscomm32.ocx
2.复制文件到指定路径:

32位的系统,文件复制到C:\WINDOWS\SYSTEM32目录下;

64位的系统,文件复制到C:\Windows\SysWOW64目录下。

3.win+r输入cmd打开cmd窗口,在cmd中输入:

32位:regsvr32 C:\Windows\System32\mscomm32.ocx
64位:regsvr32 C:\Windows\SysWOW64\mscomm32.ocx

如果失败,请以管理员身份打开cmd,再进行步骤3。

2.2 error LNK2001: 无法解析的外部符号
在进行编译时,出现如上错误的原因有两个,分别是
(1)部分函数声明了却未定义
(2)部分动态链接库的编译方式未统一

针对第一种错误,只需要找到未定义的函数,注释掉或者删除就可以了,在我的测试程序中,这类问题主要出现在BoxEditor中,可能是由于我的误操作导致,添加了OnEnChangeEditRev函数,该OnEnChange***函数针对的是窗口中数据内容变化的响应函数,但是实际没有实现这个函数,所以导致了错误。
参考:http://tieba.baidu.com/p/2049736254 

针对第二种错误,需要将 MFC使用 和 运行库 都进行统一。注意先将右上角的配置选为 所有配置, 具体选择如下:

参考:http://www.360doc.com/content/11/1031/14/4190063_160548608.shtml

附录:
在研究如何自动读取可用的串口号时,发现了一个十分完整的开源的串口通信项目。较为复杂,慢慢研究,该项目的地址如下:
http://blog.youkuaiyun.com/itas109/article/details/51337538


结语:
本文存在诸多不足,希望大家多多指教!
--------------------- 
作者:Peter_J 
来源:优快云 
原文:https://blog.youkuaiyun.com/Peter_JJH/article/details/77294592 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值