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

    xiaoxiao2021-04-15  64

    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("X", *(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; i<len;) { char 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("X", *(rxdata + k)); buffer += strtemp; } strcard.Format("%sX", strcard, *(rxdata + 3)); strcard.Format("%sX", 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); } }
    转载请注明原文地址: https://ju.6miu.com/read-671289.html

    最新回复(0)