MFC實現串口助手

界面如圖所示
打開串口

void CMXC1730Dlg::OnBnClickedButton1()//打開串口
{
	// TODO: 在此添加控件通知處理程序代碼
	CString temp;
	m_OpenCloseCtrl.GetWindowText(temp);
	UpdateData(true);
	if (temp == _T("關閉串口"))
	{
		KillTimer(0);
		u2clas.ClosePort();
		m_OpenCloseCtrl.SetWindowText(_T("打開串口"));

		m_PortNum.EnableWindow(TRUE);
		m_Baud.EnableWindow(TRUE);
		m_DataBit.EnableWindow(TRUE);
		m_Parity.EnableWindow(TRUE);
		m_StopData.EnableWindow(TRUE);
		UpdateData(false);
	}
	else
	{
		if (m_PortNum.GetCount())//有端口號
		{
			int SelPortNO, SelBaudRate, SelDataBits, SelStopBits;
			char SelParity;

			temp = m_strPortNO;
			temp.Delete(0, 3);
			SelPortNO = _ttoi(temp);

			SelBaudRate = _ttoi(m_strBaudRate);
			SelDataBits = _ttoi(m_strDataBits);
			SelParity = m_strParity.GetAt(0);
			SelStopBits = _ttoi(m_strStopBits);
			if (SelStopBits == 1)
			{
				SelStopBits = SelStopBits - 1;
			}
			if (u2clas.InitPort(this->GetSafeHwnd(), SelPortNO, SelBaudRate, SelParity, SelDataBits, SelStopBits, EV_RXFLAG | EV_RXCHAR | EV_CTS | EV_DSR | EV_TXEMPTY, 512/*寫緩衝區大小*/))
			{
				u2clas.StartMonitoring();
				m_OpenCloseCtrl.SetWindowText(_T("關閉串口"));
				m_PortNum.EnableWindow(FALSE);
				m_Baud.EnableWindow(FALSE);
				m_DataBit.EnableWindow(FALSE);
				m_Parity.EnableWindow(FALSE);
				m_StopData.EnableWindow(FALSE);
				UpdateData(false);
			}
			else
				AfxMessageBox(TEXT("該串口已經被其他應用程序所佔用!\n請選擇其它的串口"));
		}
	}
}

界面獲取的字符串轉十六進制發送

void CMXC1730Dlg::ChangeCharstr2Hexstr(CString Charstr)
{
	CString Hexstr = _T("");
	memset(Hexstr1, 0, sizeof(BYTE) * 7);
	Charstr.MakeUpper();//改爲大寫
	HexStringFilter(Charstr);//十六進制字符串過濾(即字母不能大於F)
	int Length = Charstr.GetLength();//得到字符串的長度:幾個字節
	if (Length % 2)//奇數個字節的話就省去最後一個字節
	{
		Charstr.Delete(Length - 1);
	}
	Length = Charstr.GetLength();
	for (int i = 0; i < Length / 2; i++)
	{
		Hexstr1[i] = (unsigned char)CombineHexChar(Charstr.GetAt(i * 2), Charstr.GetAt(i * 2 + 1));
	}
}

void CMXC1730Dlg::HexStringFilter(CString & str)
{
	BOOL bOK;
	for (int i = 0; i < str.GetLength()/*得到字符串的長度:幾個字節*/;)
	{
		bOK = ((str.GetAt(i) >= '0') && (str.GetAt(i) <= '9')) ||
			((str.GetAt(i) >= 'A') && (str.GetAt(i) <= 'F')) ||
			((str.GetAt(i) >= 'a') && (str.GetAt(i) <= 'f'));
		if (!bOK)
		{
			str.Delete(i);
		}
		else
		{
			i++;
		}
	}
}

char CMXC1730Dlg::CombineHexChar(char CharH, char CharL)
{
	char result;
	char temp;
	if (CharH >= '0'&&CharH <= '9')
		result = (CharH - '0');
	else if
		(CharH >= 'a'&&CharH <= 'f')		result = (CharH - 'a' + 10);
	else if
		(CharH >= 'A'&&CharH <= 'F')		result = (CharH - 'A' + 10);
	else
		result = 0;

	if (CharL >= '0'&&CharL <= '9')
		temp = (CharL - '0');
	else if (CharL >= 'a'&&CharL <= 'f')
		temp = (CharL - 'a' + 10);
	else if (CharL >= 'A'&&CharL <= 'F')
		temp = (CharL - 'A' + 10);
	else
		temp = 0;

	result = result * 16 + temp;
	return result;
}

發送事件

void CMXC1730Dlg::OnBnClickedButton2()//發送事件
{
	// TODO: 在此添加控件通知處理程序代碼
	CString temp;
	m_OpenCloseCtrl.GetWindowText(temp);
	UpdateData(true);
	if (temp == _T("打開串口"))
	{
		MessageBoxW(TEXT("請打開串口"));
	}
	else
	{
		temp = m_strSend;//"發送"顯示編輯框
		ChangeCharstr2Hexstr(temp);//十六進制發送
		if (sizeof(*Hexstr1))//發送編輯框有內容
		{
			u2clas.WriteToPort(Hexstr1, 7);
			UpdateData(false);
		}
	}
}

接收數據

//接收數據
/*接收數據時通過相應固定的消息來實現的,也就是只要有數據,串口類就會發送消息給窗口,窗口進行數據解析顯示;
本例以接收32字節的數據位例子,校驗和不算字頭;
第一包數據不足32字節或者沒有找到字節時,這包數據不會丟棄,會和下一報數據拼接在一起,直到找到第一個字頭位置;
*/
LRESULT CMXC1730Dlg::OnReceiveData(WPARAM wParam, LPARAM commInfo)
{
	CString strLog, strline;
	struct serialPortInfo
	{
		UINT portNr;//串口號
		DWORD bytesRead;//讀取的字節數
	}*pCommInfo;
	pCommInfo = (serialPortInfo*)commInfo;

	nData = pCommInfo->bytesRead;//讀取的字節數
	strline.Format(TEXT(" %d-:%d"), nData, __LINE__);
	strLog = strline + TEXT(" ");

	BYTE *pByte = (BYTE *)wParam;//接收到的數據

	CByteArray tempary;//保存完整的幀數據
	tempary.RemoveAll();

	CByteArray datary;//存放此次接收到的數據
	datary.RemoveAll();

	for (int i = 0; i < nData; i++)
	{
		datary.Add(pByte[i]);//將接受的原始數據轉換成【字節型】保存到動態數組
	}

	int total_len = 0;
	if (m_ary.GetSize() > 0)//解析完數據後還有數據
	{
		//進入此條件表明【不是第一組數據】出現過不完整幀後,遺留數據
		total_len = m_ary.GetSize() + datary.GetSize();
		tempary.SetSize(total_len);
		memcpy(tempary.GetData(), m_ary.GetData(), m_ary.GetCount());
		memcpy(tempary.GetData() + m_ary.GetSize()/*數組大小*/, datary.GetData(), datary.GetSize());
		m_ary.RemoveAll();
	}
	else
	{
		//進入此條件表明【是第一組數據】
		tempary.Append(datary);
		datary.RemoveAll();
	}
	AnalysisData(tempary, m_ary/*NULL*/);
	return TRUE;
}

void CMXC1730Dlg::AnalysisData(CByteArray & im_pcks, CByteArray & om_pcks)
{
	int nCount = 0;
	rxLen = 0;//有效長度
	int nStart = 0;
	bool flag_rev = false;
	int pcklen = im_pcks.GetCount();//完整幀數據字節數
		for (int i = 0; i < pcklen; i++)
	{
		switch (nCount)
		{
		case 0:
			if (0xdd == im_pcks.GetAt(i))//返回指定下標處的數組元素的值 
			{
				nCount++;
				nStart = i;
			}
			else
			{
				nCount = 0;
			}
			break;
		default:
			nCount++;
			break;
		}
		if (nCount > 31)
		{
			//按位異或 兩個二進制位相同,則結果爲0,不同爲1
			BYTE datasum = 0;
			for (int i = 0; i < 28; i++)//取校驗和
			{
				datasum += im_pcks.GetAt(nStart + i + 3);
			}
			datasum = datasum & 0xff;
			if (datasum == im_pcks.GetAt(nStart + 31))//判斷校驗和
			{
				rxLen = nCount;
				nCount = 0;
				flag_rev = true;
				Uartpck(im_pcks, rxLen, nStart);//im_pcks接收到的數據,rxLen422數組元素個數,nStart是存0xAA這個值的下標
			}
			else
			{
				nCount = 0;
				flag_rev = false;
			}
		}
	}
	if (!flag_rev)
	{
		unsigned char *p = (unsigned char*)(im_pcks.GetData()/* + rxLen422 +1*/);
		om_pcks.SetSize(im_pcks.GetSize()/* - rxLen422 - 1*/);
		memcpy(om_pcks.GetData(), p, (im_pcks.GetSize()/* - rxLen422 - 1*/));
	}

	//Uartpck(im_pcks, pcklen, 0);
}

bool CMXC1730Dlg::Uartpck(CByteArray & szData, int ilen, int iStart)
{
	unsigned char *ptempdata = new unsigned char[ilen]();//存儲十六進制發送的數據
	CString im_pckss = _T("");
	CString szTemp = _T("");

	for (int i = 0; i < ilen; i++)
	{
		ptempdata[i] = szData.GetAt(i + iStart);
		szTemp.Format(TEXT("%02x "), szData.GetAt(i + iStart));
		im_pckss = im_pckss + szTemp;
	}
	m_strReceive = im_pckss;//接收有效數據
	UpdateData(FALSE);
	return TRUE;
}

本例子在VS2010上編寫,MFC靜態庫編譯生成,用到了網上開源的SerialPort串口類,我在項目中都是這樣用的,比較穩定。有問題請聯繫我:[email protected]
源代碼鏈接:https://download.csdn.net/download/weixin_44533976/12104963

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章