📄 serialport.cpp
字号:
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 + -