分享

VS2010/MFC 入门编程七(基于MSCOMM32.OCX控件的串口编程)

 独孤琅嬛 2015-01-31

值得注意的是 第一种方法的发送方式是发送不了0X00的,第二种方法中解决啦0x 00不能发送的问题; 

 

 

建立基于对话框的MFC工程,命名为“CommTest”,应用程序选择”基于对话框“

 

建立好工程如下图所示:

 

 

 

删除默认的按钮以及静态文本框,添加如下对话框控件:

A:打开串口控件,工具栏中拖一个botton 到 diadlg 上 ,并修改Caption 为 ”打开串口“,修改ID 为  IDC_BOTTON_OPEN

 

B: 关闭串口控件,工具栏中拖一个botton 到 diadlg 上 ,并修改Caption 为 ”关闭串口“,修改ID 为  IDC_BOTTON_CLOSE

 

C:发送控件,工具栏中拖一个botton 到 diadlg 上 ,并修改Caption 为 ”发送“,修改ID 为  IDC_BOTTON_SEND

 

D:发送编辑框 和  接受编辑框

 

 

添加通信串口控件,在对话框上右键

 

 

 

在对话框右下角电话样子的就是串口通信控件

 

 

给控件添加变量

在电话图标上右击:

 

命名如图示,点击完成 在工程中会自动生成mscomm.h 和mscomm.cpp两个文件;

 

给两个编辑框添加成员变量

 

添加三个按钮的事件

直接双击 三个按钮 会在程序中自动添加如下函数

  1. void CCommTestDlg::OnBnClickedButtonSend()  
  2. {  
  3.     // TODO: 在此添加控件通知处理程序代码  
  4. }  


 

  1. void CCommTestDlg::OnBnClickedButtonOpen()  
  2. {  
  3.     // TODO: 在此添加控件通知处理程序代码  
  4.       
  5. }  

 

  1. void CCommTestDlg::OnBnClickedButtonClose()  
  2. {  
  3.     // TODO: 在此添加控件通知处理程序代码  
  4. }  


 

 

 

 

添加控件事件处理函数:

 

 

 

点击添加编辑即可,在CommTestDlg.cpp中会生成函数:

  1. void CCommTestDlg::OnCommMscomm1()  
  2. {  
  3.     // TODO: 在此处添加消息处理程序代码  
  4. }  

数据接收都是从这个函数处理

 

 

打开串口函数实现:

  1. void CCommTestDlg::OnBnClickedButtonOpen()  
  2. {  
  3.     // TODO: 在此添加控件通知处理程序代码  
  4.     if(m_mscomm.get_PortOpen())  
  5.     {  
  6.             m_mscomm.put_PortOpen(FALSE);  
  7.     }  
  8.     m_mscomm.put_CommPort(3); //选择COM3  
  9.     m_mscomm.put_InBufferSize(1024); //接收缓冲区  
  10.     m_mscomm.put_OutBufferSize(1024);//发送缓冲区  
  11.     m_mscomm.put_InputLen(0);//设置当前接收区数据长度为0,表示全部读取  
  12.     m_mscomm.put_InputMode(1);//以二进制方式读写数据  
  13.     m_mscomm.put_RThreshold(1);//接收缓冲区有1个及1个以上字符时,将引发接收数据的OnComm  
  14.     m_mscomm.put_Settings(_T("9600,n,8,1"));//波特率9600无检验位,8个数据位,1个停止位  
  15.           
  16.     if(!m_mscomm.get_PortOpen())//如果串口没有打开则打开  
  17.     {  
  18.             m_mscomm.put_PortOpen(TRUE);//打开串口  
  19.             AfxMessageBox(_T("串口3打开成功"));  
  20.     }  
  21.     else  
  22.     {  
  23.             m_mscomm.put_OutBufferCount(0);  
  24.             AfxMessageBox(_T("串口3打开失败"));  
  25.     }  
  26.   
  27. }  


关闭按钮实现:

  1. void CCommTestDlg::OnBnClickedButtonClose()  
  2. {  
  3.     // TODO: 在此添加控件通知处理程序代码  
  4.     m_mscomm.put_PortOpen(FALSE);//关闭串口  
  5.     AfxMessageBox(_T("串口 3 已关闭"));  
  6. }  


发送代码实现:

  1. void CCommTestDlg::OnBnClickedButtonSend()  
  2. {  
  3.     // TODO: 在此添加控件通知处理程序代码  
  4.     UpdateData(true); //读取编辑框内容  
  5.     m_mscomm.put_Output(COleVariant(m_EditSend));//发送数据  
  6.     m_EditSend.Empty(); //发送后清空输入框  
  7.     UpdateData(false); //更新编辑框内容  
  8. }  


接受数据实现:

 

  1. void CCommTestDlg::OnCommMscomm1()  
  2. {  
  3.     // TODO: 在此处添加消息处理程序代码  
  4.     static unsigned int cnt=0;  
  5.     VARIANT variant_inp;  
  6.     COleSafeArray safearray_inp;  
  7.     long len,k;  
  8.     unsigned int data[1024]={0};  
  9.     byte rxdata[1024]; //设置 BYTE 数组  
  10.     CString strtemp;  
  11.     if(m_mscomm.get_CommEvent()==2) //值为 2 表示接收缓冲区内有字符  
  12.     {  
  13.         cnt++;  
  14.         variant_inp=m_mscomm.get_Input(); //读缓冲区消息  
  15.         safearray_inp=variant_inp; ///变量转换  
  16.         len=safearray_inp.GetOneDimSize(); //得到有效的数据长度  
  17.         for(k=0;k<len;k++)  
  18.         {  
  19.             safearray_inp.GetElement(&k,rxdata+k);  
  20.         }  
  21.         for(k=0;k<len;k++) //将数组转换为 CString 型变量  
  22.         {  
  23.             strtemp.Format(_T("%c"),*(rxdata+k));  
  24.             m_EditReceive+=strtemp;  
  25.             CString temp=_T("\r\n"); //换行  
  26.             m_EditReceive+=temp;  
  27.         }  
  28.     }  
  29.     UpdateData(FALSE); //更新编辑框内容  
  30. }  


//接收到的数据存放在
//byte 型数组 rxdata[1024]中,再进行进一步处理,此处只是
//以 16 进制显示出来
//说明(自己的理解):上面是基于事件驱动型的串口通信方式,感觉事件驱动与中断类似,但
//绝对不是中断,每一次响应事件的时候接收缓冲区的数据的长度不是固定的。例如:我的下
//位机发送了 10 个 BYTE 的数据,第一次上位机响应的时候只接收到 8 个,第二次响应时接收
//到另外两个。并不是每收到一个数据就响应一次。

 

下图是测试结果 收到的是a,b......显示的是数字码;

 

 

 

特被注意的是这样编程并不是所有的电脑都会兼容MSCOMM32.OCX,这时候就需要我们手动的在代码里面动态的注册MSCOMM32.OCX控件,函数的实现都是成APP函数开始 ,我们在APP函数的初始化函数中注册这个控件

 

实现代码:

  1. BOOL CProgrammerApp::InitInstance()  
  2. {  
  3.     HINSTANCE h;    
  4.     h = ::LoadLibrary(_T("MSCOMM32.OCX"));    
  5.          FARPROC pFunc = ::GetProcAddress((HMODULE)h,"DllRegisterServer");    
  6.          if (pFunc==NULL)    
  7.          {    
  8.                  ::MessageBox(NULL,_T("OCX控件加载失败!"),_T("错误"),MB_ICONERROR);    
  9.                  return FALSE;    
  10.          }    
  11.          pFunc();    
  12.         ......  
  13.         略  
  14. }  


 

 

解决不能发送oXoo 的问题

上面不能实现0x00发送的原因是因为字符串本身就是以0x00默认作为结束符,所以在数据发送到0x00时候就会默认的发错 而且 大于127是负数 ,系统并不知道你是带符号还是不带符号 上面的方法系统会默认带符号 所以发送0x00或则大于127的数据就会发送错误。

 

 

下面是实现的方法

实现的方法是 将需要发送的内容通过二进制发送

 

  1. void CProgrammerDlg::TranSmitt(void)  
  2. {  
  3.     int i;  
  4.     unsigned short sum = 0; //计算校验和   
  5.     CByteArray   array;   
  6.           
  7.     for(i=0; i< m_sendlength; i++)  //计算校验和  
  8.     {  
  9.         sum += Txbufer[i];  
  10.     }  
  11.   
  12.     sum =sum^0xFFFF;  
  13.     Txbufer[m_sendlength++] =  (unsigned char)(sum&0x00FF);  
  14.     Txbufer[m_sendlength++] =  (unsigned char)((sum&0xFF00) >> 8);  //存储校验和  
  15.   
  16.     array.RemoveAll();                          //清空数组   
  17.     array.SetSize(m_sendlength);                //设置数组大小为帧长度   
  18.   
  19.     for(i=0; i< m_sendlength; i++)            //把待发送数据存入数组   
  20.            {  
  21.         array.SetAt(i,Txbufer[i]);   
  22.     }  
  23.          m_mscomm.put_Output(COleVariant(array));  
  24. }  



 

 

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多