MFC单文档之串口通讯实现16进制数据的发送和接收

1、引言

上一节中已经完成了一次设置多个对话框中串口控件的串口flag,那么现在要实现的功能是打开串口后进行收发数据了,而且有多个编辑框,编辑框中数据是整形,中间涉及到进制转换。

2、发送数据

发送一个命令:

void CDLG_CI::OnBnClickedStart()
{
// TODO: 在此添加控件通知处理程序代码
CByteArray senddata;
int data1 = 0xAA, data2 = 0x55, data3 = 0x08, data4 = 0x00, data5 = 0x00, data6 = 0x00, data7 = 0x00, data8 = 0x00, data9 = 0x00, data10 = 0x00,
data11 = 0x00, data12 = 0x00, data13 = 0x00, data14 = 0x00, data15 = 0x00, data16 = 0x00, data17 = 0x00, data18 = 0x00, data19 = 0x00, data20 = 0x00,
data21 = 0x00, data22 = 0x00, data23 = 0x00, data24 = 0x00, data25 = 0x00, data26 = 0x00, data27 = 0x00, data28 = 0x00, data29 = 0x00, data30 = 0x00,
data31 = 0x00, data32 = 0x00, data33 = 0x00, data34 = 0x00, data35 = 0x00,
data36 = data1 + data2 + data3 + data4 + data5 + data6 + data7 + data8 + data9 + data10 + data11 + data12 + data13 + data14 + data15 + data16 + data17 +
data18 + data19 + data20 + data21 + data22 + data23 + data24 + data25 + data26 + data27 + data28 + data29 + data30 + data31 + data32 + data33 + data34 + data35,
data37 = (data36 & 0xff00) >> 8, data38 = (data36 & 0xff);
//将其转化为数值类型
senddata.Add(data1); senddata.Add(data2); senddata.Add(data3); senddata.Add(data4); senddata.Add(data5);
senddata.Add(data6); senddata.Add(data7); senddata.Add(data8); senddata.Add(data9); senddata.Add(data10);
senddata.Add(data11); senddata.Add(data12); senddata.Add(data13); senddata.Add(data14); senddata.Add(data15);
senddata.Add(data16); senddata.Add(data17); senddata.Add(data18); senddata.Add(data19); senddata.Add(data20);
senddata.Add(data21); senddata.Add(data22); senddata.Add(data23); senddata.Add(data24); senddata.Add(data25);
senddata.Add(data26); senddata.Add(data27); senddata.Add(data28); senddata.Add(data29); senddata.Add(data30);
senddata.Add(data31); senddata.Add(data32); senddata.Add(data33); senddata.Add(data34); senddata.Add(data35); senddata.Add(data37); senddata.Add(data38);
m_mscomm_ci.put_Output(COleVariant(senddata));//发送数据
}

发送多个编辑框中数据:

void CDLG_CI::OnBnClickedLoaddata3a()
{
    // TODO:  在此添加控件通知处理程序代码
    //切换插补方式
    m_StateLed159.SetIcon(m_hIconLedRed);
    int flag = MyPublicData.Public_com;
    if (flag)//如果输入的串口编号为正整数,才执行下列命令
    {
        if (m_mscomm_ci.get_PortOpen())
        {
            m_mscomm_ci.put_PortOpen(FALSE);
        }
        m_mscomm_ci.put_CommPort(flag); //选择COM
        m_mscomm_ci.put_InBufferSize(1024); //接收缓冲区
        m_mscomm_ci.put_OutBufferSize(1024);//发送缓冲区
        m_mscomm_ci.put_InputLen(0);//设置当前接收区数据长度为0,表示全部读取
        m_mscomm_ci.put_InputMode(1);//以二进制方式读写数据
        m_mscomm_ci.put_RThreshold(1);//接收缓冲区有1个及1个以上字符时,将引发接收数据的OnComm
        m_mscomm_ci.put_Settings(_T("9600,n,8,1"));//波特率9600无检验位,8个数据位,1个停止位

        if (!m_mscomm_ci.get_PortOpen())//如果串口没有打开则打开
        {
            m_mscomm_ci.put_PortOpen(TRUE);//打开串口
            CByteArray senddata;
            int data1 = 0xAA, data2 = 0x55, data3 = 0x09, data11 = 0x00, data12 = 0x00, data13 = 0x00, data14 = 0x00, data15 = 0x00, data16 = 0x00, data17 = 0x00, data18 = 0x00, data19 = 0x00, data20 = 0x00,
                data21 = 0x00, data22 = 0x00, data23 = 0x00, data24 = 0x00, data25 = 0x00, data26 = 0x00, data27 = 0x00, data28 = 0x00, data29 = 0x00, data30 = 0x00,
                data31 = 0x00, data32 = 0x00, data33 = 0x00, data34 = 0x00, data35 = 0x00;
            CString   str4, str5, str6, str7, str8, str9, str10;
            GetDlgItemText(IDC_COMBO2, str4); GetDlgItemText(IDC_COMBO3, str5); GetDlgItemText(IDC_COMBO4, str6); GetDlgItemText(IDC_EDIT4, str7);
            GetDlgItemText(IDC_EDIT5, str8); GetDlgItemText(IDC_EDIT6, str9); GetDlgItemText(IDC_COMBO5, str10);

            int  data4 = _ttoi(str4), data5 = _ttoi(str5), data6 = _ttoi(str6), data7 = _ttoi(str7), data8 = _ttoi(str8),
                data9 = _ttoi(str9), data10 = _ttoi(str10), //将其转化为数值类型
                data36 = data1 + data2 + data3 + data4 + data5 + data6 + data7 + data8 + data9 + data10 + data11 + data12 + data13 + data14 + data15 + data16 + data17 +
                data18 + data19 + data20 + data21 + data22 + data23 + data24 + data25 + data26 + data27 + data28 + data29 + data30 + data31 + data32 + data33 + data34 + data35,
                data37 = (data36 & 0xff00) >> 8, data38 = (data36 & 0xff);
            //将其转化为数值类型
            senddata.Add(data1); senddata.Add(data2); senddata.Add(data3); senddata.Add(data4); senddata.Add(data5);
            senddata.Add(data6); senddata.Add(data7); senddata.Add(data8); senddata.Add(data9); senddata.Add(data10);
            senddata.Add(data11); senddata.Add(data12); senddata.Add(data13); senddata.Add(data14); senddata.Add(data15);
            senddata.Add(data16); senddata.Add(data17); senddata.Add(data18); senddata.Add(data19); senddata.Add(data20);
            senddata.Add(data21); senddata.Add(data22); senddata.Add(data23); senddata.Add(data24); senddata.Add(data25);
            senddata.Add(data26); senddata.Add(data27); senddata.Add(data28); senddata.Add(data29); senddata.Add(data30);
            senddata.Add(data31); senddata.Add(data32); senddata.Add(data33); senddata.Add(data34); senddata.Add(data35); senddata.Add(data37); senddata.Add(data38);
            m_mscomm_ci.put_Output(COleVariant(senddata));//发送数据
        }
        else
        {
            m_mscomm_ci.put_OutBufferCount(0);
            AfxMessageBox(_T("串口打开失败"));
        }
    }
    else
    {
        AfxMessageBox(_T("请先输入需要打开串口编号"));
    }
}

这里要注意的地方是编辑框中的内容是可以直接获取的,不用添加变量也行,非常方便。

3、接收数据

void CDLG::OnCommMscomm1()
{
    // TODO:  在此处添加消息处理程序代码
    VARIANT variant_inp;
    COleSafeArray safearray_inp;
    long len, k;
    byte rxdata[1024]; //设置 BYTE 数组
    CString strtemp, buffer;
    static unsigned int Receive_flag = 0;
    if (m_mscomm_io.get_CommEvent() == 2) //值为 2 表示接收缓冲区内有字符
    {
        variant_inp = m_mscomm_io.get_Input(); //读缓冲区消息
        safearray_inp = variant_inp; ///变量转换
        len = safearray_inp.GetOneDimSize(); //得到有效的数据长度
        //将数组转换为 CString 型变量
        for (k = 0; k < len; k++) 
        {safearray_inp.GetElement(&k, rxdata + k);
            strtemp.Format("%02X", *(rxdata + k)); buffer += strtemp;}
    }
    buffer.TrimLeft();
    buffer.TrimRight();
    CByteArray receivedata;
    int receivedatalen;
    receivedatalen = Str2Hex(buffer, receivedata);
    int data36 = receivedata[0] + receivedata[1] + receivedata[2] + receivedata[3] + receivedata[4] + receivedata[5] + receivedata[6] + receivedata[7] + receivedata[8] + receivedata[9]
        + receivedata[10] + receivedata[11] + receivedata[12] + receivedata[13] + receivedata[14] + receivedata[15] + receivedata[16] + receivedata[17] + receivedata[18] + receivedata[19]
        + receivedata[20] + receivedata[21] + receivedata[22] + receivedata[23] + receivedata[24] + receivedata[25] + receivedata[26] + receivedata[27] + receivedata[28] + receivedata[29] 
        + receivedata[30] + receivedata[31] + receivedata[32] + receivedata[33] + receivedata[34],
        data37 = (data36 & 0xff00) >> 8, data38 = (data36 & 0xff);

    if((receivedata[35] == data37) && (receivedata[36] == data38))
    {
        if ((detflag == 0) && (receivedata[2]==0x02))
    {
        if (receivedata[3] == 0x00)   { m_StateLed1.SetIcon(m_hIconLedRed), m_StateLed2.SetIcon(m_hIconLedRed); }
        if (receivedata[3] == 0x01)   { m_StateLed1.SetIcon(m_hIconLedRed), m_StateLed2.SetIcon(m_hIconLedGreen); }
        if (receivedata[3] == 0x02)   { m_StateLed1.SetIcon(m_hIconLedGreen), m_StateLed2.SetIcon(m_hIconLedRed); }
        if (receivedata[3] == 0x03)   { m_StateLed1.SetIcon(m_hIconLedGreen), m_StateLed2.SetIcon(m_hIconLedGreen); }

  }
}
    else
    {
        m_mscomm_io.put_PortOpen(0);//关掉串口
        m_StateLed151.SetIcon(m_hIconLedRed);
        AfxMessageBox(_T("通讯数据异常,请检查后重试!"));
    }
}

这里加了一个buffer和strtemp可以实现buffer区域的缓存足够,不然会有buffer too small 的bug。同时用到了两个函数,把收到的数据转成16进制数存储。

//将字符转换十六进制
char CDLG::HexChar(char c)
{
    if ((c >= '0') && (c <= '9'))
        return c - 0x30;
    else if ((c >= 'A') && (c <= 'F'))
        return c - 'A' + 10;
    else if ((c >= 'a') && (c <= 'f'))
        return c - 'a' + 10;
    else
        return -1;
}
//将字符串转换成十六进制
int CDLG::Str2Hex(CString str, CByteArray &senddata)
{
    int hexdata, lowhexdata;
    int hexdatalen = 0;
    int len = str.GetLength();
    senddata.SetSize(len / 2);
    for (int i = 0; ichar lstr, hstr = str[i];
        if (hstr == ' ')
        {
            i++;
            continue;
        }
        i++;
        if (i >= len)
            break;
        lstr = str[i];
        hexdata = HexChar(hstr);    //高位转换
        lowhexdata = HexChar(lstr); //低位转换
        if((hexdata==16)||(lowhexdata==16))
        break;
        else 
        hexdata = hexdata * 16 + lowhexdata;
        i++;
        senddata[hexdatalen] = (char)hexdata;
        hexdatalen++;
    }
    return hexdatalen;
}

函数定义部分:
放在头文件的public部分:

char CDLG::HexChar(char c);
int CDLG::Str2Hex(CString str, CByteArray& senddata);

4、接收卡号部分

这里要把一串数据中的其中两个拼接起来,本来是想着把得到的16进制数组中的元素再转化为字符串的,后来发现这样做倒不如直接在开始就提取出来,因为想要的数据位置知道。
如下:

void CCARDNUM::OnCommMscommCardnum()
{
    // TODO:  在此处添加消息处理程序代码
    VARIANT variant_inp;
    COleSafeArray safearray_inp;
    long len, k;
    byte rxdata[1024]; //设置 BYTE 数组
    CString strtemp, buffer,strcard;
    static unsigned int Receive_flag = 0;
    if (m_mscomm_cardnum.get_CommEvent() == 2) //值为 2 表示接收缓冲区内有字符
    {
        variant_inp = m_mscomm_cardnum.get_Input(); //读缓冲区消息
        safearray_inp = variant_inp; ///变量转换
        len = safearray_inp.GetOneDimSize(); //得到有效的数据长度
        //将数组转换为 CString 型变量
        for (k = 0; k < len; k++)
        {
            safearray_inp.GetElement(&k, rxdata + k);
            strtemp.Format("%02X", *(rxdata + k)); buffer += strtemp;
        }
        strcard.Format("%s%02X", strcard, *(rxdata + 3));
        strcard.Format("%s%02X", strcard, *(rxdata + 4));
    }

    buffer.TrimLeft();
    buffer.TrimRight();
    CByteArray receivedata;
    int receivedatalen;
    receivedatalen = Str2Hex(buffer, receivedata);
    int data36 = receivedata[0] + receivedata[1] + receivedata[2] + receivedata[3] + receivedata[4] + receivedata[5] + receivedata[6] + receivedata[7] + receivedata[8] + receivedata[9]
        + receivedata[10] + receivedata[11] + receivedata[12] + receivedata[13] + receivedata[14] + receivedata[15] + receivedata[16] + receivedata[17] + receivedata[18] + receivedata[19]
        + receivedata[20] + receivedata[21] + receivedata[22] + receivedata[23] + receivedata[24] + receivedata[25] + receivedata[26] + receivedata[27] + receivedata[28] + receivedata[29]
        + receivedata[30] + receivedata[31] + receivedata[32] + receivedata[33] + receivedata[34],
        data37 = (data36 & 0xff00) >> 8, data38 = (data36 & 0xff);

    if ((receivedata[35] == data37) && (receivedata[36] == data38))
    {
        if ((receivedata[2] == 0x01))  
        {
            MyPublicData.Public_card = strcard;
            m_cardnum = strcard;
            SetDlgItemText(IDC_CARDSHOW, m_cardnum);
            AfxMessageBox(_T("已识别卡号!"));
            m_StateLed1.SetIcon(m_hIconLedGreen);
        }
    }
    else
    {
        m_mscomm_cardnum.put_PortOpen(FALSE);
        AfxMessageBox(_T("串口数据有误,请重新加载参数!"));
        m_StateLed1.SetIcon(m_hIconLedRed);
    }

}

你可能感兴趣的:(01MFC/VS2013编程,数据,通讯,文档,mfc,对话框)