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

📄 comstatus.cpp

📁 和基恩士对接的串口程序
💻 CPP
字号:
#include "stdafx.h"

#include "ComStatus.h"
#include "string.h"



CComStatus::CComStatus()//构造
{
	m_hCom = NULL;
	
	m_bComId = (char)1;//默认COM1串口

	m_bByteSize=8;
	m_bStopBits=ONESTOPBIT;
	m_bParity=NOPARITY;
	m_dwBaudRate=9600;

	m_bEvtChar=EVENTCHAR;
	m_fBinary=1;

	m_bConnected = FALSE;
	m_bFlowCtrl = FC_XONXOFF ;
	m_fXonXoff = FALSE;
	
}
//--------------------------------------------------------------//--------------
//外部设置参数函数
void CComStatus::Set(BYTE bComId,
					 BYTE bByteSize,
					 BYTE bStopBits,
					 BYTE bParity,		
					 DWORD dwBaudRate,
					 char bEvtChar,
					 DWORD fBinary)
{
	m_hCom = NULL;
	m_bComId = bComId;

	m_bByteSize=bByteSize;
	m_bStopBits=bStopBits;
	m_bParity=bParity;
	m_dwBaudRate=dwBaudRate;

	m_bEvtChar=bEvtChar;
	m_fBinary=fBinary;

	m_bConnected = FALSE;
	m_bFlowCtrl = FC_XONXOFF ;
	m_fXonXoff = FALSE;
}
//---------------------------------------------------------------//---------------
//打开串口函数
BOOL CComStatus::OpenConnection()
{
	char csCom[10];
    COMMTIMEOUTS  CommTimeOuts ;

    if((m_bComId < 0) || (m_bComId > 4))
		return FALSE;//从COM1到COM4
	if(m_hCom)//if already open
		return FALSE;
    //OVERLAPPED包含异步I/O信息
	m_rdos.Offset = 0;
	m_rdos.OffsetHigh = 0;
	m_rdos.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
	if(m_rdos.hEvent == NULL)
		return FALSE;
	m_wtos.Offset = 0;
	m_wtos.OffsetHigh = 0;
	m_wtos.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
	if(m_wtos.hEvent == NULL)
	{
		CloseHandle(m_rdos.hEvent);
		return FALSE;
	}
	
    //打开串口
	wsprintf(csCom,"COM%d",m_bComId);
	m_hCom = CreateFile(csCom,GENERIC_READ | GENERIC_WRITE,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
    NULL
	);

	if(m_hCom == INVALID_HANDLE_VALUE) 
	{
		//dwError = GetLastError();
	    // handle error 
		return FALSE;
	}
	else
	{
      // get any early notifications

      SetCommMask( m_hCom, EV_RXCHAR ) ;

      // setup device buffers

      SetupComm( m_hCom, 4096, 4096 ) ;

      // purge any information in the buffer

      PurgeComm( m_hCom, PURGE_TXABORT | PURGE_RXABORT |
                                      PURGE_TXCLEAR | PURGE_RXCLEAR ) ;

      // set up for overlapped I/O
	  DWORD dwTemp = 1000 / (this->m_dwBaudRate / 8);
      CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ;
      CommTimeOuts.ReadTotalTimeoutMultiplier = 0;//((dwTemp > 0) ? dwTemp : 1);
      CommTimeOuts.ReadTotalTimeoutConstant = 1000 ;
      // CBR_9600 is approximately 1byte/ms. For our purposes, allow
      // double the expected time per character for a fudge factor.
      
      CommTimeOuts.WriteTotalTimeoutMultiplier = 2*CBR_9600/this->m_dwBaudRate;//( npTTYInfo ) ;
      CommTimeOuts.WriteTotalTimeoutConstant = 0;//1000 ;
      SetCommTimeouts( m_hCom, &CommTimeOuts ) ;
	}
	if(!SetupConnection())
	{
		CloseConnection();
		return FALSE;
	}
	EscapeCommFunction( m_hCom, SETDTR );
	m_bConnected = TRUE;
	return TRUE;
}
//----------------------------------------------------------//-----------------------
//关闭串口连接函数
BOOL CComStatus::CloseConnection()
{
   if (NULL == m_hCom)
      return ( TRUE ) ;

   // set connected flag to FALSE

	m_bConnected = FALSE;
   // disable event notification and wait for thread
   // to halt
   //禁止任何消息
   SetCommMask( m_hCom, 0 ) ;

   // block until thread has been halted

   //while(THREADID(npTTYInfo) != 0);

   // kill the focus

   //KillTTYFocus( hWnd ) ;

   // drop DTR
  //  清除 buffer 中所有数据 
   EscapeCommFunction( m_hCom, CLRDTR ) ;

   // purge any outstanding reads/writes and close device handle

   PurgeComm( m_hCom, PURGE_TXABORT | PURGE_RXABORT |
                                   PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
   CloseHandle( m_hCom ) ;
	m_hCom = NULL;

	CloseHandle(m_rdos.hEvent);
	CloseHandle(m_wtos.hEvent);

   return ( TRUE ) ;
}
//-------------------------------------------------------------//----------------
//设置连接参数
BOOL CComStatus::SetupConnection()
{
   BOOL       fRetVal ;
   BYTE       bSet ;
   DCB        dcb ;
	if(m_hCom == NULL)
		return FALSE; 
   dcb.DCBlength = sizeof( DCB ) ;
   //获取串口的当前配置
   GetCommState( m_hCom, &dcb ) ;

   dcb.BaudRate = this->m_dwBaudRate;
   dcb.ByteSize = this->m_bByteSize;
   dcb.Parity =  this->m_bParity;
   dcb.StopBits = this->m_bStopBits ;
	dcb.EvtChar = this->m_bEvtChar ;
   // setup hardware flow control

   bSet = (BYTE) ((m_bFlowCtrl & FC_DTRDSR) != 0) ;
   dcb.fOutxDsrFlow = bSet ;
   if (bSet)
      dcb.fDtrControl = DTR_CONTROL_HANDSHAKE ;
   else
      dcb.fDtrControl = DTR_CONTROL_ENABLE ;

   bSet = (BYTE) ((m_bFlowCtrl & FC_RTSCTS) != 0) ;
	dcb.fOutxCtsFlow = bSet ;
   if (bSet)
      dcb.fRtsControl = RTS_CONTROL_HANDSHAKE ;
   else
      dcb.fRtsControl = RTS_CONTROL_ENABLE ;

   // setup software flow control

   bSet = (BYTE) ((m_bFlowCtrl & FC_XONXOFF) != 0) ;

   dcb.fInX = dcb.fOutX = bSet ;
   dcb.XonChar = ASCII_XON ;
   char xon = ASCII_XON ;
   dcb.XoffChar = ASCII_XOFF ;
    char xoff = ASCII_XOFF ;
    dcb.XonLim = 100 ;
   dcb.XoffLim = 100 ;


   dcb.fBinary = TRUE ;
   dcb.fParity = TRUE ;
   //修改串口的配置
   fRetVal = SetCommState( m_hCom, &dcb ) ;

   return ( fRetVal ) ;

} 
//-----------------------------------------------------//-------------------------
//判断是否处于连接状态
BOOL CComStatus::IsConnected()
{
	return m_bConnected;
}


//  Description:
//     Reads a block from the COM port and stuffs it into
//     the provided buffer.
//
//  Parameters:
//     HWND hWnd
//        handle to TTY window
//
//     LPSTR lpszBlock
//        block used for storage
//
//     int nMaxLength
//        max length of block to read


//将一个字符串作为十六进制串转化为一个字节数组,字节间可用空格分隔,
//返回转换后的字节数组长度,同时字节数组长度自动设置。
int CComStatus::Str2Hex(CString str, char *data)
{
	int t,t1;
	int rlen=0,len=str.GetLength();	
	for(int i=0;i<len;)
	{
		char l,h=str[i];
		if(h==' ')
		{
			i++;
			continue;
		}
		i++;
		if(i>=len)
			break;
		l=str[i];
		t=HexChar(h);
		t1=HexChar(l);
		if((t==16)||(t1==16))
			break;
		else 
			t=t*16+t1;
		i++;
		data[rlen]=(char)t;
		rlen++;
	}
	return rlen;


}

char CComStatus::HexChar(char c)
{
	if((c>='0')&&(c<='9'))
		return c-0x30;
	else if((c>='A')&&(c<='F'))
		return c-'A'+10;
	else if((c>='a')&&(c<='f'))
		return c-'a'+10;
	else 
		return 0x10;

}


/*----------------------------------------------------------
初始化串口参数 
    默认端口		com1 
	波特率			9600
	数据位			8
	就校验          NO
	停止位          1
如果要更改Com口 在Set(串口号)
-----------------------------------------------------------*/
BOOL CComStatus::InitialCom()
{
	
	Set(1);
	if(OpenConnection()==FALSE)
	{
		AfxMessageBox("无法打开该串口!");
		return FALSE;
	
	}
	
	else
	{
		AfxMessageBox("该串口已经被成功打开!");
		return TRUE;
	}
	
	

}





/*------------------------------------------------------
读取激光传感器的值 
outID=1 读取out1的值
outID=2 读取out2的值

-------------------------------------------------------*/
float CComStatus::ReadOutValue(int outID)
{   
	char buffer[1024]={""};    //写缓冲区
	char  reBuffer[1024]={""}; //读缓冲区
    char data[512]={""};       //转换缓冲区
	int length;
	int len;
	int reLen;
	
	float m_fValue=0.0;

	if(outID==1)
		strcat(buffer,"4D310D");
	else if(outID==2)
        strcat(buffer,"4D320D");
	else
	{
		
		AfxMessageBox("所读通道只能是1 或者 2");
		exit(0);
	}
	
	length=strlen(buffer);    
	len=Str2Hex(buffer,data);

	data[0] = 'M';
	data[1] = '0';
	data[2] = 0x0d;
	data[3] = 0;

	if(WriteCommBlock(data,3)==FALSE)
		{
			AfxMessageBox("没有连接串口线!");
			exit(0);
		}	

	if(ReadCommBlock(reBuffer,1024)!=0)
	{   		

		reLen=strlen(reBuffer);
		CString m_strTemp="";
		
		m_fValue+=HexChar(reBuffer[4])*10;
		m_fValue+=HexChar(reBuffer[5])*1;
		m_fValue+=HexChar(reBuffer[7])*0.1;
		m_fValue+=HexChar(reBuffer[8])*0.01;
		m_fValue+=HexChar(reBuffer[9])*0.001;
		m_fValue+=HexChar(reBuffer[10])*0.0001;
	

		if(reBuffer[4]=='F')
		{
			AfxMessageBox("测试物不再范围内");
		    exit(0);
		}
		if(reBuffer[3]==0x2d)		
			m_fValue=-1.0*m_fValue;
		//m_strTemp.Format("%f",m_fValue); 测试用
		//AfxMessageBox(m_strTemp); 
		
		 
	
	}
	return m_fValue;

}

BOOL CComStatus::WriteCommBlock(LPSTR lpByte, DWORD dwBytesToWrite)
{
   BOOL        fWriteStat ;
   DWORD       dwBytesWritten ;
   DWORD       dwErrorFlags;
   DWORD   		dwError;
   DWORD       dwBytesSent=0;
   COMSTAT     ComStat;
   char        szError[ 128 ] ;

   fWriteStat = WriteFile( m_hCom , lpByte, dwBytesToWrite,
                           &dwBytesWritten, &( m_wtos) ) ;

   // Note that normally the code will not execute the following
   // because the driver caches write operations. Small I/O requests
   // (up to several thousand bytes) will normally be accepted
   // immediately and WriteFile will return true even though an
   // overlapped operation was specified

   if (!fWriteStat)
   {
      if(GetLastError() == ERROR_IO_PENDING)
      {
         // We should wait for the completion of the write operation
         // so we know if it worked or not

         // This is only one way to do this. It might be beneficial to
         // place the write operation in a separate thread
         // so that blocking on completion will not negatively
         // affect the responsiveness of the UI

         // If the write takes too long to complete, this
         // function will timeout according to the
         // CommTimeOuts.WriteTotalTimeoutMultiplier variable.
         // This code logs the timeout but does not retry
         // the write.

         while(!GetOverlappedResult( m_hCom,
            &(m_wtos), &dwBytesWritten, TRUE ))
         {
            dwError = GetLastError();
            if(dwError == ERROR_IO_INCOMPLETE)
            {
               // normal result if not finished
               dwBytesSent += dwBytesWritten;
               continue;
            }
            else
            {
               // an error occurred, try to recover
               wsprintf( szError, "<CE-%u>", dwError ) ;
               ClearCommError( m_hCom, &dwErrorFlags, &ComStat ) ;
               break;
            }
         }

         dwBytesSent += dwBytesWritten;

         if( dwBytesSent != dwBytesToWrite )
             wsprintf(szError,"\nProbable Write Timeout: Total of %ld bytes sent", dwBytesSent);
         else
             wsprintf(szError,"\n%ld bytes written", dwBytesSent);

         OutputDebugString(szError);

      }
      else
      {
         // some other error occurred
         ClearCommError( m_hCom, &dwErrorFlags, &ComStat ) ;
         return ( FALSE );
      }
   }
   return ( TRUE ) ;
	

}

int CComStatus::ReadCommBlock(LPSTR lpszBlock, int nMaxLength)
{
   BOOL       fReadStat ;

   COMSTAT    ComStat ;
   DWORD      dwErrorFlags;
   DWORD      dwLength;
   DWORD      dwError;
   char       szError[ 10 ] ;

   // only try to read number of bytes in queue
   ClearCommError( m_hCom, &dwErrorFlags, &ComStat ) ;
   dwLength = min( (DWORD) nMaxLength, ComStat.cbInQue ) ;

   if (dwLength > 0)
   {
      fReadStat = ReadFile( m_hCom, lpszBlock,
		                    dwLength, &dwLength, &(m_rdos) ) ;
      if (!fReadStat)
      {
         if (GetLastError() == ERROR_IO_PENDING)
         {
            OutputDebugString("\n\rIO Pending");
            // We have to wait for read to complete.
            // This function will timeout according to the
            // CommTimeOuts.ReadTotalTimeoutConstant variable
            // Every time it times out, check for port errors
            while(!GetOverlappedResult( m_hCom ,
               &(m_rdos), &dwLength, TRUE ))
            {
               dwError = GetLastError();
               if(dwError == ERROR_IO_INCOMPLETE)
                  // normal result if not finished
                  continue;
               else
               {
                  // an error occurred, try to recover
                  wsprintf( szError, "<CE-%u>", dwError ) ;
                  ClearCommError( m_hCom , &dwErrorFlags, &ComStat ) ;
                  break;
               }

            }

	      }
         else
         {
            // some other error occurred
            dwLength = 0 ;
            ClearCommError( m_hCom , &dwErrorFlags, &ComStat ) ;
         }
      }
   }

   return ( dwLength ) ;

}



/*-----------------------------------------------------------
//设置激光采集零点 
outID=0: 两个都设置为零
outID=1: out1设置为零
outID=2: out2设置为零
-------------------------------------------------------------*/
BOOL CComStatus::AutoZero(int outID)
{
	char buffer[1024]={""};    //写缓冲区	
    char data[512]={""};       //转换缓冲区
	int length;
	int len;
	int reLen;
	
	float m_fValue=0.0;

	if(outID==0)
		strcat(buffer,"56300D");
	else if(outID==1)
        strcat(buffer,"56310D");
	else if(outID==2)
        strcat(buffer,"56320D");
	else
	{
		
		AfxMessageBox("所读通道只能是0,1 或者 2");
		return FALSE;
	}
	length=strlen(buffer);    
	len=Str2Hex(buffer,data);

	if(WriteCommBlock(data,length)==FALSE)
		{
			AfxMessageBox("没有连接串口线!");
			exit(0);
		}	


	return TRUE;

}

⌨️ 快捷键说明

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