上一节中已经完成了一次设置多个对话框中串口控件的串口flag,那么现在要实现的功能是打开串口后进行收发数据了,而且有多个编辑框,编辑框中数据是整形,中间涉及到进制转换。
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("请先输入需要打开串口编号"));
}
}
这里要注意的地方是编辑框中的内容是可以直接获取的,不用添加变量也行,非常方便。
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);
这里要把一串数据中的其中两个拼接起来,本来是想着把得到的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);
}
}