zoukankan      html  css  js  c++  java
  • vc 串口精灵软件分析

    前几天找这个源码,没有找到,今天找到了,有打开串口参数设置对话框,梳理一下关键实现代码:

    主界面如下:

          

    打开软件,设置初始的变量,串口参数:

    // CCommWizardDlg dialog
    
    CCommWizardDlg::CCommWizardDlg(CWnd* pParent /*=NULL*/)
        : CDialog(CCommWizardDlg::IDD, pParent)
    {
        bSend = FALSE;//自动发送标志
        bReceive = FALSE;//自动接收标志
    
        m_nPort = 1;//端口号
        m_strSettings = _T("9600,n,8,1");//串口参数
        m_strSendString = _T("");//发送的字符串
        m_nTime = 1000;//时间间隔1s
    
        m_nInputMode = 1;//输入模式设置为1
    
        //{{AFX_DATA_INIT(CCommWizardDlg)
        m_strReceive = _T("");//文本框内容清除
        //}}AFX_DATA_INIT
        // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
        m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    }

    初始化函数中:初始化输入模式选择,

        // TODO: Add extra initialization here
        m_ctrlDataType.AddString(_T("按ASCII码"));
        m_ctrlDataType.AddString(_T("按2进制"));//
        m_ctrlDataType.AddString(_T("按16进制"));
        m_ctrlDataType.SetCurSel(m_nInputMode);//初始化时是1,即按2进制

    改变组合框的输入模式代码:

    void CCommWizardDlg::OnSelchangeType() 
    {
        // TODO: Add your control notification handler code here
        m_nInputMode = m_ctrlDataType.GetCurSel();
    }

    
    
    清除接收文本框内容:

    void
    CCommWizardDlg::OnClear() { // TODO: Add your control notification handler code here m_strReceive = _T("");//清除接收文本框内容 }

    主对话框中定义声明的:

    // CCommWizardDlg dialog
    
    class CCommWizardDlg : public CDialog
    {
    // Construction
    public:
        char CCommWizardDlg::ConvertHexChar(char ch);
        int  String2Hex(CString str, CByteArray &senddata);//字符串到十六进制转换
        void OpenPort();//打开串口
        CCommWizardDlg(CWnd* pParent = NULL);    // standard constructor
    
        BOOL bSend;//发送
        BOOL bReceive;//接收
    
        int m_nInputMode;//输入模式
    
        int        m_nPort;//端口号
        CString    m_strSettings;//参数
        CString    m_strSendString;//发送的字符串
        int        m_nTime;//间隔时间
    // Dialog Data
        //{{AFX_DATA(CCommWizardDlg)
        enum { IDD = IDD_COMMWIZARD_DIALOG };
        CButton    m_ctrlReceive;//接收按钮控件
        CButton    m_ctrlSend;//发送按钮控件
        CComboBox    m_ctrlDataType;//控制数据类型  输入模式 组合框控件变量
        CString    m_strReceive;//接收到的字符串
        CMSComm    m_Com;//串口控件
        //}}AFX_DATA

    点击设置参数后,代码如下:

    void CCommWizardDlg::OnSettings() 
    {
        // TODO: Add your control notification handler code here
        CSettingDlg setDlg;//声明类对象
        
        setDlg.nPort = m_nPort;//上次设置的端口号值
        setDlg.nTime = m_nTime;//上次设置的间隔时间值
        setDlg.strSettings = m_strSettings;//上次设置的串口参数值
        setDlg.strSendString = m_strSendString;//上次设置的发送字符串值
    
        if(setDlg.DoModal() == IDOK)//弹出对话框,点确定按钮后返回值设置。
        {
            m_nPort = setDlg.nPort;//从setDlg(参数设置类)中获取端口号
            m_nTime = setDlg.nTime;//间隔时间值
            m_strSettings = setDlg.strSettings;//串口参数值
            m_strSendString = setDlg.strSendString;//发送字符串值
        }
        OpenPort();//打开串口
    }

    设置参数如下,设置串口相关参数。

    点确定之后,选择的串口就被打开了,代码如下:

    void CCommWizardDlg::OnSettings() 
    {
        // TODO: Add your control notification handler code here
        CSettingDlg setDlg;//声明类对象
        
        setDlg.nPort = m_nPort;//上次设置的端口号值
        setDlg.nTime = m_nTime;//上次设置的间隔时间值
        setDlg.strSettings = m_strSettings;//上次设置的串口参数值
        setDlg.strSendString = m_strSendString;//上次设置的发送字符串值
    
        if(setDlg.DoModal() == IDOK)//弹出对话框,点确定按钮后返回值设置。
        {
            m_nPort = setDlg.nPort;//从setDlg(参数设置类)中获取端口号
            m_nTime = setDlg.nTime;//间隔时间值
            m_strSettings = setDlg.strSettings;//串口参数值
            m_strSendString = setDlg.strSendString;//发送字符串值
        }
        OpenPort();//打开串口
    }

    打开串口函数:

    //打开串口
    void CCommWizardDlg::OpenPort()
    {
        if(m_Com.GetPortOpen())
            m_Com.SetPortOpen(FALSE);//关闭串口
    
        m_Com.SetCommPort(m_nPort); //选择串口号
        if( !m_Com.GetPortOpen())
            m_Com.SetPortOpen(TRUE);//打开串口
        else
            AfxMessageBox("cannot open serial port");
    
        m_Com.SetSettings(m_strSettings); //波特率9600,无校验,8个数据位,1个停止位
        m_Com.SetRThreshold(1); 
        //参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件
        m_Com.SetInputMode(1);
        m_Com.SetInputLen(0);  //设置当前接收区数据长度为0
        m_Com.GetInput();//先预读缓冲区以清除残留数据    
    }

    程序中的变量的声明定义:

    // CSettingDlg dialog
    
    class CSettingDlg : public CDialog
    {
    // Construction
    public:
        CSettingDlg(CWnd* pParent = NULL);   // standard constructor
        int nPort, nTime;
        CString strSettings, strSendString;
    // Dialog Data
        //{{AFX_DATA(CSettingDlg)
        enum { IDD = IDD_DIALOG1 };
        int        m_nPort;
        CString    m_strSettings;
        CString    m_strSendString;
        int        m_nTime;
        //}}AFX_DATA

    点确定后将数据保存在当前参数设置窗口类中。

    自动发送:

    自动发送代码:

    void CCommWizardDlg::OnSend() 
    {
        // TODO: Add your control notification handler code here
        bSend = !bSend;//取反。
        if(bSend)//发送。
        {
            m_ctrlSend.SetWindowText(_T("停止发送"));
            SetTimer(1,m_nTime,NULL);//发送时间为1000毫秒,启动发送。
        }
        else//停止发送。
        {
            m_ctrlSend.SetWindowText(_T("自动发送"));
            KillTimer(1);  //取消发送定时。
        }    
    }

    自动发送时启动定时器:

    void CCommWizardDlg::OnTimer(UINT nIDEvent) 
    {
        // TODO: Add your message handler code here and/or call default
        OnManualsend();//手动发送函数
        CDialog::OnTimer(nIDEvent);
    }

    调用手动发送函数:

    void CCommWizardDlg::OnManualsend() 
    {
        // TODO: Add your control notification handler code here
        CString strSend;//发送字符串
    
        if(m_nInputMode > 1)//输入模式大于1(字节数组,十六进制)
        {
            CByteArray hexdata;//字节数据,
            int len=String2Hex(m_strSendString ,hexdata);//字符串转十六进制字节数组
            m_Com.SetOutput(COleVariant(hexdata));//发送字节数组
        }
        else
            m_Com.SetOutput(COleVariant(m_strSendString));//发送数据,发送字符串
    }
    //字符串转十六进制字节数组
    int CCommWizardDlg::String2Hex(CString str, CByteArray &senddata)
    {
        int hexdata,lowhexdata;
        int hexdatalen=0;
        int len=str.GetLength();
        
        senddata.SetSize(len/2);
        
        for(int i=0;i<len;)
        {
            char lstr,hstr=str[i];
            if(hstr==' ')
            {
                i++;
                continue;
            }
            i++;
            if(i>=len)
                break;
            lstr=str[i];
            hexdata=ConvertHexChar(hstr);
            lowhexdata=ConvertHexChar(lstr);
            if((hexdata==16)||(lowhexdata==16))
                break;
            else 
                hexdata=hexdata*16+lowhexdata;
            i++;
            senddata[hexdatalen]=(char)hexdata;
            hexdatalen++;
        }
    
        senddata.SetSize(hexdatalen);
        return hexdatalen;
    }

    接收回显方式的选择:

    改变组合框输入模式选择:

    void CCommWizardDlg::OnSelchangeType() 
    {
        // TODO: Add your control notification handler code here
        m_nInputMode = m_ctrlDataType.GetCurSel();
    }

    接收数据:

    //自动接收按钮
    void CCommWizardDlg::OnReceive() 
    {
        // TODO: Add your control notification handler code here
        m_Com.GetInput();//先预读缓冲区以清除残留数据
        bReceive = !bReceive;//自动接收标志取反,,,定时器里有检测该变量
        if(bReceive)//自动接收
            m_ctrlReceive.SetWindowText(_T("停止接收"));//按钮控件文本设置
        else//不自动接收
            m_ctrlReceive.SetWindowText(_T("开始接收"));
    }
    //这是一个将字符转换为相应的十六进制值的函数
    //功能:若是在0-F之间的字符,则转换为相应的十六进制字符,否则返回-1
    char CCommWizardDlg::ConvertHexChar(char ch) 
    {
        if((ch>='0')&&(ch<='9'))
            return ch-0x30;
        else if((ch>='A')&&(ch<='F'))
            return ch-'A'+10;
        else if((ch>='a')&&(ch<='f'))
            return ch-'a'+10;
        else return (-1);
    }

    串口控件:

    BEGIN_EVENTSINK_MAP(CCommWizardDlg, CDialog)
        //{{AFX_EVENTSINK_MAP(CCommWizardDlg)
        ON_EVENT(CCommWizardDlg, IDC_COMMCTRL, 1 /* OnComm */, OnOnCommCommctrl, VTS_NONE)
        //}}AFX_EVENTSINK_MAP
    END_EVENTSINK_MAP()

    接收函数:

    void CCommWizardDlg::OnOnCommCommctrl() 
    {
        // TODO: Add your control notification handler code here
        VARIANT variant_inp;
        COleSafeArray safearray_inp;
        LONG len,k;
        BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed.
        CString strtemp;
        if(bReceive)
        {
            if(m_Com.GetCommEvent()==2)     //事件值为2表示接收缓冲区内有字符
            {
                variant_inp = m_Com.GetInput();   //读缓冲区
                safearray_inp = variant_inp;           //VARIANT型变量转换为ColeSafeArray型变量
                len=safearray_inp.GetOneDimSize(); //得到有效数据长度
                for(k=0;k<len;k++)
                    safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组
                for(k=0;k<len;k++)             //将数组转换为Cstring型变量
                {
                    BYTE bt=*(char*)(rxdata+k);      //字符型
                                
                    if(m_nInputMode == 2)
                        strtemp.Format("%02X ",bt); //将字符以十六进制方式送入临时变量strtemp存放,注意这里加入一个空隔
                    else 
                        strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放
    
                    m_strReceive = m_strReceive + strtemp;    //加入接收编辑框对应字符串    
                }
                m_strReceive += "
    ";
            }
        }
        UpdateData(FALSE);           //更新编辑框内容
    }

    在主对话框中加入串口控件后,引入 头文件#include "mscomm.h"

    串口h文件中有这几行代码:

    // CMSComm wrapper class
    
    class CMSComm : public CWnd
    {
    protected:
        DECLARE_DYNCREATE(CMSComm)
    public:
        CLSID const& GetClsid()
        {
            static CLSID const clsid
                = { 0x648a5600, 0x2c6e, 0x101b, { 0x82, 0xb6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14 } };
            return clsid;
        }
    发现自己的不足,善于利用找到的方法去扬长避短。行动起来。
  • 相关阅读:
    IIS7中的几种身份鉴别方式(一)Basic身份验证
    IIS7中的几种身份鉴别方式(二)集成身份验证
    java集合
    SharePoint 2010中welcome page的设置细节
    SharePoint中使用Linq出现未将对象引用到实例化的解决方法
    SharePoint 2010中关于An error was encountered while retrieving the user profile的处理方式记录
    The Need for an Architectural Body of Knowledge
    The Softer Side of the Architect
    Event Receivers 学习小结
    使用SmtpClient发送带图片的邮件的代码实现
  • 原文地址:https://www.cnblogs.com/rechen/p/5085253.html
Copyright © 2011-2022 走看看