打印
[技术讨论]

MFC之串口编程

[复制链接]
996|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主


串口软件是电子相关工程师经常会用到的,虽然网上有众多的串口软件,但是,有时候并一定适合
自己的应用,因此,针对与特殊应用,我们依然需要根据实际去改造串口软件,下面是使用VC6.0中
的MFC编写的串口程序,该程序仅仅实现了基本功能,如果实际应用,还需要使用者自行更改。

1:首先添加好串口控件
在对话框中,点击鼠标右键,选中“插入Active X控件”,然后选则Microsoft Communications Control version6.0
控件后在对话框中出现串口控件




2:遍历能够使用的COM口并按顺序显示在组合框中,并定义组合框变量m_Box


BYTE i;
  m_Box.SetCurSel(0);  //设置当前组合框索引
  for(i = 1; i < 17; i++)
  {
          port.Format(_T("\\\\.\\COM%d"), i);
            hCom = CreateFile(port.GetBuffer(0), 0, 0, 0, OPEN_EXISTING,     FILE_ATTRIBUTE_NORMAL, 0);
          if(INVALID_HANDLE_VALUE != hCom )
          {
            CloseHandle(hCom);
            m_Box.AddString(port.Mid(4));
          }
  }

3:通过组合框中选择串口,然后触发组合框的选中事件(::OnSelendokCombo1()),在里面完成串口初始化
BYTE serail  = FASLE;

void CRFTestDlg::OnSelendokCombo1()
{
        // TODO: Add your control notification handler code here
           CString port,str;
        BYTE sel;

        /*close the open serial port*/
        if(serail == TRUE)
        {
          m_Msc.SetPortOpen(FALSE);  //如果串口已经打开,先关闭
        }

        m_Box.GetLBText(m_Box.GetCurSel(), str);
        sel = atoi(str.Mid(3));

       m_Msc.SetCommPort(sel);
       if(!m_Msc.GetPortOpen())
        {
           m_Msc.SetPortOpen(TRUE);
          serail = TRUE;
          m_Static1.SetWindowText("OK!");
        }
        else
        {
          serail = FALSE;
          m_Static1.SetWindowText("Error!");
        }

        if(serail == TRUE)
        {
               m_Msc.SetSettings("9600,n,8,1");
               m_Msc.SetInputMode(1);   //二进制
            //m_Msc.SetInputMode(0); //以字符格式接收,注意字符接收数据的处理与二进制是不一样的
             //m_Msc.SetInBufferSize(1024);  //默认1024
             //m_Msc.SetOutBufferSize(1024);
               m_Msc.SetRThreshold(1);  //一个字节引发一次事件
               m_Msc.SetInputLen(0);   
               m_Msc.GetInput();
        }
}


4:发送5个串口数据
BYTE test[10] = {0x01,0x02,0x03,0x04,0x05};
BYTE i;

COleVariant value;
CByteArray OutBuf;

OutBuf.SetSize(5);
for(i = 0 ; i < 12; i++)
{
    OutBuf =  delet_all;
}

value = OutBuf;
m_Msc.SetOutput(value);



5:串口数据接收
如果串口收到数据,会触发comm事件,事件代码为2

以十六进制接收
BYTE RxData[256];
BYTE RxPos;
BYTE RxTimeOut ;

void CRFTestDlg::OnOnCommMscomm1()
{
        // TODO: Add your control notification handler code here
    VARIANT getrxbuf;  //任意类型
    COleSafeArray rx_save;
    LONG k,len;

    if(m_Msc.GetCommEvent() == 2)
    {
         getrxbuf = m_Msc.GetInput();
         rx_save = getrxbuf;

         RxTimeOut = 2;                           //用于接收超时判断
         len = rx_save.GetOneDimSize(); //得到有效数据长度

         for(k=0;k < len; k++,RxPos++)
         {
             rx_save.GetElement(&k,RxData+RxPos);//转换为BYTE型数组  
          }
        }
}

以字符格式接收
CString strRxdt ;
BYTE RxTimeOut;

void CRFTestDlg::OnOnCommMscomm1()
{
        // TODO: Add your control notification handler code here
    VARIANT getrxbuf;  //任意类型

     if(m_Msc.GetCommEvent() == 2)
     {
          getrxbuf = m_Msc.GetInput();
           strRxdt += getrxbuf.bstrVal;
           RxTimeOut = 3;
     }
}



6:硬件定时器的使用(软件定时器不太准)
6.1)在RFTestDlg.cpp文件中添加如下头文件,并把定时器使用的库包含进去,如图所示



#include "MMSystem.h"
#include "windows.h"

#pragma comment(lib, "winmm.lib")

定义一个全局变量
MMRESULT TimerId;

定义好定时器的回调函数
void CALLBACK TimeProc(UINT uID, UINT uMsg,DWORD dwUser, DWORD dw1, DWORD dw2)
{
  if (uID==TimerId)
  {
     if(RxTimeOut)
     {
        RxTimeOut--;
        if(RxTimeOut  == 0)
        {
           //处理接收到的数据
        }
     }
  }
}




在对话框中初始化函数中注册一个硬件定时器

TimerId = timeSetEvent(1000,0,TimeProc,0,TIME_PERIODIC);  //初始化一个一直周期运行的定时器,定时间隔1000ms

程序的运行结果:


源码下载(源码与上述过程略有不同,但是思路是一致的):
https://pan.baidu.com/s/1S4M9l_DTbHgCh2tSZaBB3w





相关帖子

沙发
红蛋大叔|  楼主 | 2018-7-19 09:39 | 只看该作者

使用特权

评论回复
板凳
GEA| | 2018-7-19 16:11 | 只看该作者

使用特权

评论回复
地板
123654789| | 2021-4-30 19:49 | 只看该作者
顶顶顶顶顶顶顶顶

使用特权

评论回复
5
123654789| | 2021-5-6 08:40 | 只看该作者
已经 下载

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

25

主题

69

帖子

3

粉丝