• MSComm串口类的使用 (程序设计)


    参考文档:http://wenku.baidu.com/link?url=MLGQojaxyHnEgngEAXG8oPnISuM9SVaDzNTvg0oTSrrJkMXIR_6MR3cO_Vnh-grkUekLw2CSnQlE2ni5P-CzCCyI36fnNFFl_BkbEbMomP_     MSComm在VS2010中的实现过程

    注:在vs2010中MSComm类中一些函数被改变了,例如setcommport()被改成了put_commport(),getinput()改为了get_input(),以此类推。

    串口编程流程

    image

    1、串口初始化。

         在MSCommDlg.cpp中的OnInitDialog()中,加入串口初始化代码。

    代码如下:

       1:  // CMSCommDlg 消息处理程序
       2:   
       3:  BOOL CMSCommDlg::OnInitDialog()
       4:  {
       5:      CDialogEx::OnInitDialog();
       6:   
       7:      // 将“关于...”菜单项添加到系统菜单中。
       8:   
       9:      // IDM_ABOUTBOX 必须在系统命令范围内。
      10:      ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
      11:      ASSERT(IDM_ABOUTBOX < 0xF000);
      12:   
      13:      CMenu* pSysMenu = GetSystemMenu(FALSE);
      14:      if (pSysMenu != NULL)
      15:      {
      16:          BOOL bNameValid;
      17:          CString strAboutMenu;
      18:          bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
      19:          ASSERT(bNameValid);
      20:          if (!strAboutMenu.IsEmpty())
      21:          {
      22:              pSysMenu->AppendMenu(MF_SEPARATOR);
      23:              pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
      24:          }
      25:      }
      26:   
      27:      // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
      28:      //  执行此操作
      29:      SetIcon(m_hIcon, TRUE);            // 设置大图标
      30:      SetIcon(m_hIcon, FALSE);        // 设置小图标
      31:   
      32:      // TODO: 在此添加额外的初始化代码
      33:      m_Comm.put_CommPort(2);//选择串口2
      34:      m_Comm.put_InputMode(1);//输入模式为二进制模式
      35:      m_Comm.put_InBufferSize(1024);//输入缓冲区大小
      36:      m_Comm.put_OutBufferSize(512);//输出缓冲区大小
      37:      //设置波特率9600,无奇偶校验,8位数据位,1位停止位
      38:      m_Comm.put_Settings(_T("9600,n,8,1"));
      39:      if(!m_Comm.get_PortOpen())
      40:      {
      41:          m_Comm.put_PortOpen(TRUE);//打开串口
      42:      }
      43:      //每接收一个字符或多个字符就会触发OnComm事件
      44:      m_Comm.put_RThreshold(1);//每当接收缓冲区有1个字符则接收串口数据
      45:      //清空缓存区内容
      46:      m_Comm.put_InputLen(0);//  设置当前缓冲区长度为0
      47:      m_Comm.get_Input();   //   预读缓冲区以清除残留数据(从接收缓冲区中读取数据)
      48:   
      49:      return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
      50:  }

    2、为MSComm类添加事件处理函数OnCommMscomm1();用于处理接收到的数据。

         注:在此介绍一个小知识。文本框如何和字符串相关联。

    DDX_Control 与 DDX_Text 区别

          1)DDX_Text()的作用可以理解为把字符串变量与控件的文本(WindowText)关联起来。

          2)DDX_Control()的作用可以理解为把变量和控件本身相关联,此变量就是一个控件类型的变量。

          3)DoDataExchange(pDX)的作业可以理解为处理所有变量与其相关联控件,两者进行数据交换的函数。

       1:  void CView::DoDataExchange(CDataExchange* pDX)
       2:  
       3:        CFormView::DoDataExchange(pDX);
       4:        DDX_Text(pDX, IDC_ID_VALUE, m_strID);      //1
       5:        DDX_Control(pDX, IDC_ID_VALUE, m_editID);  //2
       6:  

          针对1:  通过updateData(TRUE)取得控件上的值传给m_strID,此时说明可以进行修改。修改完之后,通过ApdateData(FALSE),将变量的值传回控件,然后进行界面显示。
          针对2: 通过m_editID.GetWindText(str),取得值,处理后,通过m_editID.SetWindText(str)传回控件界面显示。

    下面再举一个小实例来进行说明:

    给编辑框加成员变量m_strA
    在响应插入操作的消息里如下写
    UpdateData(TRUE);
    m_strA += _T("b"); //此处只能是一个常量,变量行不通,需要利用DDX_Text()或者下面的函数进行处理。
    UpdateData(FALSE);
    等同于:
    CString str;
    ((CEdit*)GetDlgItem(IDC_EDIT)->GetWindowText(str);
    str+="b";
    ((CEdit*)GetDlgItem(IDC_EDIT)->SetWindowText(str);
     
     
    主要程序如下:
       1:  void CMSCommDlg::OnCommMscomm1()
       2:  {
       3:      // TODO: 在此处添加消息处理程序代码
       4:      VARIANT variant_inp;//VARIANT型变量,用于接收串口数据
       5:      COleSafeArray safearray_inp;//安全数组,用于接收串口数据
       6:      LONG len,k;
       7:      BYTE rxdata[2048];//接收数据缓冲区
       8:      CString strTemp;
       9:      if(m_Comm.get_CommEvent() == 2)//事件值为2表示有接收到的数据到来
      10:      {
      11:          variant_inp = m_Comm.get_Input();
      12:          safearray_inp = variant_inp;//将VARIANT类型变量转换为COleSafeArray类型变量(我们可以理解为一个容器,有数据有长度尺寸等。)
      13:          len = safearray_inp.GetOneDimSize();//获取有效数据的长度
      14:          for(k = 0; k < len; k++)
      15:          {
      16:              safearray_inp.GetElement(&k,rxdata+k);//将COleSafeArray类型变量,拆解为字符数组。
      17:          }
      18:          for(k = 0; k < len; k++)  //将字符数组转换为字符串类型变量
      19:          {
      20:              BYTE bt = *(char *)(rxdata + k);
      21:              strTemp.Format(_T("%c"),bt);
      22:              m_strEditRXData += (strTemp);
      23:          }
      24:      }
      25:      //自动换行的实现
      26:      CString temp = _T("
    ");//显示完成后要自动换行
      27:      //_T就是TEXT,vs2010里面为了兼容vc6.0而设计的转换(兼容)函数。
      28:      m_strEditRXData += temp;
      29:      UpdateData(FALSE); //显示接收编辑框中的内容
      30:  }

    3、发送数据。通过put_output()函数,向发送缓冲区写入数据即可。

         为对话框类添加onbuttonsend函数,然后编辑。核心代码如下:

       1:  void CMSCommDlg::OnBnClickedButton1Send()
       2:  {
       3:      // TODO: 在此添加控件通知处理程序代码
       4:      UpdateData(TRUE); //读取发送编辑框中的文本内容
       5:      //对发送的数据进行强制类型转换,由CString 字符串数据转换为VARIANT 类型。
       6:      m_Comm.put_Output(COleVariant(m_strEditTXData));//发送数据,可以将字符串变为VARIANT型数据类型
       7:      //以下两句代码可以不要。以下两句为一个整体,用其一肯定没有用处。
       8:      //用下面两句就不用手动清空了。呵呵,可以自动清空发送缓冲区数据。
       9:      //首先清空发送的字符串变量,然后将此变量的值返回给控件。使控件为空。从而达到清空的目的。
      10:      m_strEditTXData.Empty();//发送后清空输入框
      11:      UpdateData(FALSE);     //更新编辑框内容
      12:  }

    4、结果演示:

    image

     
     
    以下是整个代码:(供读者朋友们参考)
    MSCommDlg.cpp文件:
       1:   
       2:  // MSCommDlg.cpp : 实现文件
       3:  //
       4:   
       5:  #include "stdafx.h"
       6:  #include "MSComm.h"
       7:  #include "MSCommDlg.h"
       8:  #include "afxdialogex.h"
       9:  #include "Resource.h"
      10:   
      11:  #ifdef _DEBUG
      12:  #define new DEBUG_NEW
      13:  #endif
      14:   
      15:   
      16:  // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
      17:   
      18:  class CAboutDlg : public CDialogEx
      19:  {
      20:  public:
      21:      CAboutDlg();
      22:   
      23:  // 对话框数据
      24:      enum { IDD = IDD_ABOUTBOX };
      25:   
      26:      protected:
      27:      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
      28:   
      29:  // 实现
      30:  protected:
      31:      DECLARE_MESSAGE_MAP()
      32:  };
      33:   
      34:  CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
      35:  {
      36:  }
      37:   
      38:  void CAboutDlg::DoDataExchange(CDataExchange* pDX)
      39:  {
      40:      CDialogEx::DoDataExchange(pDX);
      41:  }
      42:   
      43:  BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
      44:  END_MESSAGE_MAP()
      45:   
      46:   
      47:  // CMSCommDlg 对话框
      48:   
      49:   
      50:   
      51:   
      52:  CMSCommDlg::CMSCommDlg(CWnd* pParent /*=NULL*/)
      53:      : CDialogEx(CMSCommDlg::IDD, pParent)
      54:  {
      55:      m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
      56:      m_strEditRXData = _T(""); //也可以自己自动在对话框上右击,添加变量生成。
      57:      m_strEditTXData = _T("");
      58:  }
      59:   
      60:  void CMSCommDlg::DoDataExchange(CDataExchange* pDX)
      61:  {
      62:      CDialogEx::DoDataExchange(pDX);
      63:      DDX_Control(pDX, IDC_MSCOMM1, m_Comm);
      64:      //  DDX_Control(pDX, IDC_EDIT1, m_strEditRXData);
      65:      DDX_Text(pDX,IDC_EDIT1,m_strEditRXData);
      66:      DDX_Text(pDX,IDC_EDIT2,m_strEditTXData);
      67:  }
      68:   
      69:  BEGIN_MESSAGE_MAP(CMSCommDlg, CDialogEx)
      70:      ON_WM_SYSCOMMAND()
      71:      ON_WM_PAINT()
      72:      ON_WM_QUERYDRAGICON()
      73:      ON_BN_CLICKED(IDC_BUTTON1_SEND, &CMSCommDlg::OnBnClickedButton1Send)
      74:  END_MESSAGE_MAP()
      75:   
      76:   
      77:  // CMSCommDlg 消息处理程序
      78:   
      79:  BOOL CMSCommDlg::OnInitDialog()
      80:  {
      81:      CDialogEx::OnInitDialog();
      82:   
      83:      // 将“关于...”菜单项添加到系统菜单中。
      84:   
      85:      // IDM_ABOUTBOX 必须在系统命令范围内。
      86:      ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
      87:      ASSERT(IDM_ABOUTBOX < 0xF000);
      88:   
      89:      CMenu* pSysMenu = GetSystemMenu(FALSE);
      90:      if (pSysMenu != NULL)
      91:      {
      92:          BOOL bNameValid;
      93:          CString strAboutMenu;
      94:          bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
      95:          ASSERT(bNameValid);
      96:          if (!strAboutMenu.IsEmpty())
      97:          {
      98:              pSysMenu->AppendMenu(MF_SEPARATOR);
      99:              pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
     100:          }
     101:      }
     102:   
     103:      // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
     104:      //  执行此操作
     105:      SetIcon(m_hIcon, TRUE);            // 设置大图标
     106:      SetIcon(m_hIcon, FALSE);        // 设置小图标
     107:   
     108:      // TODO: 在此添加额外的初始化代码
     109:      m_Comm.put_CommPort(2);//选择串口2
     110:      m_Comm.put_InputMode(1);//输入模式为二进制模式
     111:      m_Comm.put_InBufferSize(1024);//输入缓冲区大小
     112:      m_Comm.put_OutBufferSize(512);//输出缓冲区大小
     113:      //设置波特率9600,无奇偶校验,8位数据位,1位停止位
     114:      m_Comm.put_Settings(_T("9600,n,8,1"));
     115:      if(!m_Comm.get_PortOpen())
     116:      {
     117:          m_Comm.put_PortOpen(TRUE);//打开串口
     118:      }
     119:      //每接收一个字符或多个字符就会触发OnComm事件
     120:      m_Comm.put_RThreshold(1);//每当接收缓冲区有1个字符则接收串口数据
     121:      //清空缓存区内容
     122:      m_Comm.put_InputLen(0);//  设置当前缓冲区长度为0
     123:      m_Comm.get_Input();   //   预读缓冲区以清除残留数据(从接收缓冲区中读取数据)
     124:   
     125:      return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
     126:  }
     127:   
     128:  void CMSCommDlg::OnSysCommand(UINT nID, LPARAM lParam)
     129:  {
     130:      if ((nID & 0xFFF0) == IDM_ABOUTBOX)
     131:      {
     132:          CAboutDlg dlgAbout;
     133:          dlgAbout.DoModal();
     134:      }
     135:      else
     136:      {
     137:          CDialogEx::OnSysCommand(nID, lParam);
     138:      }
     139:  }
     140:   
     141:  // 如果向对话框添加最小化按钮,则需要下面的代码
     142:  //  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
     143:  //  这将由框架自动完成。
     144:   
     145:  void CMSCommDlg::OnPaint()
     146:  {
     147:      if (IsIconic())
     148:      {
     149:          CPaintDC dc(this); // 用于绘制的设备上下文
     150:   
     151:          SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
     152:   
     153:          // 使图标在工作区矩形中居中
     154:          int cxIcon = GetSystemMetrics(SM_CXICON);
     155:          int cyIcon = GetSystemMetrics(SM_CYICON);
     156:          CRect rect;
     157:          GetClientRect(&rect);
     158:          int x = (rect.Width() - cxIcon + 1) / 2;
     159:          int y = (rect.Height() - cyIcon + 1) / 2;
     160:   
     161:          // 绘制图标
     162:          dc.DrawIcon(x, y, m_hIcon);
     163:      }
     164:      else
     165:      {
     166:          CDialogEx::OnPaint();
     167:      }
     168:  }
     169:   
     170:  //当用户拖动最小化窗口时系统调用此函数取得光标
     171:  //显示。
     172:  HCURSOR CMSCommDlg::OnQueryDragIcon()
     173:  {
     174:      return static_cast<HCURSOR>(m_hIcon);
     175:  }
     176:   
     177:  BEGIN_EVENTSINK_MAP(CMSCommDlg, CDialogEx)
     178:      ON_EVENT(CMSCommDlg, IDC_MSCOMM1, 1, CMSCommDlg::OnCommMscomm1, VTS_NONE)
     179:  END_EVENTSINK_MAP()
     180:   
     181:   
     182:  void CMSCommDlg::OnCommMscomm1()
     183:  {
     184:      // TODO: 在此处添加消息处理程序代码
     185:      VARIANT variant_inp;//VARIANT型变量,用于接收串口数据
     186:      COleSafeArray safearray_inp;//安全数组,用于接收串口数据
     187:      LONG len,k;
     188:      BYTE rxdata[2048];//接收数据缓冲区
     189:      CString strTemp;
     190:      if(m_Comm.get_CommEvent() == 2)//事件值为2表示有接收到的数据到来
     191:      {
     192:          variant_inp = m_Comm.get_Input();
     193:          safearray_inp = variant_inp;//将VARIANT类型变量转换为COleSafeArray类型变量(我们可以理解为一个容器,有数据有长度尺寸等。)
     194:          len = safearray_inp.GetOneDimSize();//获取有效数据的长度
     195:          for(k = 0; k < len; k++)
     196:          {
     197:              safearray_inp.GetElement(&k,rxdata+k);//将COleSafeArray类型变量,拆解为字符数组。
     198:          }
     199:          for(k = 0; k < len; k++)  //将字符数组转换为字符串类型变量
     200:          {
     201:              BYTE bt = *(char *)(rxdata + k);
     202:              strTemp.Format(_T("%c"),bt);
     203:              m_strEditRXData += (strTemp);
     204:          }
     205:      }
     206:      //自动换行的实现
     207:      CString temp = _T("
    ");//显示完成后要自动换行
     208:      //_T就是TEXT,vs2010里面为了兼容vc6.0而设计的转换(兼容)函数。
     209:      m_strEditRXData += temp;
     210:      UpdateData(FALSE); //显示接收编辑框中的内容
     211:  }
     212:   
     213:   
     214:  void CMSCommDlg::OnBnClickedButton1Send()
     215:  {
     216:      // TODO: 在此添加控件通知处理程序代码
     217:      UpdateData(TRUE); //读取发送编辑框中的文本内容
     218:      //对发送的数据进行强制类型转换,由CString 字符串数据转换为VARIANT 类型。
     219:      m_Comm.put_Output(COleVariant(m_strEditTXData));//发送数据,可以将字符串变为VARIANT型数据类型
     220:      //以下两句代码可以不要。以下两句为一个整体,用其一肯定没有用处。
     221:      //用下面两句就不用手动清空了。呵呵,可以自动清空发送缓冲区数据。
     222:      //首先清空发送的字符串变量,然后将此变量的值返回给控件。使控件为空。从而达到清空的目的。
     223:      m_strEditTXData.Empty();//发送后清空输入框
     224:      UpdateData(FALSE);     //更新编辑框内容
     225:  }

    MSCommDlg.h 文件:

       1:   
       2:  // MSCommDlg.h : 头文件
       3:  //
       4:   
       5:  #pragma once
       6:  #include "mscomm1.h"
       7:  #include "afxwin.h"
       8:   
       9:   
      10:  // CMSCommDlg 对话框
      11:  class CMSCommDlg : public CDialogEx
      12:  {
      13:  // 构造
      14:  public:
      15:      CMSCommDlg(CWnd* pParent = NULL);    // 标准构造函数
      16:   
      17:  // 对话框数据
      18:      enum { IDD = IDD_MSCOMM_DIALOG };
      19:   
      20:      protected:
      21:      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
      22:   
      23:   
      24:  // 实现
      25:  protected:
      26:      HICON m_hIcon;
      27:   
      28:      // 生成的消息映射函数
      29:      virtual BOOL OnInitDialog();
      30:      afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
      31:      afx_msg void OnPaint();
      32:      afx_msg HCURSOR OnQueryDragIcon();
      33:      DECLARE_MESSAGE_MAP()
      34:  public:
      35:      DECLARE_EVENTSINK_MAP()
      36:      void OnCommMscomm1();
      37:      afx_msg void OnBnClickedButton1Send();
      38:      CMscomm1 m_Comm;
      39:      CString    m_strEditRXData;   //可以通过为对话框添加变量建立此变量,也可以直接敲代码建立此成员变量。
      40:      CString    m_strEditTXData;    //假如是通过直接敲代码建立的成员变量,需要在.cpp文件里面手动初始化。然后,在和需要联系的
      41:     //    CEdit m_strEditRXData;    // 控件建立联系。.cpp里面有很详细。
      42:  };
  • 相关阅读:
    spring复杂数据类型传递
    spring表单—乱码解决方案
    spring重定向与转发
    线程在WPF中的使用
    xheditor编辑器上传截图图片抓取远程图片代码
    js window.open()弹出窗口参数说明及居中设置
    INFORMATION_SCHEMA.COLUMNS 查询表字段语句
    SQL 使用Cursor(游标)遍历结果集
    js禁止浏览器滚屏方法
    基础-ADO插入数据后返回自增ID @@IDENTITY
  • 原文地址:https://www.cnblogs.com/zhuxuekui/p/3551350.html
Copyright © 2020-2023  润新知