2023年6月22日发(作者:)
SerialPort.c#include "stdafx.h"#include "SerialPort1.h"#include
//// Constructor//CSerialPort::CSerialPort(){m_hComm = NULL;// initialize overlapped structure members to zerom_ = 0;m_High = 0;// create eventsm_ = NULL;m_hWriteEvent = NULL;m_hShutdownEvent = NULL;m_szWriteBuffer = NULL;m_nWriteSize=1;m_bThreadAlive = FALSE;}//// Delete dynamic memory//CSerialPort::~CSerialPort(){do{SetEvent(m_hShutdownEvent);} while (m_bThreadAlive);TRACE(_T("Thread endedn"));delete [] m_szWriteBuffer;}//// Initialize the port. This can be port 1 to 4.//BOOL CSerialPort::InitPort(CWnd* pPortOwner, // the owner (CWnd) of the port (receives message)UINT portnr, // portnumber (1..4)UINT baud, // baudratechar parity, // parity
UINT databits, // databits
UINT stopbits, // stopbits
DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etcUINT writebuffersize) // size to the writebuffer{assert(portnr > 0 && portnr < 5);assert(pPortOwner != NULL);// if the thread is alive: Killif (m_bThreadAlive){do{SetEvent(m_hShutdownEvent);} while (m_bThreadAlive);TRACE(_T("Thread endedn"));}// create eventsif (m_ != NULL)ResetEvent(m_);m_ = CreateEvent(NULL, TRUE, FALSE, NULL);if (m_hWriteEvent != NULL)ResetEvent(m_hWriteEvent);m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);if (m_hShutdownEvent != NULL)ResetEvent(m_hShutdownEvent);m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);// initialize the event objectsm_hEventArray[0] = m_hShutdownEvent; // highest prioritym_hEventArray[1] = m_;m_hEventArray[2] = m_hWriteEvent;// initialize critical sectionInitializeCriticalSection(&m_csCommunicationSync);// set buffersize for writing and save the ownerm_pOwner = pPortOwner;if (m_szWriteBuffer != NULL)delete [] m_szWriteBuffer;m_szWriteBuffer = new char[writebuffersize];m_nPortNr = portnr;m_nWriteBufferSize = writebuffersize;m_dwCommEvents = dwCommEvents;BOOL bResult = FALSE;char *szPort = new char[50];char *szBaud = new char[50];// now it critical!EnterCriticalSection(&m_csCommunicationSync);// if the port is already opened: close itif (m_hComm != NULL){CloseHandle(m_hComm);m_hComm = NULL;}// prepare port strings//sprintf(szPort, "COM%d", portnr);//sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);// get a handle to the portm_hComm = CreateFile(_T("COM2"),GENERIC_READ |GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0); // template must be 0 for comm devicesif (m_hComm == INVALID_HANDLE_VALUE){// port not founddelete [] szPort;delete [] szBaud;return FALSE;}// set the timeout valuesm_tervalTimeout = 1000;m_talTimeoutMultiplier = 1000;m_talTimeoutConstant = 1000;m_otalTimeoutMultiplier = 1000;m_otalTimeoutConstant = 1000;// configureif (SetCommTimeouts(m_hComm, &m_CommTimeouts)){
if (SetCommMask(m_hComm, dwCommEvents)){if (GetCommState(m_hComm, &m_dcb)){m_r = 'q';m_ntrol = RTS_CONTROL_ENABLE; // set RTS bit high!/*if (BuildCommDCB(szBaud, &m_dcb)){if (SetCommState(m_hComm, &m_dcb)); // continueelseProcessErrorMessage("SetCommState()");}elseProcessErrorMessage("BuildCommDCB()");*/}elseProcessErrorMessage("GetCommState()");}elseProcessErrorMessage("SetCommMask()");}elseProcessErrorMessage("SetCommTimeouts()");delete [] szPort;delete [] szBaud;// flush the portPurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);// release critical sectionLeaveCriticalSection(&m_csCommunicationSync);TRACE(_T("Initialisation for communicationport %d Startmonitor to communicate.n"), portnr);return TRUE;}//// The CommThread Function.//UINT CSerialPort::CommThread(LPVOID pParam){// Cast the void pointer passed to the thread back to// a pointer of CSerialPort classCSerialPort *port = (CSerialPort*)pParam;// Set the status variable in the dialog class to// TRUE to indicate the thread is ->m_bThreadAlive = TRUE;
// Misc. variablesDWORD BytesTransfered = 0;
DWORD Event = 0;DWORD CommEvent = 0;DWORD dwError = 0;COMSTAT comstat;BOOL bResult = TRUE;// Clear comm buffers at startupif (port->m_hComm) // check if the port is openedPurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);// begin forever loop. This loop will run as long as the thread is (;;)
{
// Make a call to WaitCommEvent(). This call will return immediatly// because our port was created as an async port (FILE_FLAG_OVERLAPPED// and an m_OverlappedStructerlapped structure specified). This call will cause the
// m_OverlappedStructerlapped element m_, which is part of the m_hEventArray to
// be placed in a non-signeled state if there are no bytes available to be read,// or to a signeled state if there are bytes available. If this event handle
// is set to the non-signeled state, it will be set to signeled when a
// character arrives at the port.// we do this for each port!bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);if (!bResult)
{
// If WaitCommEvent() returns FALSE, process the last error to determin// the reason..switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
// This is a normal return value if there are no bytes// to read at the port.// Do nothing and continuebreak;}case 87:{// Under Windows NT, this value is returned for some reason.// I have not investigated why, but it is also a valid reply// Also do nothing and ;}default:{// All other error codes indicate a serious error has// occured. Process this ->ProcessErrorMessage("WaitCommEvent()");break;}}}else{// If WaitCommEvent() returns TRUE, check to be sure there are// actually bytes in the buffer to read.
//// If you are reading more than one byte at a time from the buffer
// (which this program does not do) you will have the situation occur
// where the first byte to arrive will cause the WaitForMultipleObjects()
// function to stop waiting. The WaitForMultipleObjects() function
// resets the event handle in m_ to the non-signelead state// as it returns.
//// If in the time between the reset of this event and the call to
// ReadFile() more bytes arrive, the m_ handle will be set again// to the signeled state. When the call to ReadFile() occurs, it will
// read all of the bytes from the buffer, and the program will// loop back around to WaitCommEvent().//
// At this point you will be in the situation where m_ is set,// but there are no bytes available to read. If you proceed and call// ReadFile(), it will return immediatly due to the async port setup, but// GetOverlappedResults() will not return until the next character arrives.//// It is not desirable for the GetOverlappedResults() function to be in
// this state. The thread shutdown event (event 0) and the WriteFile()// event (Event2) will not work if the thread is blocked by GetOverlappedResults().//// The solution to this is to check the buffer with a call to ClearCommError().// This call will reset the event handle, and if there are no bytes to read// we can loop back through WaitCommEvent() again, then proceed.// If there are really bytes to read, do nothing and t = ClearCommError(port->m_hComm, &dwError, &comstat);if (e == 0)continue;} // end if bResult// Main wait function. This function will normally block the thread// until one of nine events occur that require = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);switch (Event){case 0:{// Shutdown event. This is event zero so it will be// the higest priority and be serviced andle(port->m_hComm);port->m_hComm=NULL;port->m_bThreadAlive = FALSE;// Kill this thread. break is not needed, but makes me feel Thread(100);break;}case 1: // read event{GetCommMask(port->m_hComm, &CommEvent);if (CommEvent & EV_RXCHAR)// Receive character event from eChar(port, comstat);if (CommEvent & EV_CTS)::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_CTS_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);if (CommEvent & EV_BREAK)::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_BREAK_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);if (CommEvent & EV_ERR)::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_ERR_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);if (CommEvent & EV_RING)::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RING_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);if (CommEvent & EV_RXFLAG)::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RXFLAG_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);break;}
case 2: // write event{// Write character event from portWriteChar(port);break;}} // end switch} // close forever loopreturn 0;}//// start comm watching//BOOL CSerialPort::StartMonitoring(){if (!(m_Thread = AfxBeginThread(CommThread, this)))return FALSE;TRACE(_T("Thread startedn"));return TRUE;
}//// Restart the comm thread//BOOL CSerialPort::RestartMonitoring(){TRACE(_T("Thread resumedn"));m_Thread->ResumeThread();return TRUE;
}//// Suspend the comm thread//BOOL CSerialPort::StopMonitoring(){TRACE(_T("Thread suspendedn"));m_Thread->SuspendThread();
return TRUE;
}//// If there is a error, give the right message//void CSerialPort::ProcessErrorMessage(char* ErrorText){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%snPort: %dn", (char*)ErrorText, lpMsgBuf, m_nPortNr);
//MessageBox(NULL, Temp, _T("Application Error"), MB_ICONSTOP);LocalFree(lpMsgBuf);delete [] Temp;}//// Write a character.//void CSerialPort::WriteChar(CSerialPort* port){BOOL bWrite = TRUE;BOOL bResult = TRUE;DWORD BytesSent = 0;ResetEvent(port->m_hWriteEvent);// Gain ownership of the critical sectionEnterCriticalSection(&port->m_csCommunicationSync);if (bWrite){// Initailize variablesport->m_ = 0;port->m_High = 0;// Clear bufferPurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);bResult = WriteFile(port->m_hComm, // Handle to COMM Portport->m_szWriteBuffer, // Pointer to message buffer in calling finction// strlen((char*)port->m_szWriteBuffer), // Length of message to sendport->m_nWriteSize, // Length of message to send&BytesSent, // Where to store the number of bytes sent&port->m_ov); // Overlapped structure// deal with any error codesif (!bResult)
{DWORD dwError = GetLastError();switch (dwError){case ERROR_IO_PENDING:{// continue to GetOverlappedResults()BytesSent = 0;bWrite = FALSE;break;}default:{// all other error codesport->ProcessErrorMessage("WriteFile()");}}}
else{LeaveCriticalSection(&port->m_csCommunicationSync);}} // end if(bWrite)if (!bWrite){bWrite = TRUE;bResult = 1;//GetOverlappedResult(port->m_hComm, // Handle to COMM port
// &port->m_ov, // Overlapped structure// &BytesSent, // Stores number of bytes sent// TRUE); // Wait flagLeaveCriticalSection(&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// if (BytesSent != strlen((char*)port->m_szWriteBuffer)){// TRACE("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %dn", BytesSent, strlen((char*)port->m_szWriteBuffer));}// ::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_TXEMPTY_DETECTED, (WPARAM) RXBuff, (LPARAM)port->m_nPortNr);::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_TXEMPTY_DETECTED,0,(LPARAM) port->m_nPortNr);}//// 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;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 t = 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 (e == 0){// break out when all bytes have been readbreak;}EnterCriticalSection(&port->m_csCommunicationSync);if (bRead){bResult = ReadFile(port->m_hComm, // Handle to COMM port
&RXBuff, // RX Buffer Pointer1, // 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 ->ProcessErrorMessage("ReadFile()");break;}
}}else{// ReadFile() returned complete. It is not necessary to call GetOverlappedResults()bRead = TRUE;}} // close if (bRead)if (!bRead){bRead = TRUE;bResult = 1;//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)
{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);} // end forever loop}//// Write a string to the port///*void CSerialPort::WriteToPort(char* string){
assert(m_hComm != 0);memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));strcpy(m_szWriteBuffer, string);m_nWriteSize=strlen(string);// set event for writeSetEvent(m_hWriteEvent);}*/void CSerialPort::WriteToPort(char* string,int n){
assert(m_hComm != 0);memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));// memset(m_szWriteBuffer, 0, n);// strncpy(m_szWriteBuffer, string, n);memcpy(m_szWriteBuffer, string, n);m_nWriteSize=n;// set event for writeSetEvent(m_hWriteEvent);}void CSerialPort::WriteToPort(char * string){
assert(m_hComm != 0);memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));strcpy(m_szWriteBuffer, string);m_nWriteSize=strlen(string);// set event for writeSetEvent(m_hWriteEvent);}void CSerialPort::WriteToPort(LPCTSTR string,int n){
assert(m_hComm != 0);memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));// strncpy(m_szWriteBuffer, string, n);memcpy(m_szWriteBuffer, string, n);m_nWriteSize=n;// set event for writeSetEvent(m_hWriteEvent);}//// 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;}void CSerialPort::ClosePort(){SetEvent(m_hShutdownEvent);}
发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1687428259a9297.html
评论列表(0条)