mfc串口通信上位机

运行效果

运行效果图

具体操作步骤:打开程序,点击设置按钮,设置串口号,波特率,奇偶校验。完成后点击打开串口,可发送和接受串口数据。

设置界面

实现功能:串口发送只能以字符串方式发送,串口接收数据需要以AA为帧头后跟9位字符。如果把串口tx和rx直接相连,在程序中测试会产生如下效果:

自收发测试

该工程的基础一篇百度文库的文档,链接如下:http://wenku.baidu.com/link?url=NkLGGRkSMk5TLd0exqQGVNN6KmQ8wwurD8QbsiWc68e6Kz0vXKEzrXqsVtFwrOn6uvwVoG3yUwepdY8yuqV13Wu87J2g-gX3T2gqsjIdxuG

实现代码

设置按键:

void CserialportDlg::OnBnClickedButtonset()
{
    // TODO: 在此添加控件通知处理程序代码
    CString strStatus,strTemp;
    double dblBand;
    if(m_setupdlg.DoModal()==IDOK)       //模态对话框
    {
        ComNumber=m_setupdlg.m_Com+1;
        dblBand=pow(2,(double)m_setupdlg.m_BandRate);
        dblBand=115200/dblBand;
        strStatus.Format(_T("%.0f"),dblBand);
        BandRate=strStatus;
        switch(m_setupdlg.m_Parity)
        {
            case 0:
            {
                Parity="N";
                break;
            }
            case 1:
            {
                Parity="O";
                break;
            }
            case 2:
            {
                Parity="E";
                break;
            }
        }   
        strStatus="COM";
        strTemp.Format(_T("%d"),ComNumber);
        strStatus+=strTemp;
        strStatus+=",";
        strStatus+=BandRate;
        strStatus+=",";
        strStatus+=Parity;
        strStatus+=",8,1";
        m_Para=strStatus;
        UpdateData(false);
    }
    ///write config file:string and test
    CString m_strSetPath;
    CString test;
    m_strSetPath=("C:\\config.ini");
    WritePrivateProfileString(_T("setting"),("compara"),m_Para,m_strSetPath);
    //结构名,变量名,要写的字符串,路径
    GetPrivateProfileString(_T("setting"),_T("compara"),                                    NULL,test.GetBuffer(100),100,m_strSetPath);

    /*
    //test
    m_Edit.SetSel(10000,10000);       
    m_Edit.ReplaceSel(test);
    m_Edit.ReplaceSel(_T("\n"));
    UpdateData(false);
    */

    //write config file:struct and test
    /*
    struct Data
    {
        int a1;
        CString a2;
        CString a3;
    };
    Data d1, d2;
    */
    d1.a1=ComNumber;
    d1.a2=BandRate;
    d1.a3=Parity;
           WritePrivateProfileStruct(_T("Struct"),_T("test"),&d1,sizeof(Data),m_strSetPath);
    //写入配置文件

    if(m_setupdlg.m_bgridoff)
    {
        m_Edit.ReplaceSel(_T("gridoff"));
        UpdateData(false);
    }
    if(m_setupdlg.m_bgridon)
    {
        m_Edit.ReplaceSel(_T("gridon"));
        UpdateData(false);
    }
}

打开串口按键:

void CserialportDlg::OnBnClickedButtonopen()
{
    // TODO: 在此添加控件通知处理程序代码
    if(m_mscomm.get_PortOpen())    //如果串口是打开的,则行关闭串口
    {
        m_mscomm.put_PortOpen(FALSE);
    }
    m_mscomm.put_CommPort(ComNumber);
    CString strPara;
        strPara=BandRate;
    strPara+=",";
    strPara+=Parity;
    strPara+=",8,1";
    m_mscomm.put_Settings(strPara);
    m_mscomm.put_InBufferSize(1024);//接收缓冲区
    m_mscomm.put_InBufferCount(0);
    m_mscomm.put_OutBufferSize(1024);//发送缓冲区
    m_mscomm.put_InputLen(0);//设置当前接收区数据长度为0,表示全部读取
    m_mscomm.put_InputMode(1);//以二进制方式读写数据   0是字符
    m_mscomm.put_RThreshold(1);//接收缓冲区有1个及1个以上字符时,将引发接收数据的  OnComm
    m_mscomm.put_PortOpen(TRUE);
    AfxMessageBox(_T("串口打开成功"));
    GetDlgItem(IDC_BUTTONCLOSE)->EnableWindow(TRUE);      //按钮可见    
}

串口关闭按钮:

void CserialportDlg::OnBnClickedButtonclose()
{
    // TODO: 在此添加控件通知处理程序代码
    m_mscomm.put_PortOpen(FALSE);
    AfxMessageBox(_T("串口关闭成功"));
    GetDlgItem(IDC_BUTTONCLOSE)->EnableWindow(FALSE);      //按钮可见
}

串口如果关闭不成功,可能会影响别的程序使用该串口,所以关闭成功一定要以消息框的形式显示。

串口发送数据按钮:

void CserialportDlg::OnBnClickedButtonsend()
{
    // TODO: 在此添加控件通知处理程序代码
    UpdateData(true);
    m_mscomm.put_Output(COleVariant(m_EditSend));
    m_EditSend.Empty();
    UpdateData(false);
}

串口发送只能以字符串方式发送,如果要以16进制发送,可以在此写处理代码,把16进制转换成字符串方式。

接收数据:

void CserialportDlg::OnCommMscomm()
{
    // TODO: 在此处添加消息处理程序代码
    int nEvent;
    nEvent = m_mscomm.get_CommEvent();
    switch(nEvent)
    {
    case 2:            //接收缓冲区有数据
        g_bCommDataRcv = true;     //为了控制数据接收线程
        break;
    case 3:
        break;
    default:
        break;
    }

    VARIANT            vResponse;
    int                len, i;
    unsigned char      buf[200];
    COleSafeArray      Oledata;
    BYTE               data[200];
    len =m_mscomm.get_InBufferCount();       //获取串口接收缓冲区数据字节数
    if (len > 0)
        {
        vResponse = m_mscomm.get_Input();     //读取缓冲区数据
        Oledata = vResponse;
        len = Oledata.GetOneDimSize();
        for(i=0; i<len; i++)
        {
            Oledata.GetElement((long *)&i, data+i);
        }
        for(i=0; i<len; i++)
        {
            char a = *(char *)(data+i);
            buf[i] = (unsigned char)a;
        }
        //串口数据进入字符队列
        int temp=BYTEsequence.GetCount();
        for(int k=0;k<len;k++)
            BYTEsequence.InsertAt(temp++,buf[k]);
    }
    bool bHead = FALSE;
    int location=0;
    int tt=0;
    char information[300];         //跟随length变化
    CString medit;
    while (BYTEsequence.GetCount() > 2*length+10)        //从全局数据队列BYTEsequence查找一个完整的合法数据包
    {
        len=BYTEsequence.GetCount();
        //验证数据包的同步头
        if (BYTEsequence.GetAt(tt)==0x41 &&BYTEsequence.GetAt(tt+1) ==0x41)                 //帧头AA
        {
            bHead = TRUE;
            location=tt;
        }
        tt++;
        if(tt>length+2)
            tt=0;
        if (bHead)
        {
            for(int k=0;k<length+1;k++)
            {
                information[k]=BYTEsequence.GetAt(location+2+k);
                if(k==length)
                    information[k]='\0';
            }
            BYTEsequence.RemoveAt(location,length+2);             //移除数据长加帧头帧尾长度
            if(location>0)
                for(int k=location-1;k>=0;k--)
                    BYTEsequence.RemoveAt(k,1);
            //输出information
            medit.Format(_T("%s"),information);
            m_Edit.SetSel(10000,10000);
            m_Edit.ReplaceSel(medit);
            m_Edit.ReplaceSel(_T("\n"));
            UpdateData(false);
            bHead=FALSE;
        }
    }
}

数据接收的函数编程工作量最大,其基本思路就是当串口缓存区有数据时触发这个函数,将接收到的数据写入字符队列,然后判断字符队列长度,一旦超过了两帧数据,就进行解析。首先识别帧头,把帧头前面的数据全部舍弃,从帧头开始取出一帧数据的长度,并把它显示在接收区。

用mscomm32控件操作串口有点复杂,这个程序对刚接触串口通信的人来说有点难度,所以我写了一个在stm32中的串口中断函数,思想和上面这个一样。

void UART3_IRQHandler()
{   
    //这个的数据格式是16进制,帧头D0+数据长度(01-FF)+目标地址(两位16进制数,如FF FF)+数据(16进制,超出数据长度的忽略)
    uint8 temp;
    temp = 1;
    if (1)
    {
        temp = uart_getchar();
        //TODO: put your code here
        if (RcvState == 0)
        {
            if (temp == 0xD0)
                RcvState = 1;
        }
        else if (RcvState == 1)
        {
            RcvSum = temp + 0x02;
            RcvState = 2;
        }
        else if (RcvState == 2)
        {
            if (RcvCnt < RcvSum)
            {
                RcvMsg[RcvCnt] = temp;
                RcvCnt++;
            }
            if (RcvCnt == RcvSum)
            {
                AnalyseInfo();  //在这个函数中进行数据处理,如果数据发送太快,而处理时间比较长,可以另开一个优先级比较低的中断处理,确保数据不会丢失。
                RcvCnt = 0;
                RcvSum = 0;
                RcvState = 0;
            }
        }
    }
}

关于读串口的操作分为两种方式,轮询方式和中断方式。轮询方式很少使用,除非你只干读串口这一件事。中断方式比较普遍,但要注意如果还有其他比较耗时的中断,需要将串口中断优先级设置的高一点,以免漏过数据。

关于串口通信,这一篇只是一个简单的例子,以后会有更加高级的例子和一些我用过的比较好的串口通信模块。

  • 1
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: MFC串口助手上位机源码是一种用于控制串口操作的应用程序源码。MFC(Microsoft Foundation Class)是一种用于开发Windows应用程序的类库,串口助手上位机源码使用MFC框架实现了串口通信的功能。 首先,该源码基于MFC中的CSerialPort类来管理串口连接。它通过调用一系列函数来打开、关闭、配置串口,并提供了发送和接收数据的功能。这样,用户可以通过该上位机源码实现与串口设备的通信。 其次,该上位机源码提供了图形化界面,使用者可以通过界面设置串口的参数,如波特率、数据位、停止位等。用户还可以在程序界面上输入要发送的数据,并通过点击发送按钮将数据发送到串口设备。同时,该上位机源码显示接收到的数据,并提供清除接收框的功能。 此外,该源码还提供了一些额外的功能,如保存接收到的数据到文件中,以便之后的数据分析。用户还可以通过设置定时器来定时发送数据,以实现与串口设备的交互操作。 总之,MFC串口助手上位机源码是一种基于MFC框架的应用程序源码,通过该源码实现了对串口设备的控制、数据的发送和接收,并提供了图形化界面和一些额外功能。用户可以根据自己的需求进行修改和拓展。 ### 回答2: MFC串口助手上位机的源码实际上是基于MFC(Microsoft Foundation Class)库开发的串口通信程序。该程序主要用于在计算机上与外部设备进行串口通信,实现数据的接收和发送。 MFC串口助手上位机的源码通常包含以下几个主要部分: 1. 界面设计:通过MFC的图形界面设计工具,设计程序的主窗口和其他相关界面,包括显示接收到的数据、发送数据的输入框、串口配置参数等。 2. 串口通信功能:使用MFC提供的串口通信类,如CSerialPort,实现串口的打开、关闭、配置、发送和接收等功能。可以通过设定波特率、数据位、校验位和停止位等参数,与外部设备进行正常的串口通信。 3. 数据处理:根据实际需求,对接收到的数据进行解析和处理。例如,可以将接收到的数据显示在界面上,或者根据特定的数据格式进行解析,并进行相应的操作。 4. 扩展功能:根据实际需求,可以添加其他的功能,如数据保存、数据分析、数据转发等。这些功能可以通过界面上的按钮或菜单实现,或者通过添加相应的事件和函数实现。 MFC串口助手上位机的源码可以作为一个起点,根据具体需求进行修改和扩展。可以根据实际情况,适当调整界面设计,增加新的功能模块,甚至实现与数据库或其他外部设备的交互等。 总之,MFC串口助手上位机的源码主要是为了提供一个基于MFC库的串口通信程序,方便用户与外部设备进行数据的交互和通信。使用该源码,可以快速构建并定制一个符合自己需求的串口通信应用程序。 ### 回答3: MFC串口助手上位机源码是一种用于控制串口设备的程序源代码。MFC(Microsoft Foundation Class)是微软公司的一种基于Windows的程序框架,用于开发Windows应用程序。上位机源码通常用于串口调试和控制领域,可以通过串口与下位机(嵌入式系统、传感器等)进行通信MFC串口助手上位机源码主要包括以下功能: 1. 串口参数设置:通过界面输入或下拉框选择,设置串口的波特率、数据位、停止位、校验位等参数。 2. 串口开关:通过按钮或复选框控制串口的打开和关闭,确保与下位机的连接状态。 3. 数据发送与接收:提供文本输入框或组合框,用户可以输入要发送的数据包或选择预定义命令。发送数据时,调用串口通信API将数据传输到下位机;接收数据时,监听并处理下位机返回的数据。 4. 数据显示:在用户界面上以文本窗口的形式实时显示发送和接收的数据,便于用户查看和分析通信过程。 5. 数据格式转换:对接收到的数据进行解析和转换,将原始数据转换为可读性高的格式,如16进制、ASCII码等。 6. 数据保存:提供文件保存按钮,允许用户将发送和接收的数据保存到本地计算机,用于后续分析和记录。 7. 快捷命令:通过添加快捷命令列表,用户可以保存常用命令,方便快速发送。 通过编写MFC串口助手上位机源码,我们可以实现对串口设备的简单操作和控制,方便用户进行串口通信调试和数据收发。该源码可以根据具体需求进行定制和扩展,以满足不同应用场景下的串口通信需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仟人斩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值