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 += "\r\n";
        }
    }
    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;
    }

 

posted @ 2015-12-29 11:52  星雷热忱  阅读(642)  评论(0编辑  收藏  举报