MFC中CnComm串口类移植方法(小白篇)

来源:互联网 发布:类似知乎的论坛 编辑:程序博客网 时间:2024/06/18 12:35

最近在学习MFC编写串口,首先使用了MSCOMM控件来编写,简单好用,但是它有一个缺点就是当它发布的时候,需要相应的计算机也要进行MSCOMM的注册,串口助手是一个小软件,使用前还要注册,这对于用户来说是非常麻烦的。所以放弃了MSCOMM控件;接着又使用CSerialPort这个串口类来编写,移植完了之后发现一个奇怪的问题,我使用单片机通过CP2102跟电脑通信,这个类做出来的串口助手竟然不能发送和接收数据!!!使用其他串口助手却没有这个问题,这让我很困惑,以为是我移植出错了,但是我下载别人使用这个CSerialPort这个类写出来的串口助手,也真的发送和接收不了我板子上面CP2102的数据。最后我只能放弃这个很经典的类。

接下来我就找到了CnComm这个类,虽然这个类提供了历程,但是对于刚刚学习它的我来说,还是很难找到移植参考,而在网上找了很多移植资料,都是不完整的,会出现问题的。所以这里自己整理了一下移植方式,给大家做个参考,同时也整理一下自己学习到的知识。


步骤1:

         添加CnComm.h到工程目录中。然后声明一个串口对象为主窗口类的成员(私有成员和共有成员),添加代码如下:

         CnComm m_Cncomm;         //串口声明

         其中成员名字随便取。

步骤2:

         在主窗口类的构造函数中设置Cncomm类的使用模式,在主窗口类的构造函数中添加代码如下:

m_Cncomm.SetOption(m_Cncomm.GetOption() |CnComm::EN_RX_BUFFER);//设置模式

步骤3:

         将主窗口句柄给串口类,因为串口需要发送到主窗口中显示需要句柄。在主窗口类的OnInitDialog()中添加代码如下:

         m_Cncomm.SetWnd(this->m_hWnd);

步骤4:

         在主窗口类中添加串口设置成员函数。(这个步骤也可以省略,省略的话,在使用CnComm类的Open()函数的时候,就默认设置为波特率9600,1位停止位,8位数据位,无检验位)。成员函数的代码参考如下:

         BOOL CcommDlg::CommSetState()

其中m_portBaund,m_portByteSize,m_portStopByte,m_portParity就是你要设置的值。

步骤5:

         在主窗口类中添加串口接收消息映射。

1)        首先窗口类中添加消息函数声明,代码如下:

         afx_msg LRESULT OnCommRxchar(WPARAM wParam,LPARAM lParam);

2)        然后在源文件中添加消息映射。代码如下:

        BEGIN_MESSAGE_MAP(CcommDlg, CDialogEx)

    ON_WM_SYSCOMMAND()

   ON_WM_PAINT()

    ON_WM_QUERYDRAGICON()

    ON_MESSAGE(ON_COM_RECEIVE, &CcommDlg::OnCommRxchar)//只用添加这一句

END_MESSAGE_MAP()

3)   在源文件中添加函数,参考代码如下:

/接收消息响应函数

afx_msg LRESULT CcommDlg::OnCommRxchar(WPARAMwParam, LPARAM lParam)

{

 

   if (wParam  ==m_Cncomm.GetPort())

    {

        UpdateData();

        do

        {

            char buffer[1024];

            int len = m_Cncomm.Read(buffer, 1023);

            if(len == 0)

            {

                return TRUE;

            }

           buffer[len]= '\0';

 

            //刷新数据到接收框

           for(int i=0;i<len; i++)

            {

               if( '\n' ==buffer[i])    //若是遇到‘\n’那么进行换行

               {

                    m_editReceive+= '\r';

                }

                m_editReceive+= buffer[i];

            }

        }

        while(m_Cncomm.IsRxBufferMode() &&m_Cncomm.Input().SafeSize());

        UpdateData(FALSE);//刷新数据到显示框

    }

    return TRUE;

}

在上面的函数中,接收函数添加一个遇到'\n'就换行的代码,否则刷新数据到接收框可以使用更加简洁的代码:

m_editReceive += buffer;

 

步骤6:

         编写开启串口函数。参考代码如下:

    if(!m_Cncomm.IsOpen())

    {

        if(!m_Cncomm.Open(portNum))

        {

            AfxMessageBox(_T("打开串口失败"));

           return;

        }

       if(!CommSetState())

{

           m_Cncomm.Close();

            AfxMessageBox(_T("串口设置失败"));

        }

    }

    else

    {

        m_Cncomm.Close();

        AfxMessageBox(_T("关闭串口"));

    }

步骤7:

         添加发送数据成员函数,参考代码如下:

//发送键函数

void CcommDlg::OnBnClickedButtonSend()

{

    UpdateData(TRUE);

    char* buffer =new char[m_editSend.GetLength()*2+1];

    strcpy(buffer,(LPCTSTR)m_editSend);

   int len = m_editSend.GetLength();

    m_sendTotial+= len;

    //重叠模式下或者缓冲区模式下可以不检查输出返回值并直接输出

    if (m_Cncomm.IsOverlappedMode() ||m_Cncomm.IsTxBufferMode())

    {

       m_Cncomm.Write(buffer);    

    }

    else

     {//阻塞非缓冲区模式必须检查返回值确保数据完全发送出

        for (int i = 0;i<len; i++ )

      {

            i+= m_Cncomm.Write(buffer + i, len - i);

        }

    }

    UpdateTxLength();

}

0 0
原创粉丝点击