📄 serialport.cpp
字号:
TRACE("Thread suspended\n");
m_Thread->SuspendThread();
return TRUE;
}
//
// If there is a error, give the right message
//
void CSerialPort::ProcessErrorMessage(char* ErrorText)
{
return ;
char *Temp = new char[200];
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
sprintf(Temp, "WARNING: %s Failed with the following error: \n%s\nPort: %d\n", (char*)ErrorText, lpMsgBuf, m_nPortNr);
MessageBox(NULL, Temp, "Application Error", MB_ICONSTOP);
LocalFree(lpMsgBuf);
delete[] Temp;
}
//
// Write a character.
//
int CSerialPort::WriteCom( BYTE Outbuff[], int size)
{
HANDLE hComm = m_hComm;
DWORD nBytesWrite,endtime,lrc;
static OVERLAPPED ol;
DWORD dwErrorMask,dwError;
COMSTAT comstat;
ol.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
ol.Offset=0;
ol.OffsetHigh=0;
ol.hEvent=NULL; ///标识事件,数据传送完成时,将它设为信号状态
ClearCommError(hComm,&dwErrorMask,&comstat);
if(!WriteFile(hComm,Outbuff,size,&nBytesWrite,&ol))
{
if((lrc=GetLastError())==ERROR_IO_PENDING)
{
endtime=GetTickCount()+1000;
while(!GetOverlappedResult(hComm,&ol,&nBytesWrite,FALSE))
{
dwError=GetLastError();
if(GetTickCount()>endtime)
{
AfxMessageBox("写串口时间过长,目前串口发送缓冲区中的数据数目为空");
break;
}
if(dwError=ERROR_IO_INCOMPLETE)
continue; //未完全读完时的正常返回结果
else
{
// 发生错误,尝试恢复!
ClearCommError(hComm,&dwError,&comstat);
TRACE("发生错误,尝试恢复! %d\n", dwError);
break;
}
}
}
}
FlushFileBuffers(hComm);
PurgeComm(hComm,PURGE_TXCLEAR);
return 1;
}
void CSerialPort::WriteChar(CSerialPort* port)
{
BOOL bWrite = TRUE;
BOOL bResult = TRUE;
DWORD BytesSent = 0;
ResetEvent(port->m_hWriteEvent);
// Gain ownership of the critical section
EnterCriticalSection(&port->m_csCommunicationSync);
if (bWrite)
{
// Initailize variables
port->m_ov.Offset = 0;
port->m_ov.OffsetHigh = 0;
// Clear buffer
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
bResult = WriteFile(port->m_hComm, // Handle to COMM Port
// port->m_szWriteBuffer, // Pointer to message buffer in calling finction
port->WriteBuf,
//strlen((char*)port->m_szWriteBuffer), // Length of message to send
port->WriteBufLen,
&BytesSent, // Where to store the number of bytes sent
&port->m_ov); // Overlapped structure
// deal with any error codes
if (!bResult)
{
DWORD dwError = GetLastError();
switch (dwError)
{
case ERROR_IO_PENDING:
{
// continue to GetOverlappedResults()
BytesSent = 0;
bWrite = FALSE;
break;
}
default:
{
// all other error codes
port->ProcessErrorMessage("WriteFile()");
}
}
}
else
{
LeaveCriticalSection(&port->m_csCommunicationSync);
}
} // end if(bWrite)
if (!bWrite)
{
bWrite = TRUE;
bResult = GetOverlappedResult(port->m_hComm, // Handle to COMM port
&port->m_ov, // Overlapped structure
&BytesSent, // Stores number of bytes sent
TRUE); // Wait flag
LeaveCriticalSection(&port->m_csCommunicationSync);
// deal with the error code
if (!bResult)
{
port->ProcessErrorMessage("GetOverlappedResults() in WriteFile()");
}
} // end if (!bWrite)
// Verify that the data size send equals what we tried to send
//strlen((char*)port->m_szWriteBuffer)
#ifdef _DEBUG
if (BytesSent != port->WriteBufLen)
{
TRACE("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d\n", BytesSent, port->WriteBufLen);//strlen((char*)port->m_szWriteBuffer));
}else{
//TRACE("(%d)WriteFile[%d]:",bWrite,port->WriteBufLen);
for(int i = 0 ; i < (int)port->WriteBufLen;i++){
// TRACE("%c ",port->WriteBuf[i]);
}
//TRACE("\n");
//TRACE("time = %d\n",GetTickCount()-time1);
time1 = GetTickCount();
}
#endif
}
//
// Character received. Inform the owner
//
void CSerialPort::ReceiveChar(CSerialPort* port, COMSTAT comstat)
{
BOOL bRead = TRUE;
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD BytesRead = 0;
unsigned char RXBuff[64];
for (;;)
{
// Gain ownership of the comm port critical section.
// This process guarantees no other part of this program
// is using the port object.
EnterCriticalSection(&port->m_csCommunicationSync);
// ClearCommError() will update the COMSTAT structure and
// clear any other errors.
bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
LeaveCriticalSection(&port->m_csCommunicationSync);
// start forever loop. I use this type of loop because I
// do not know at runtime how many loops this will have to
// run. My solution is to start a forever loop and to
// break out of it when I have processed all of the
// data available. Be careful with this approach and
// be sure your loop will exit.
// My reasons for this are not as clear in this sample
// as it is in my production code, but I have found this
// solutiion to be the most efficient way to do this.
if (comstat.cbInQue == 0)
{
// break out when all bytes have been read
//TRACE("comstat.cbInQue == 0\n");
break;
}
EnterCriticalSection(&port->m_csCommunicationSync);
if (bRead)
{
bResult = ReadFile(port->m_hComm, // Handle to COMM port
RXBuff, // RX Buffer Pointer
64, // Read one byte
&BytesRead, // Stores number of bytes read
&port->m_ov); // pointer to the m_ov structure
// deal with the error code
if (!bResult)
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
// asynchronous i/o is still in progress
// Proceed on to GetOverlappedResults();
bRead = FALSE;
break;
}
default:
{
// Another error has occured. Process this error.
LeaveCriticalSection(&port->m_csCommunicationSync);
port->ProcessErrorMessage("ReadFile()");
TRACE("during reading com data, a error has occured!\n");
return ;
break;
}
}
}
else
{
// ReadFile() returned complete. It is not necessary to call GetOverlappedResults()
bRead = TRUE;
}
} // close if (bRead)
if (!bRead)
{
bRead = TRUE;
bResult = GetOverlappedResult(port->m_hComm, // Handle to COMM port
&port->m_ov, // Overlapped structure
&BytesRead, // Stores number of bytes read
TRUE); // Wait flag
// deal with the error code
if (!bResult)
{
TRACE("getoverlappedresult error\n");
//port->ProcessErrorMessage("GetOverlappedResults() in ReadFile()");
}
} // close if (!bRead)
LeaveCriticalSection(&port->m_csCommunicationSync);
// notify parent that a byte was received
::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_RXCHAR, (WPARAM) RXBuff, (LPARAM) port->m_nPortNr);
port->InputChar((char)RXBuff);
} // end forever loop
}
void CSerialPort::InputChar(char ch)
{
EnterCriticalSection(&m_csRecvBufSync);
if(m_nRecvBuffer < MAX_RECVBUFFER_SIZE-1)
{
m_szRecvBuffer[m_nRecvBuffer] = ch;
m_nRecvBuffer++;
m_szRecvBuffer[m_nRecvBuffer] = 0;
//TRACE("%c", ch);
}
LeaveCriticalSection(&m_csRecvBufSync);
}
int CSerialPort::ReadChars(char *szBuf, int nBuf)
{
EnterCriticalSection(&m_csRecvBufSync);
int nRet = nBuf > m_nRecvBuffer ? m_nRecvBuffer : nBuf;
memcpy( szBuf, m_szRecvBuffer, nRet);
LeaveCriticalSection(&m_csRecvBufSync);
return nRet;
}
int CSerialPort::GetChars(char *szBuf, int nBuf)
{
EnterCriticalSection(&m_csRecvBufSync);
int nRet = nBuf > m_nRecvBuffer ? m_nRecvBuffer : nBuf;
memcpy( szBuf, m_szRecvBuffer, nRet);
int nLost = m_nRecvBuffer - nRet;
if(nLost == 0)
{
ZeroMemory(m_szRecvBuffer, m_nRecvBuffer);
m_nRecvBuffer = 0;
}else
{
memmove( m_szRecvBuffer, m_szRecvBuffer+nRet, nLost);
ZeroMemory(m_szRecvBuffer+nLost, nRet);
m_nRecvBuffer = nLost;
}
LeaveCriticalSection(&m_csRecvBufSync);
return nRet;
}
void CSerialPort::FreeRecvBuf()
{
EnterCriticalSection(&m_csRecvBufSync);
ZeroMemory(m_szRecvBuffer, MAX_RECVBUFFER_SIZE);
m_nRecvBuffer = 0;
LeaveCriticalSection(&m_csRecvBufSync);
}
void CSerialPort::SetAsyn(BOOL bAsyn)
{
m_bAsyn = bAsyn;
}
//
// Write a string to the port
//
void CSerialPort::WriteToPort(BYTE* string,int strlen)
{
if(m_hComm == 0) return ;
//assert(m_hComm != 0);
if(WriteBuf)
delete WriteBuf;
// else
WriteBuf = new BYTE[strlen +1];
memset(WriteBuf,0,strlen+1);
memcpy(WriteBuf,string,strlen);
WriteBufLen = strlen;
/*
memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));
strcpy(m_szWriteBuffer, string);
*/
// set event for write
// if(m_bAsyn) //异步
// SetEvent(m_hWriteEvent);
// else //同步
WriteChar(this);
}
//
// Return the device control block
//
DCB CSerialPort::GetDCB()
{
return m_dcb;
}
//
// Return the communication event masks
//
DWORD CSerialPort::GetCommEvents()
{
return m_dwCommEvents;
}
//
// Return the output buffer size
//
DWORD CSerialPort::GetWriteBufferSize()
{
return m_nWriteBufferSize;
}
BOOL CSerialPort::SetDCBa(DCB &dcb)
{
return SetCommState(m_hComm, &dcb);
}
BOOL CSerialPort::GetDCBa(DCB &dcb)
{
return GetCommState(m_hComm, &dcb);
}
typedef struct tagComContext{
BOOL bLoop;
BOOL bPause;
WORD wSleep;
BYTE bBuf[128];
WORD wLen;
}COMCONTEXT,*LPCOMCONTEXT;
static LPCOMCONTEXT *g_CurComContext;
static BOOL g_ComContinueSend=FALSE;
static BYTE g_sendbuf[128];
static BYTE g_bufsize=0;
static WORD g_sleep = 10;
static BOOL g_pause = FALSE;
UINT CSerialPort::ComContinueSendThread(LPVOID lpVoid)
{
CSerialPort *port = (CSerialPort*)lpVoid;
int i = 0;
// port->SetAsyn(0);
while(g_ComContinueSend && g_bufsize)
{
if(g_pause) continue;
if(i == 0 || i == g_sleep)
{
i = 0;
port->WriteToPort(g_sendbuf,g_bufsize);
}
if(g_sleep) Sleep(1);
if(g_pause) continue;
i++;
}
g_pause = FALSE;
g_bufsize = 0;
return 1;
}
//static int stopcnt = 0;
void CSerialPort::StopSend()
{
if(g_ComContinueSend==FALSE) return;
g_ComContinueSend = FALSE;
while(g_bufsize){
Sleep(1);
}
TRACE("over continue send\n");
memset(g_sendbuf,0,128);
}
void CSerialPort::StopContinueSend(BYTE *buf,int size)
{
TRACE("StopContinueSend\n");
StopSend();
if(size)
WriteToPort(buf,size);
}
void CSerialPort::StartContinueSend(BYTE *buf,int size,int sleep)
{
if(size==0) return;
StopSend();
TRACE("StartContinueSend\n");
memcpy(g_sendbuf,buf,size);
g_bufsize = size;
g_sleep = sleep;
g_ComContinueSend = TRUE;
AfxBeginThread(ComContinueSendThread,this);
}
//用来修改连发过程中数据包的内容;如:速度;
void CSerialPort::ChgConnectBuf(BYTE *buf, int size)
{
if(g_ComContinueSend==FALSE) return;
if(size <= 0) return;
g_pause = TRUE;
memcpy(g_sendbuf,buf,size);
g_bufsize = size;
g_pause = FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -