📄 rs232port.cpp
字号:
timeout.WriteTotalTimeoutConstant = 2000;
timeout.WriteTotalTimeoutMultiplier = 60; // 60ms per char sent
error = SetCommTimeouts(h232Port, &timeout);
if (! error)
{
CString errMsg("Error: Could configure the timeouts.");
RSDataMessage(errMsg);
AfxMessageBox(errMsg, MB_OK|MB_ICONEXCLAMATION);
ClosePort();
return FALSE;
}
RSDataMessage("Timeouts configured (100ms/500ms)\n");
// done
m_lastCharIncommingtime = GetTickCount() + PORT_MAX_IDLETIME*5;
return (TRUE);
} // ConfigurePort
// ----------------------------------- Purge ---------------------------
// remove all characters from the RX buffer (eliminates back-log)
//
BOOL CRS232Port::Purge()
{
BOOL ret;
if (!keepPolling)
return FALSE;
ASSERT(INVALID_HANDLE_VALUE != h232Port);
// interlock
EnterCriticalSection(&critSec);
ret = PurgeComm(h232Port, PURGE_RXCLEAR);
LeaveCriticalSection(&critSec);
return (ret);
} // Purge
// ---------------------------------- ClosePort -------------------------
// PURPOSE:
BOOL CRS232Port::ClosePort()
{
// interlock
EnterCriticalSection(&critSec);
if (INVALID_HANDLE_VALUE != h232Port)
{
// tell dialog that we are closing it (this is so fast anyway)
RSStateChanged(RSPORTCURRENTLY_CLOSING);
RSDataMessage("Closing port\n");
CloseHandle(h232Port);
}
// set HANDLE to closed so we know in future
h232Port = INVALID_HANDLE_VALUE;
LeaveCriticalSection(&critSec);
return (TRUE);
} // ClosePort
// ---------------------------------- Send --------------------------------
// PURPOSE: This one should be clear
//
LONG CRS232Port::Send(int numberOfBytestoWrite,
const BYTE* bufferPtr,
CHAR* debugStrPtr
)
{
BOOL error;
DWORD numberOfBytesWritten=0;
ASSERT (numberOfBytestoWrite>0);
if (!keepPolling)
return FALSE;
// send the bytes out on the wire
if (INVALID_HANDLE_VALUE==h232Port)
{
OutputDebugString("Error: Cannot send. Port closed!\n"); // busy shutting down the app
return FALSE;
}
// flag our intention
RSStateChanged(RSPORTCURRENTLY_WRITTING);
// interlock
EnterCriticalSection(&critSec);
//error = EscapeCommFunction(h232Port, CLRDTR);
// ASSERT(0);
error = WriteFile(h232Port,
bufferPtr,
numberOfBytestoWrite, // nNumberOfBytesToWrite,
&numberOfBytesWritten,
NULL);
// Sleep(50);
// error = EscapeCommFunction(h232Port, SETDTR);
LeaveCriticalSection(&critSec);
// output it in windows debugger
RSDataDebugger(bufferPtr, numberOfBytesWritten, TRUE);
return (TRUE);
} // Send
// ------------------------------ GenDataDebugger ------------------------------
/*static*/
void CRS232Port::GenDataDebugger(const BYTE * buffer, LONG length, int transmit)
{
CString debuggerString;
BYTE *data;
byte hiNib,loNib;
/*
//convert BIN-ary to ASCII for display
data = new BYTE[(length*2)+1];
for (int i = 0; i < length; i++)
{
hiNib = ( *(buffer+i) >>4) & 0x0f;
loNib = ( *(buffer+i) ) & 0x0f;
data[(i*2)] = ( (hiNib < 0x0A) ? ('0' + hiNib) : ('A' + hiNib-10) );
data[(i*2)+1] = ( (loNib < 0x0A) ? ('0' + loNib) : ('A' + loNib-10) );
}
data[(length*2)] = '\0';
*/
//convert BIN-ary to ASCII for display
data = new BYTE[(length*3)+1];
BYTE* pChar = data;
for (int i = 0; i < length; i++)
{
hiNib = ( *(buffer+i) >>4) & 0x0f;
loNib = ( *(buffer+i) ) & 0x0f;
*pChar++ = ( (hiNib < 0x0A) ? ('0' + hiNib) : ('A' + hiNib-10) );
*pChar++ = ( (loNib < 0x0A) ? ('0' + loNib) : ('A' + loNib-10) );
*pChar++ = ' ';
}
--*pChar = '\0';
//data[(length*2)] = '\0';
if (transmit)
{
if (length)
pGlobalDialog->OnCharactersSent();
debuggerString.Format("TX:%s\n", data);
}
else
{
if (length)
pGlobalDialog->OnCharactersReceived();
debuggerString.Format("RX:%s\n", data);
}
// Send to debugger list-box
if (length)
pGlobalDialog->AddCommsDebugString(debuggerString);
#ifdef _COMMS_DEBUGGING
OutputDebugString(debuggerString);
#endif
delete (data);
} // GenDataDebugger
// ---------------------------- UpdateModemStatus -------------------------
void CRS232Port::UpdateModemStatus()
{
DWORD status;
if (!keepPolling)
return;
// get ready to read bytes
if (INVALID_HANDLE_VALUE==h232Port)
{
OutputDebugString("Error: Cannot get modem. Port closed!\n"); // busy shutting down the app
Sleep(0);
return;
}
GetCommModemStatus(h232Port, &status);
RSModemStatus(status);
// display on scope when status changes
if (m_lastModemStatus != status)
{
CString modemDescr;
modemDescr.Format("Modem status : [CTS %c] [DSR %c] [RING %c]",
(status & MS_CTS_ON ? 'X' : '_'),
(status & MS_DSR_ON ? 'X' : '_'),
(status & MS_RING_ON? 'X' : '_')
);
RSDataMessage(modemDescr);
m_lastModemStatus = status;
}
}
// ------------------------------ Recieve ------------------------------------
// return TRUE if a telegram was read.
// return false if no packet was read, this routine will keep trying to build a
// full telegram.
LONG CRS232Port::Recieve(DWORD * numberOfBytesLong, CHAR* bufferPtr, CHAR* debugStrPtr)
{
BOOL error;
DWORD numberOfBytesWritten=0;
DWORD readAheadLength; // # bytes we probably need (depends on what we have in the buffer so far)
DWORD numberOfBytesRead, dwCommError, tickCount;
BYTE * rxBuffPtr;
CString debuggerStr;
RSStateChanged(RSPORTCURRENTLY_READING);
if (!keepPolling)
return FALSE;
// get ready to read bytes
if (INVALID_HANDLE_VALUE==h232Port)
{
OutputDebugString("Error: Cannot RX. Port closed!\n"); // busy shutting down the app
Sleep(0);
return FALSE;
}
// check if port has been idle for too long
tickCount = GetTickCount();
if (((LONG)tickCount - (LONG)m_lastCharIncommingtime) > PORT_MAX_IDLETIME)
{
m_lastCharIncommingtime = tickCount + PORT_MAX_IDLETIME*5;
if (rxBufferIndex)
{
CString msg;
msg = "Port idle, buffer cleared!\n"; // idle
OutputDebugString(msg);
RSDataMessage(msg);
//OnHWError(0);
}
// start recieving from fresh again
rxBufferIndex = 0; // set up our RX buffer
memset(rxBuffer, 0 , sizeof(rxBuffer));
OnHWError(0);
}
rxBuffPtr = &rxBuffer[rxBufferIndex];
*numberOfBytesLong = 0;
// Work out our read-ahead length
//
readAheadLength = SimulationSerialPort::CalculateReadAheadLength(rxBuffer, rxBufferIndex);
ASSERT(rxBufferIndex + readAheadLength < sizeof(rxBuffer));
#ifdef _COMMS_DEBUGGING
//debuggerStr.Format("Read-ahead %d bytes\n", readAheadLength);
//OutputDebugString(debuggerStr);
#endif
// read what-ever is on the port, up to a maximum of readAheadLength.
numberOfBytesRead = 0;
EnterCriticalSection(&critSec);
error = ReadFile(h232Port,
rxBuffPtr,
readAheadLength, // nNumberOfBytesToWrite,
&numberOfBytesRead,
NULL);
LeaveCriticalSection(&critSec);
rxBufferIndex+=numberOfBytesRead;
// display the chars in the debugger
RSDataDebugger(rxBuffPtr, numberOfBytesRead, FALSE);
// keep idle tick count alive since we just got a char(s)
if (numberOfBytesRead)
m_lastCharIncommingtime = GetTickCount();
if (0==error)
{
// clear it
ClearCommError(h232Port, &dwCommError, NULL);
// clear the buffers
rxBufferIndex = 0;
numberOfBytesRead = 0;
OnHWError(dwCommError);
}
// done reading
RSStateChanged(RSPORTCURRENTLY_IDLE);
if (rxBufferIndex)
{
*numberOfBytesLong = numberOfBytesRead;
memcpy(bufferPtr, rxBuffPtr, numberOfBytesRead);
return(TRUE);
}
return (FALSE); // no data avail yet
} // Recieve
// -------------------------------------- Poll ------------------------------
// The main simulator thread loop
//
void CRS232Port::Poll(CHAR * debugStr)
{
DWORD numBytes;
CHAR buffer[MAX_MODBUS_MESSAGELEN];
CHAR debugMsg[80];
BOOL discard;
while (keepPolling) // check to see if we must quit this loop
{
discard = FALSE;
UpdateModemStatus();
if ((! m_masterHasWork) && (Recieve(&numBytes, buffer, debugMsg)) )
{
// test to see if they want this thread to die.
if (!keepPolling)
break;
//CMODMessage msg(buffer, numBytes);
//if (msg.CRCOK())
//{
// build a response etc
OnProcessData(buffer, numBytes, &discard); //
//}
}
else
{
m_masterHasWork = FALSE;
if (! OnProcessData(buffer, 0 , &discard))
Sleep(10); // allow this thread some "space" when it is not doing anything
// only needed at times when the port is not available.
}
if (discard)
rxBufferIndex = 0;
}
OutputDebugString("Poll loop exiting\n");
} // Poll
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -