📄 comstatus.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 + -