📄 rs232port.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
//
// FILE: RS232Port.cpp : implementation file
//
// See _README.CPP
//
// Implementation of the CRS232Port class.
// Requires MFC headder <afxmt.h>
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "RS232Port.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// ------------------------------ AsyncFriend ------------------------------
// Worker thread function, this is a friend of the CRS232Port class
//
UINT AsyncFriend(LPVOID pParam)
{
CHAR debugStr2[MAX_DEBUG_STR_LEN];
CHAR debugStr[MAX_DEBUG_STR_LEN];
CRS232Port* portPtr;
portPtr = (CRS232Port*)pParam;
try
{
// call the function the thread will run in
if (portPtr->IsKindOf(RUNTIME_CLASS( CRS232Port)))
{
// wait untill the Application is ready for us
CSingleLock lk(&portPtr->m_threadStartupEvent);
lk.Lock(5000); // wait max 5 seconds
portPtr->RSStateChanged(RSPORTCURRENTLY_VOID);
// stays in a loop at this point
portPtr->Poll(debugStr);
}
else
{
sprintf(debugStr2, "CRS232Port AsyncFriend pointer corruption!!!!\n");
OutputDebugString(debugStr2);
}
}
catch (...)
{
CString msg;
msg.Format("INTERNAL APPLICATION ERROR FILE %s LINE: %d\n%s\n%s",
__FILE__, __LINE__, __MY_APPVERSION__, __DATE__);
OutputDebugString(msg);
portPtr->RSDataMessage(msg);
//OutputDebugString( "Catch\n" );
//sprintf(debugStr2, "CRS232Port AsyncFriend Exception !!!!\n");
//OutputDebugString(debugStr2);
}
portPtr->m_listenThreadStatus = RS232_EX_TERMINATED;
{
CString d;
d.Format("[Comms thread %4d Terminating.]\n", GetCurrentThreadId());
OutputDebugString(d);
}
portPtr->m_threadDeadEvent.SetEvent();// CEvent
OutputDebugString("Port object thread returning to System\n");
//AfxEndThread(0);
return(0);
} // AsyncFriend
char commsParityStr[] = "NOEMS"; //NOPARITY ODDPARITY EVENPARITY MARKPARITY SPACEPARITY
char commsStopStr[][4] = {// ONESTOPBIT ONE5STOPBITS TWOSTOPBITS
"1",
"1.5",
"2"
};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC( CRS232Port, CObject);
CRS232Port::CRS232Port()
{
m_debuggerStep = 0;
m_masterHasWork = FALSE;
h232Port = INVALID_HANDLE_VALUE;
m_lastModemStatus = 0xFFFF;
// create the listening thread
m_listenThreadStatus = RS232_EX_PENDING;
m_pWorkerThread = AfxBeginThread((AFX_THREADPROC)AsyncFriend,
this,
THREAD_PRIORITY_TIME_CRITICAL, 0,
CREATE_SUSPENDED
);
rxBufferIndex = 0; // set up our RX buffer
memset(rxBuffer, 0 , sizeof(rxBuffer));
keepPolling = TRUE;
m_lastCharIncommingtime = GetTickCount() + PORT_MAX_IDLETIME*5;
InitializeCriticalSection(&critSec);
}
CRS232Port::~CRS232Port()
{
ClosePort();
// caller must wait for thread to die, if not already dead
OutputDebugString("Port object deleted\n");
TerminateThread(m_pWorkerThread,0);
}
#ifdef _DEBUG
VOID CRS232Port::Dump(CDumpContext& dc) const
{
// call the base class first
CObject::Dump(dc);
// dump our object to the debuggers output
// all important members can be dumped at this stage.
dc << "RS232 Port: " << "\n";
} // Dump
#endif // _DEBUG
// ------------------------- RSStateChanged ----------------------------
void CRS232Port::RSStateChanged(DWORD state)
{
// do nothing in the base class
} // RSStateChanged
/*
// ------------------------- RSDataDebugger ----------------------------
void CRS232Port::RSDataDebugger(const BYTE * buffer, LONG length, BOOL transmit)
{
CString prefix, ASCIIdata;
LONG index, i;
if (transmit)
prefix = "TX:";
else
prefix = "RX:";
index = 0;
while (index < length)
{
i=0;
OutputDebugString("\n");
OutputDebugString(prefix);
while ((index+i < length)&&(i<8))
{
ASCIIdata.Format("%02X", buffer[index+i]);
OutputDebugString(ASCIIdata);
i++;
}
index +=8;
}
} // RSDataDebugger
*/
// --------------------------------- OpenPort ---------------------------
BOOL CRS232Port::OpenPort(LPCTSTR oPortName)
{
CHAR longPortName[MAX_PORT_NAME];
BOOL error;
CString msg;
portNameS = oPortName;
GetLongComPortName(portNameS, longPortName); // get windows port name in long format
// for COM ports >COM9 Windows uses a different naming format, hence this
// little catch and we have to be compatible.
portName = longPortName;
h232Port = CreateFile( portName, // PIP 1823-400-1997
GENERIC_READ | GENERIC_WRITE,
(DWORD)NULL, // exclusive access
NULL, // no security
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL // hTemplate
);
if (INVALID_HANDLE_VALUE ==h232Port)
{
AfxMessageBox("Error: Could not open the RS232 port!", MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
msg.Format("Port %s opened.\n" , longPortName);
// OutputDebugString(msg);
RSDataMessage(msg);
// set up the comms parameters now that we have a handle
error = SetupComm(h232Port,
(DWORD)2048, (DWORD)2048);
msg.Format("Port I/O buffers configured.\n");
//OutputDebugString(msg);
RSDataMessage(msg);
RSStateChanged(RSPORTCURRENTLY_IDLE);
m_lastCharIncommingtime = GetTickCount() + PORT_MAX_IDLETIME*5;
return (TRUE);
} // OpenPort
void CRS232Port::OnHWError(DWORD dwCommError)
{
// do nothing
}
// ----------------------- ReConfigurePort ------------------------------
//
BOOL CRS232Port::ReConfigurePort()
{
return (ConfigurePort(dcb.BaudRate, dcb.ByteSize, dcb.Parity, dcb.fRtsControl, (NOPARITY==dcb.Parity?FALSE:TRUE)));
}
// ---------------------------------- ConfigurePort ---------------------
//
BOOL CRS232Port::ConfigurePort(DWORD baud,
DWORD byteSize,
DWORD parity,
DWORD stopBits,
DWORD rts,
DWORD checkParity)
{
BOOL error;
COMMTIMEOUTS timeout;
if (INVALID_HANDLE_VALUE==h232Port)
{
CString errMsg("Error: Could not set up RS232 port. Port not open!");
RSDataMessage(errMsg);
AfxMessageBox(errMsg, MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
m_lastModemStatus = 0xFFFF;
// Set up the DCB with our settings
// Get it first so we fill all members
error = GetCommState(h232Port,
&dcb);
dcb.BaudRate = baud;
dcb.ByteSize = (BYTE)byteSize;
dcb.Parity = (BYTE)parity;
dcb.fParity = checkParity;
dcb.StopBits = (BYTE)stopBits;
// set the default parameters
dcb.fOutxDsrFlow = FALSE;
// ASSERT(0);
dcb.fDsrSensitivity = FALSE; // SCM22 appears to be DSR sensing = TRUE;//
dcb.fOutxCtsFlow = FALSE; // TRUE;
// set the port for hardware handshaking
dcb.fRtsControl = rts;
dcb.fDtrControl = DTR_CONTROL_ENABLE; //DTR_CONTROL_HANDSHAKE; was DTR_CONTROL_DISABLE;//
dcb.fAbortOnError = TRUE;
dcb.fBinary = TRUE;
dcb.fTXContinueOnXoff = FALSE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.fErrorChar = 0;
dcb.fNull = 0;
dcb.fDummy2 = 0;
// assign it
error = SetCommState(h232Port,
&dcb);
CString paramsSet;
if (!error)
{
CHAR errorMsg[MAX_ERROR_STR_LEN];
CHAR *errorMsgPtr = errorMsg;
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -