📄 rs232port.cpp
字号:
DWORD ntError = GetLastError();
// call the API using the default system language
errorMsg[0] = '\0';
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL, // ignored, search the system only
ntError, // error code passed in
GetSystemDefaultLangID(),// English ,English US
errorMsg, // message buffer
sizeof(errorMsg), // length
NULL); // optional parameter list
//
while(*errorMsgPtr) // Find any '\r' and replace with ' '
{
errorMsgPtr++;
if (( *errorMsgPtr == '\r') | ( *errorMsgPtr == '\n'))
*errorMsgPtr = ' ';
}
paramsSet.Format("Error configuring port for %d,%d,%c,%s : (error %d) - %s",
baud,
byteSize,
commsParityStr[parity],
commsStopStr[stopBits],
ntError,
errorMsg);
RSDataMessage(paramsSet);
AfxMessageBox( paramsSet, MB_OK | MB_ICONEXCLAMATION);
ClosePort();
return FALSE;
}
else
{
paramsSet.Format("Port configured %d,%d,%c,%s", baud,
byteSize,
commsParityStr[parity],
commsStopStr[stopBits]);
RSDataMessage(paramsSet);
}
// Set up the timeouts to use, they are quite short, since we will loop anyway.
// Do not make them zero, else we will have a CPU load problem. Too large a value,
// and we have to wait for comms to time out when shutting down
// fill timeout structure
GetCommTimeouts(h232Port, &timeout);
timeout.ReadIntervalTimeout = 100; // 500ms between incomming chars.
timeout.ReadTotalTimeoutConstant = 500;
timeout.ReadTotalTimeoutMultiplier = 0; // #chars to read does not add to timeout amount
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\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 = WriteFile(h232Port,
bufferPtr,
numberOfBytestoWrite, // nNumberOfBytesToWrite,
&numberOfBytesWritten,
NULL);
LeaveCriticalSection(&critSec);
// output it in windows debugger
RSDataDebugger(bufferPtr, numberOfBytesWritten, TRUE);
return (TRUE);
} // Send
// ------------------------------ 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;
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 + -