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

来源:互联网 发布:怎么看淘宝卖家的电话 编辑:程序博客网 时间:2024/06/05 02:05

参考文档: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("\r\n");//显示完成后要自动换行
  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("\r\n");//显示完成后要自动换行
 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:  };
0 0