⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serialport.cpp

📁 串口程序源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		if (bIgnoreBusyPorts) {
			// Only display ports that can be opened for read/write
			HANDLE hCom = CreateFile(rsi.strDevPath,
				GENERIC_READ | GENERIC_WRITE,
				0,    /* comm devices must be opened w/exclusive-access */
				NULL, /* no security attrs */
				OPEN_EXISTING, /* comm devices must use OPEN_EXISTING */
				0,    /* not overlapped I/O */
				NULL  /* hTemplate must be NULL for comm devices */
				);
			if (hCom == INVALID_HANDLE_VALUE) {
				// It can't be opened; remove it.
				asi.RemoveAt(ii);
				ii--;               
				continue;
			}
			else {
				// It can be opened! Close it and add it to the list
				::CloseHandle(hCom);
			}
		}

		// Come up with a name for the device.
		// If there is no friendly name, use the port name.
		if (rsi.strFriendlyName.IsEmpty())
			rsi.strFriendlyName = rsi.strPortName;

		// If there is no description, try to make one up from
		// the friendly name.
		if (rsi.strPortDesc.IsEmpty()) {
			// If the port name is of the form "ACME Port (COM3)"
			// then strip off the " (COM3)"
			rsi.strPortDesc = rsi.strFriendlyName;
			int startdex = rsi.strPortDesc.Find(" (");
			int enddex = rsi.strPortDesc.Find(")");
			if (startdex > 0 && enddex == 
				(rsi.strPortDesc.GetLength()-1))
				rsi.strPortDesc = rsi.strPortDesc.Left(startdex);
		}
	}
}

CString CSCCEnum::EnumSerialPorts()
{
	CString str;
	CArray<SSerInfo,SSerInfo&> asi;
	EnumSerialPorts(asi,FALSE/*include all*/);
	for (int i=0; i<asi.GetSize(); i++) 
		str+=asi[i].strFriendlyName+"\r\n";
	str="本机所有串口:\r\n"+str;
	asi.RemoveAll();
	return str;
}
#endif
//===============================
CSCCArray::CSCCArray()
{

}
CSCCArray::~CSCCArray()
{
//	SaveConfig();
}

int CSCCArray::GetCOMIndex(int nCOMNo)
{
	int nExeist=m_asp.GetSize();
	for(int i=0;i<nExeist;i++)
	{
		if(m_asp.GetAt(i)->m_nCOMNo==nCOMNo )	return i;
	}
	return -1;
}

BOOL CSCCArray::IsCOMOpen(int nCOMNo)
{
	int nCurIndex=GetCOMIndex(nCOMNo) ;
	if(nCurIndex==-1)	return 0; //不存在于列表

	return (m_asp.GetAt(nCurIndex))->IsOpen();
}
BOOL CSCCArray::OpenCOM(CSerialPort *pSP, CWnd *pWnd, int nCOMNo)
{
	if(pSP==NULL)	return 0;
	int nCurIndex=GetCOMIndex(nCOMNo) ;
	if(pSP->Open(pWnd,nCOMNo))
	{
		if(nCurIndex==-1)	m_asp.Add(pSP);
		CSCCTools::RWReg(pSP,0);
		return 1;
	}
	if(nCurIndex!=-1)	m_asp.RemoveAt(nCurIndex);
	return 0;
}

BOOL CSCCArray::OpenCOM(CWnd *pWnd, int nCOMNo)
{
	int nCurIndex=GetCOMIndex(nCOMNo) ;
	if(nCurIndex==-1)	return 0; //不存在于列表

	if((m_asp.GetAt(nCurIndex))->Open(pWnd,nCOMNo))
	{
		CSCCTools::RWReg(m_asp.GetAt(nCurIndex),0);
		return 1;
	}
	m_asp.RemoveAt(nCurIndex);
	return 0;
}
BOOL CSCCArray::CloseCOM(int nCOMNo)
{
	int nCurIndex=GetCOMIndex(nCOMNo) ;
	if(nCurIndex==-1)	return 0; //不存在于列表
	return (m_asp.GetAt(nCurIndex))->Close();
}

CSCCTools::CSCCTools()
{

}
CSCCTools::~CSCCTools()
{

}
BOOL CSCCTools::RWReg(CSerialPort *pSP,BOOL bRead)
{
	CString str;
	char strname[8];
	sprintf(strname,"COM%d",pSP->m_nCOMNo+1);

	if(bRead)
	{
		str = AfxGetApp()->GetProfileString("Settings",strname);
		if(!str.IsEmpty())
		{
			int cRead = _stscanf(str , "%i:%i:%i:%i:%i:%i" , 
						&pSP->m_nBaudRate,&pSP->m_nParityBit,
						&pSP->m_nDataBit ,&pSP->m_nStopBit,
						&pSP->m_nFlowCtrl,&pSP->m_nRTO);
			if(cRead==6) return 1;
		}
	}
	else
	{
		if(pSP->m_bValid)	
		{
			str.Format("%i:%i:%i:%i:%i:%i",
						pSP->m_nBaudRate,pSP->m_nParityBit,
						pSP->m_nDataBit ,pSP->m_nStopBit,
						pSP->m_nFlowCtrl,pSP->m_nRTO);
			AfxGetApp()->WriteProfileString("Settings" ,strname, str);	
		}
	}
	str.Empty();
	return 0;
}

void CSCCTools::OptionCOM(CSerialPort *pSP,int nBautRate,int nParityBit,int nDataBit,int nStopBit,BOOL bIndex)
{
	if(!bIndex)
	{
		pSP->m_nBaudRate=nBautRate;
		pSP->m_nParityBit=nParityBit;
		pSP->m_nDataBit=nDataBit;
		pSP->m_nStopBit=nStopBit;
	}
	else
	{
		pSP->m_nBaudRate=GetParams(nBautRate,0);
		pSP->m_nParityBit=GetParams(nParityBit,1);
		pSP->m_nDataBit=GetParams(nDataBit,2);
		pSP->m_nStopBit=GetParams(nStopBit,3);
	}
}
BOOL CSCCTools::SetupFlowCtrl(CSerialPort *pSP)
{
	if (pSP->m_hFile == NULL)	return FALSE;
	DCB dcb;
	dcb.DCBlength = sizeof(DCB);
	if (!::GetCommState(pSP->m_hFile,&dcb))	return FALSE;
	dcb.fDsrSensitivity = FALSE;
	switch (pSP->m_nFlowCtrl)
	{
	case NO_FC:
		{
		  dcb.fOutxCtsFlow = FALSE;
		  dcb.fOutxDsrFlow = FALSE;
		  dcb.fOutX = FALSE;
		  dcb.fInX = FALSE;
		  break;
		}
	case RTS_CTS_FC:
		{
		  dcb.fOutxCtsFlow = TRUE;
		  dcb.fOutxDsrFlow = FALSE;
		  dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
		  dcb.fOutX = FALSE;
		  dcb.fInX = FALSE;
		  break;
		}
	case DTR_CTS_FC:
		{
		  dcb.fOutxCtsFlow = TRUE;
		  dcb.fOutxDsrFlow = FALSE;
		  dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
		  dcb.fOutX = FALSE;
		  dcb.fInX = FALSE;
		  break;
		}
	case RTS_DSR_FC:
		{
		  dcb.fOutxCtsFlow = FALSE;
		  dcb.fOutxDsrFlow = TRUE;
		  dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
		  dcb.fOutX = FALSE;
		  dcb.fInX = FALSE;
		  break;
		}
	case DTR_DSR_FC:
		{
		  dcb.fOutxCtsFlow = FALSE;
		  dcb.fOutxDsrFlow = TRUE;
		  dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
		  dcb.fOutX = FALSE;
		  dcb.fInX = FALSE;
		  break;
		}
	case XON_XOFF_FC:
		{
		  dcb.fOutxCtsFlow = FALSE;
		  dcb.fOutxDsrFlow = FALSE;
		  dcb.fOutX = TRUE;
		  dcb.fInX = TRUE;
		  dcb.XonChar = ASCII_XON;
		  dcb.XoffChar = ASCII_XOFF;
		  dcb.XoffLim = 100;
		  dcb.XonLim = 100;
		  break;
		}
	default:
		{
		  ASSERT(FALSE);
		  break;
		}
	}

	if (!::SetCommState(pSP->m_hFile,&dcb))	return FALSE;

	return TRUE;
}

int CSCCTools::GetParams(int nIndex, int nParamItem)
{
	if(nParamItem==0)	//波特率
	{
		switch(nIndex) 
		{
			case 0:		return CBR_600;
			case 1:		return CBR_1200;
			case 2:		return CBR_2400;
			case 3:		return CBR_4800;
			case 4:		return CBR_9600;
			case 5:		return CBR_19200;  

			case 6:		return CBR_75; 
			case 7:		return CBR_110;
			case 8:		return CBR_134;
			case 9:		return CBR_150;
			case 10:	return CBR_300;
			case 11:	return CBR_1800; 
			case 12:	return CBR_7200; 
			case 13:	return CBR_12000;
			case 14:	return CBR_14400;
			case 15:	return CBR_28800;
			case 16:	return CBR_33600;
			case 17:	return CBR_38400;
			case 18:	return CBR_56000;
			case 19:	return CBR_57600;
			case 20:	return CBR_115200;
			case 21:	return CBR_128000;
			case 22:	return CBR_256000;

			default:	return CBR_9600;
		}
	}
	else if(nParamItem==1)	//检验位
	{/*NOPARITY,ODDPARITY, EVENPARITY,MARKPARITY,SPACEPARITY*/
		if((nIndex>=1)&&(nIndex<=4))	return nIndex;
		else	return 0;
	}
	else if(nParamItem==2)	//数据位
	{
		if((nIndex>=1)&&(nIndex<=4))	return 8-nIndex;
		else	return 8;
	}
	else if(nParamItem==3)	//停止位
	{/*ONESTOPBIT,ONE5STOPBITS, TWOSTOPBITS*/
		if((nIndex>=1)&&(nIndex<=2))	return nIndex;
		else	return 0;
	}
	return CBR_9600;
}

int CSCCTools::GetParIndex(int nParam, int nParamItem)
{
	if(nParamItem==0)	//波特率
	{
		switch(nParam) 
		{
			case CBR_600	:  	return 0;
			case CBR_1200	:  	return 1;
			case CBR_2400	:  	return 2;
			case CBR_4800	:  	return 3;
			case CBR_9600	:  	return 4;
			case CBR_19200	:  	return 5;
                                                                 
			case CBR_75		:  	return 6;
			case CBR_110	:  	return 7;
			case CBR_134	:   return 8;
			case CBR_150	:   return 9;
			case CBR_300    :	return 10;
			case CBR_1800   :	return 11;
			case CBR_7200   :	return 12;
			case CBR_12000  :	return 13;
			case CBR_14400  :	return 14;
			case CBR_28800  :	return 15;
			case CBR_33600  :	return 16;
			case CBR_38400  :	return 17;
			case CBR_56000  :	return 18;
			case CBR_57600  :	return 19;
			case CBR_115200 :	return 20;
			case CBR_128000 :	return 21;
			case CBR_256000 :	return 22;

			default:	return 4;
		}
	}
	else if(nParamItem==1)	//检验位
	{/*NOPARITY,ODDPARITY, EVENPARITY,MARKPARITY,SPACEPARITY*/
		if((nParam>=ODDPARITY)&&(nParam<=SPACEPARITY))	return nParam;
		else	return 0;
	}
	else if(nParamItem==2)	//数据位
	{
		if((nParam>=4)&&(nParam<=7))	return 8-nParam;
		else	return 0;
	}
	else if(nParamItem==3)	//停止位
	{/*ONESTOPBIT,ONE5STOPBITS, TWOSTOPBITS*/
		if((nParam>=ONE5STOPBITS)&&(nParam<=TWOSTOPBITS))	return nParam;
		else	return 0;
	}
	return 4;
}

CString CSCCTools::GetParStr(int nData, int nItem, BOOL bIndex)
{
	CString str;
	switch(nItem)
	{
	case 0:	//波特率
	case 2:	//数据位
		if(bIndex)	str.Format("%d",GetParams(nData,nItem));
		else		str.Format("%d",nData);
		return str;
	case 1:
		switch(nData)
		{
		case 1:		return "奇校验";
		case 2:		return "偶校验";
		case 3:		return "标志";	
		case 4:		return "空";
		}
		return "无校验";
	case 3:
		switch(nData)
		{
		case ONE5STOPBITS:		return "1.5";
		case TWOSTOPBITS:		return "2";	
		}
		return "1";	
	case 4:
		switch(nData)
		{
		case RTS_CTS_FC:	return "RTS/CTS";
		case XON_XOFF_FC:	return "XON/XOFF";
		case DTR_CTS_FC:	return "DTR/CTS";
		case RTS_DSR_FC:	return "RTS/DSR";	
		case DTR_DSR_FC:	return "DTR/DSR";	
		}
		return "无";	
	}
	return "";
}

DWORD CSerialPort::WriteData(CString str)
{
	int nlength=str.GetLength();
	LPTSTR lpstr=str.GetBuffer(nlength);
	str.ReleaseBuffer();
	return WriteData(lpstr,nlength);
}

CString CSCCTools::HexToStr(BYTE *btData, int nLength)
{
	if((btData==NULL)||(nLength<1))	return "";
	CString strCvt,strOutput;   
	int nl=nLength-1;
	for(int i = 0; i < nl; i++)                           
	{          
		strCvt.Format("%02X ", btData[i]);     
	   	strOutput += strCvt;                                    
	}         
	strCvt.Format("%02X", btData[i]);
	strOutput+=strCvt;
	strCvt.Empty();
	return strOutput;
}

BOOL CSCCTools::IsHexFormat(CString str)
{
	int nStrlength=str.GetLength();
	if(nStrlength<2)	return FALSE;
	for(int i=0;i<nStrlength;i+=3)
	{
		if(((i+1)==nStrlength)||((i+3)==nStrlength))	return FALSE;
		TCHAR chr=' ';
		if((i+2)!=nStrlength)	chr=str.GetAt(i+2);
		if(chr!=' ')	return FALSE;
		for(int j=0;j<2;j++)
		{
			chr=str.GetAt(i+j);
			BOOL bHex=(((chr>='0')&&(chr<='9'))||((chr>='A')&&(chr<='F'))||((chr>='a')&&(chr<='f')));
			if(!bHex)	return FALSE;
		}
	}
	return TRUE;
}

int CSCCTools::StrToHex(CString str, BYTE *btData)
{
	int nLength=str.GetLength();
	if(nLength<2)	return 0;
	for(int i=0;i<nLength;i+=3)	_stscanf(str.Mid(i,2),"%02X",&btData[i/3]);
	return (i+1)/3;
}

void CSCCTools::HexToStr(BYTE *btData, int nLength, CString &strOutput)
{
	if((btData==NULL)||(nLength<1)) return;
	CString strCvt;   
	int nl=nLength-1;
	for(int i = 0; i < nl; i++)                           
	{          
		strCvt.Format("%02X ", btData[i]);     
	   	strOutput += strCvt;                                    
	}         
	strCvt.Format("%02X", btData[i]);
	strOutput+=strCvt;
	strCvt.Empty();
}

BOOL CSCCTools::MakeAscHex(CString str, CString &strNew, BOOL bToAsc)
{
	int nRead=str.GetLength();
	if(nRead==0)	return 0;
	if(bToAsc)
	{		
		if(!IsHexFormat(str))	return 0;
		BYTE btTmp[4096];
		for(int i=0;i<nRead;i+=3)	_stscanf(str.Mid(i,2),"%02X",&btTmp[i/3]);
		strNew=btTmp;
	}
	else
	{
		nRead-=1;
		CString strTmp;
		for(int i=0;i<nRead;i++)
		{
			strTmp.Format("%2X ",(BYTE)str.GetAt(i));
			strNew+=strTmp;
		}
		strTmp.Format("%2X",(BYTE)str.GetAt(nRead));
		strNew+=strTmp;	
		strTmp.Empty();
	}
	return 1;
}

CSerialPort* CSCCArray::GetCOM(int nArrayIndex)
{
	if((nArrayIndex<0)||(nArrayIndex>m_asp.GetSize()))	return NULL;
	return m_asp.GetAt(nArrayIndex);
}

void CSCCArray::SaveConfig()
{
	int nCOMNums=m_asp.GetSize();
	for(int i=0;i<nCOMNums;i++)
	{
		if(m_asp.GetAt(i)->IsOpen())	m_asp.GetAt(i)->Close();
		CSCCTools::RWReg(m_asp.GetAt(i),0);
	}
	m_asp.RemoveAll();
}

CString CSCCTools::GetCOMName(int nCOMIndex)
{
	CString str;
	str.Format("COM%d",nCOMIndex+1);
	return str;
}

BOOL CSCCTools::IsHexFormat(CString str, CString &strError, int &nErrorPos)
{
	int nStrlength=str.GetLength();
	if(nStrlength<2)	
	{
		strError="长度不能小于 1 个字节!";
		nErrorPos=0;
		return 0;
	}
	int i=0;
	BOOL bError=FALSE;
	for(i=0;i<nStrlength;i+=3)
	{
		if((i+1)==nStrlength)
		{
			strError="最后不能为半个字节!";	
			nErrorPos=i+1;
			return 0;
		}
		if((i+3)==nStrlength)
		{
			TCHAR lastchar=str.GetAt(i+2);
			if(isascii(lastchar)==0)	
				strError.Format("最后多出一个非ASCII字符,其16进制为:  %02X H",(BYTE)lastchar);
			else	strError.Format("最后多出一个字符:  \' %c \'",lastchar);
			nErrorPos=i+3;
			return 0;
		}
		TCHAR chr=' ';
		if((i+2)!=nStrlength)	chr=str.GetAt(i+2);
		if(chr!=' ')	
		{
			if(isascii(chr)==0)
				 strError.Format("第 %d 个字节后为非ASCII字符,其16进制为:  %02X H。必须改为  空格",i/3+1,(BYTE)chr);
			else strError.Format("第 %d 个字节后的字符  \' %c \'  必须改为  空格",i/3+1,chr);
			nErrorPos=i+3;
			return 0;
		}
		BOOL bHex=FALSE;
		for(int j=0;j<2;j++)
		{
			chr=str.GetAt(i+j);
			if(chr==' ')	
			{
				if(j==0)	strError.Format("第 %d 个字节的高位不能为  空格,必须是16进制数",i/3+1);
				else		strError.Format("第 %d 个字节的低位不能为  空格,必须是16进制数",i/3+1);
				nErrorPos=i+j+1;
				return 0;
			}
			bHex=(((chr>='0')&&(chr<='9'))||((chr>='A')&&(chr<='F'))||((chr>='a')&&(chr<='f')));
			if(!bHex)
			{
				if(j==0)	
				{
					if(isascii(chr)==0)
						 strError.Format("第 %d 个字节的高位为非ASCII字符,其16进制为:  %02X H。必须是16进制数",i/3+1,(BYTE)chr);
					else strError.Format("第 %d 个字节的高位不能为  \' %c \',必须是16进制数",i/3+1,chr);
				}
				else	
				{
					if(isascii(chr)==0)
						 strError.Format("第 %d 个字节的低位为非ASCII字符,其16进制为:  %2X H。必须是16进制数",i/3+1,(BYTE)chr);
					else strError.Format("第 %d 个字节的低位不能为  \' %c \',必须是16进制数",i/3+1,chr);
				}
				nErrorPos=i+j+1;
				return 0;
			}
		}
	}
	return 1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -