打開串口
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