基于MFC串口编程和曲线图绘制(visual studio2008,Teechart绘图控件)的程序总结

前言


今年刚进入公司按经理的要求为底盘测控机写了一个小小的console。这也是第一次教认真的完成整个程序的编写。程序不大,所用技术比较基础也不前卫,属于初级程序员的练手程序(知识的整理和搬运)。虽然如此,期间也由于一次选用的方案不正确而推掉重做了一次。

要是有什么写的不对的地方请留言赐教,谢谢。

介绍

以下是这次用到的主要知识内容:
1)MSCOMM串口控件编程;
2)Window API函数的串口编程;
3)Teechart绘图控件编程;
4)Windows 函数多线程编程;
5)MFC主窗口和子窗口间的值传递和控件控制;
6)MFC自定义消息函数和子窗口的初始化函数;
7)MFC各种控件的使用:Combo box control,edit control,button control,text control,tab control,check-box control,以及两个外插控件MScomm串口控件和Teechart绘图控件。

MScomm控件串口编程

第一次的方案选用MScomm控件实现串口数据的传输,之后改用windows API串口编程。其是全双工,封装性好,不需要太多的了解内部的实现方式和协议的细节,只需简单的调用相应的API就能实现相应的功能。但其缺点是不够灵活,而且*不支持多线程*(放弃使用的原因),要在其他主机使用该控件编写的程序时需要注册该控件(第三方控件都需要如此)。下面做简单的使用总结,并提及一些个人使用中在意的细节。更详细的使用方式其他博客有很多。

使用方式如下:

创建控件并添加响应函数和控制变量->配置串口参数并打开串口->在响应函数中实现数据接收和发送的处理->关闭串口。
下载好控件并安装。控件下载路径
在VS工具栏中,选择工具(T)->选择工具选项(x)->com组件->选中控件并点确认。选中红色框中的选项

之后工具栏中就会有一个电话的图形控件。MScomm控件

把该控件添加到界面视图,并添加OnComm()响应事件和控制变量。就可以按自己要求实现相应的串口通讯功能了(初始化各属性和参数->在OnComm()响应函数中实现数据处理功能)。
在该程序中使用的函数有:
put_CommPort()//选择串口
put_RThreshold()//设置触发OnComm事件的条件
put_InputMode()//验取数据方式
put_InBufferSize()//输入缓冲区大小
put_OutBufferSize()//输出缓冲区大小
put_Settings()//串口参数设置
put_InputLen()//设置接收区数据长度
put_PortOpen()//打开串口

get_PortOpen()//获取串口状态
get_Input()//获取缓冲区数据
get_CommEvent()//获取串口事件

OnComm()//响应函数

个人的实现代码片段:

//设置-----------------------------------
    if(m_CtrlComm.get_PortOpen())
        m_CtrlComm.put_PortOpen(FALSE);

    m_CtrlComm.put_CommPort(COM_NUM);           //选择串口号
    m_CtrlComm.put_RThreshold(2);               //收到两个字节引发OnComm事件
    m_CtrlComm.put_InputMode(1);                //输入模式选为二进制
    m_CtrlComm.put_InBufferSize(1024);          //设置输入缓冲区的大小,Bytes
    m_CtrlComm.put_OutBufferSize(1024);         //设置输出缓冲区的大小,Bytes
    m_CtrlComm.put_Settings(SerialPortMessage); //设置串口参数,波特率,奇偶校验,数据位,停止位
    m_CtrlComm.put_InputMode(1);                //以二进制方法验取数据
//  m_CtrlComm.put_RThreshold(1);               //每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件
    m_CtrlComm.put_InputLen(0);                 //设置当前接收区数据长度为0
//  m_ctrlComm.put_PortOpen(TRUE);              //打开串口
    if(!m_CtrlComm.get_PortOpen())
        m_CtrlComm.put_PortOpen(TRUE);
    else
        AfxMessageBox("Can not open serial port!");

    m_CtrlComm.get_Input();


//事件处理-------------------------------
void Ccomm12Dlg::OnCommMscomm1()
{
    // TODO: 在此处添加消息处理程序代码
    VARIANT variant_inp;
    COleSafeArray safearray_inp;
    long len,k;
    BYTE rxdata[2048];
    BYTE bt = NULL;
    if(m_CtrlComm.get_CommEvent() == 2)                 //事件值为2表示接收缓冲区内有字符
    {

        //以下你可以根据自己的通信协议加入处理代码
        UpdateData(TRUE);
        variant_inp = m_CtrlComm.get_Input();           //读缓冲区
        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型变量
        {
            bt = *(char*)(rxdata+k);                    //字符型
            //strtemp_recive_data.Format("%X",bt);      //将字符送入临时变量strtemp存放 
            m_EditRxData+=bt;                           //加入接收编辑框对应字符串 
            strtemp_recive_data+=bt;
        }
        ............
}

注意事项:控件在安装后有些可能需要注册才能正常使用控件。在接收的数据中,因为其接收的数据类型是VARIANT,需要将其转为ColeSafeArray类型->BYTE类型。特别的,在数据需要以十六进制输出去时要用到CByteArray数据类型!这里给出实现代码:

// 去除空格并压缩数据
int Ccomm12Dlg::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;
}

// 将一个字符转换为相应的十六进制
char Ccomm12Dlg::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 ch;
}

Windows API 串口编程

在放弃MScomm串口控件后,使用API串口编程方式。该方式虽然相比MScomm控件函数实现方式比较复杂一点,但其实现功能更加的灵活,功能更加
  • 11
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值