打开串口
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]