📄 rs232.cpp
字号:
#include "stdafx.h"
#include "RS232.h"
C_RS232 ::
C_RS232(BYTE* DeviceCount, char* Namen, COMM_SIGNAL OnSignal, COMM_ERROR OnError)
{
//unter Win NT w鋜en theoretisch 255 Com-Ports m鰃lich
//testen welche existieren und/oder noch frei sind
char* Testname = new char[MAX_PATH];
memset(&m_Handles.name[0],0x00,MAX_PATH);
memset(&m_dcb,0x00,sizeof(DCB));
*DeviceCount = 0;
m_Signal = OnSignal;
m_CommError = OnError;
m_Handles.hHandle = 0;
m_SignalEvents = 0;
m_ThreadEvent = 0;
m_Timeout = 0;
m_Read = 0;
m_Write = 0;
m_EventThread = 0;
m_FlowControl = 0;
for (int i = 1; i < 256; i++)
{
memset(&Testname[0],0x00,MAX_PATH);
sprintf(&Testname[0],"Com%d",i);
m_Handles.hHandle = CreateHandle(Testname, true, 0);
if (Enabled(m_Handles.hHandle))
{
strcat(Namen,"[");
strcat(Namen,Testname);
strcat(Namen,"];");
DestroyHandle(&m_Handles.hHandle);
*DeviceCount += 1;
};
};
sprintf(Namen,"%s (%d freie Schnittstellen)",Namen,*DeviceCount);
delete Testname;
}
C_RS232 ::
~C_RS232()
{
if (Enabled(m_Handles.hHandle))
DestroyHandle(&m_Handles.hHandle);
}
void C_RS232 ::
ReturnLastErrorMsg(unsigned long Code, char* Msg)
{
char sMsg[MAX_PATH];
memset(&sMsg[0],0x00,MAX_PATH);
memset(&Msg[0],0x00,MAX_PATH);
if (!FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
Code,
LANG_NEUTRAL, // Default language
sMsg,
MAX_PATH-1,
NULL
))
strcpy(Msg,"FormatMessage failed.");
else
strncpy(Msg,sMsg,strlen(sMsg)-2);
}
/***************************************************************************************************/
//Dataconrol-Block
/***************************************************************************************************/
DCB C_RS232 ::
GetDataControlBlock(HANDLE hHandle)
{
if (Enabled(hHandle))
{
memset(&m_dcb,OFF,sizeof(m_dcb));
GetCommState(hHandle, &m_dcb);
};
return m_dcb;
}
BOOL C_RS232 ::
UpdateDataControlBlock(HANDLE hHandle, BYTE Baud, BYTE Size, BYTE StpBits, BYTE Parity)
{
if (Enabled(hHandle))
{
GetCommState(hHandle, &m_dcb);
m_dcb.BaudRate = (1 << Baud)*300;
m_dcb.ByteSize = Size+4;
m_dcb.StopBits = StpBits;
m_dcb.Parity = Parity;
m_dcb.DCBlength = sizeof(m_dcb);
switch(m_FlowControl)
{
case NONE: m_dcb.fBinary = ON; //Clear all flags
break;
case CTS:
{
m_dcb.fOutxCtsFlow = ON;
m_dcb.fRtsControl = ON;
break;
};
case DTR:
{
m_dcb.fOutxDsrFlow = ON;
m_dcb.fDtrControl = ON;
break;
};
case SWR:
{
m_dcb.fOutX = ON;
m_dcb.fInX = ON;
break;
};
default: m_dcb.fBinary = ON;
};
if (!SetCommState(hHandle, &m_dcb))
{
if (Assigned(m_CommError))
m_CommError(hHandle,GetLastError(),DCBERRORSTRING);
return FALSE;
}
else
return TRUE;
};
m_CommError(hHandle,GetLastError(),INVALIDHANDLESTRING);
return FALSE;
}
/***************************************************************************************************/
//Ereignisse anzeigen (J/N)
/***************************************************************************************************/
DWORD WINAPI OnComEvent(LPVOID pParam)
{
DWORD WaitableEvents = EV_BREAK|EV_CTS|EV_DSR|EV_ERR|EV_RING|EV_RLSD|EV_RXCHAR|EV_RXFLAG|EV_TXEMPTY;
COMMTIMEOUTS lpCommTimeouts;
OVERLAPPED Overlapped = {0};
BOOL IsSignaled = FALSE;
C_RS232* seriell = (C_RS232*)pParam;
memset(&lpCommTimeouts,seriell->m_Timeout,sizeof(COMMTIMEOUTS));
//alle hineinmaskieren und default timeout verwenden
if ((!SetCommMask(seriell->m_Handles.hHandle, WaitableEvents))
|| (!SetCommTimeouts(seriell->m_Handles.hHandle,&lpCommTimeouts)))
goto ShowFailure;
memset(&Overlapped, OFF, sizeof(Overlapped));
seriell->m_ThreadEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
Overlapped.hEvent = seriell->m_ThreadEvent;
while (seriell->m_SignalEvents)
{
IsSignaled = WaitCommEvent(seriell->m_Handles.hHandle, &WaitableEvents, &Overlapped);
if (ERROR_IO_PENDING == GetLastError())
IsSignaled = (WAIT_TIMEOUT != WaitForSingleObject(seriell->m_ThreadEvent,seriell->m_Timeout));
if (IsSignaled)
seriell->DoOnSignal(WaitableEvents);
else
{
if (NULL != seriell->m_CommError)
seriell->m_CommError(seriell->m_Handles.hHandle,ERROR_COUNTER_TIMEOUT,THREADTIMEOUT);
WaitableEvents = EV_BREAK|EV_CTS|EV_DSR|EV_ERR|EV_RING|EV_RLSD|EV_RXCHAR|EV_RXFLAG|EV_TXEMPTY;
SetCommMask(seriell->m_Handles.hHandle, WaitableEvents);
ResetEvent(seriell->m_ThreadEvent);
};
};
ShowFailure:;
SetCommMask(seriell->m_Handles.hHandle, 0);
PurgeComm(seriell->m_Handles.hHandle, PURGEALL);
CloseHandle(seriell->m_ThreadEvent);
seriell->m_ThreadEvent = 0;
if (NULL != seriell->m_CommError)
seriell->m_CommError(seriell->m_Handles.hHandle,GetLastError(),THREADDONE);
return 0;
}
/***************************************************************************************************/
//Create..Destroy Handle
/***************************************************************************************************/
HANDLE C_RS232 ::
CreateHandle(char* Name, BOOL testmode, DWORD Timeout)
{
m_Timeout = Timeout;
if ((Enabled(m_Handles.hHandle))
&&(!testmode))
{
if (Assigned(m_CommError))
m_CommError(m_Handles.hHandle,0,ALREADYOPENEDSTRING);
return m_Handles.hHandle;
};
if (0 == strlen(Name))
{
if (Assigned(m_CommError))
m_CommError(m_Handles.hHandle,0,INVALIDNAME);
return m_Handles.hHandle;
};
strcpy(m_Handles.name,Name);
m_Handles.hHandle = CreateFile( m_Handles.name,
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (( (!Enabled(m_Handles.hHandle))
|| (GetFileType(m_Handles.hHandle) != FILE_TYPE_CHAR))
&& (!testmode))
{
DestroyHandle(&m_Handles.hHandle);
if (Assigned(m_CommError))
m_CommError(m_Handles.hHandle,GetLastError(),OPENERRORSTRING);
return m_Handles.hHandle;
};
DWORD Dummy;
m_SignalEvents = ( (Enabled(m_Handles.hHandle))
&& (Assigned(m_Signal))
&& (!testmode));
if (m_SignalEvents)
m_EventThread = CreateThread(NULL,0,OnComEvent,this,THREAD_PRIORITY_NORMAL,&Dummy);
return m_Handles.hHandle;
}
BOOL C_RS232 ::
DestroyHandle(HANDLE* hHandle)
{
BOOL ret = true;
if( (Enabled(m_EventThread))
&&(*hHandle == m_Handles.hHandle))
{
m_SignalEvents = 0;
ret = TerminateOnSignal();
Sleep(10);
};
CloseHandle(*hHandle);
*hHandle = INVALID_HANDLE_VALUE;
return ret;
}
void C_RS232 ::
DoOnSignal(DWORD hEvent)
{
COMSTAT ComStat;
DWORD Errors;
BOOL hasEvent = FALSE;
ClearCommError(m_Handles.hHandle, &Errors, &ComStat);
//Behandeln des Ereignisses
if (hEvent&EV_BREAK)
{/*NOP*/ hasEvent = TRUE;};
if (hEvent&EV_CTS)
{/*NOP*/ hasEvent = TRUE;};
if (hEvent&EV_DSR)
{/*NOP*/ hasEvent = TRUE;};
if (hEvent&EV_RING)
{/*NOP*/ hasEvent = TRUE;};
if (hEvent&EV_RLSD)
{/*NOP*/ hasEvent = TRUE;};
if (hEvent&EV_TXEMPTY)
{/*NOP*/ hasEvent = TRUE;};
if (hEvent&EV_RXCHAR)
{/*NOP*/ hasEvent = (0 < ComStat.cbInQue);};
if (hEvent&EV_RXFLAG)
{/*NOP*/ hasEvent = (0 < ComStat.cbInQue);};
if (Assigned(m_Signal)&&(hasEvent))
m_Signal(m_Handles.hHandle,Errors,ComStat.cbInQue,hEvent);
}
BOOL C_RS232 ::
TerminateOnSignal()
{
BYTE Dummy = 0;
if(Enabled(m_EventThread))
{
SetEvent(m_ThreadEvent);
DWORD ExitCode = STILL_ACTIVE;
while (STILL_ACTIVE == ExitCode)
{
TerminateThread(m_EventThread,0);
GetExitCodeThread(m_EventThread,&ExitCode);
if ((Dummy++) >= 0xfe) break;
};
CloseHandle(m_EventThread);
m_EventThread = 0;
};
return (Dummy < 0xfe);
}
BOOL C_RS232 ::
DisableOnSignal()
{
BYTE Dummy = 0;
if(Enabled(m_EventThread))
{
m_SignalEvents = false;
SetEvent(m_ThreadEvent);
while (!(0 >= SuspendThread(m_EventThread)))
{/* NOP */ if ((Dummy++) >= 0xfe) break;};
};
return (Dummy < 0xfe);
}
BOOL C_RS232 ::
EnableOnSignal()
{
DWORD Dummy = 0;
if(Enabled(m_EventThread))
{
m_SignalEvents = true;
while (!(0 >= ResumeThread(m_EventThread)))
{/* NOP */ if ((Dummy++) >= 0xfe) break;};
}
else
{
m_EventThread = CreateThread(NULL,0,OnComEvent,this,THREAD_PRIORITY_NORMAL,&Dummy);
return (Enabled(m_EventThread));
};
return (Dummy < 0xfe);
}
/***************************************************************************************************/
//I/O-Buffer bearbeiten
/***************************************************************************************************/
BOOL C_RS232 ::
Purge(BYTE Kind, HANDLE hHandle)
{
if (Enabled(hHandle))
{
switch(Kind)
{
case INBUF: PurgeComm(hHandle, PURGEREAD);
break;
case OUTBUF: PurgeComm(hHandle, PURGEWRITE);
break;
case ALL: PurgeComm(hHandle, PURGEALL);
break;
default:
{
if (Assigned(m_CommError))
{
char Msg[MAX_PATH] = {0};
strcpy(Msg,INVALIDCHOISE);
sprintf(Msg,"%s [valids are %d; %d; %d]",INVALIDCHOISE,INBUF,OUTBUF,ALL);
m_CommError(m_Handles.hHandle,0,Msg);
return false;
};
};
};
return true;
};
return false;
}
/***************************************************************************************************/
int C_RS232 ::
GetInOutQueCount(BYTE Que, HANDLE hHandle)
{
if (Enabled(hHandle))
{
COMSTAT ComStat;
DWORD Errors;
if (!ClearCommError(hHandle, &Errors, &ComStat))
{
if (Assigned(m_CommError))
m_CommError(m_Handles.hHandle,GetLastError(),FUNCTIONFAILED);
return -1;
}
switch(Que)
{
case INBUF: return ComStat.cbInQue;
break;
case OUTBUF: return ComStat.cbOutQue;
break;
default:
{
if (Assigned(m_CommError))
{
char Msg[MAX_PATH] = {0};
strcpy(Msg,INVALIDCHOISE);
sprintf(Msg,"%s [valids are %d; %d]",INVALIDCHOISE,INBUF,OUTBUF);
m_CommError(m_Handles.hHandle,0,Msg);
return -1;
};
};
};
};
return -1;
}
DWORD C_RS232 ::
GetModemState(HANDLE hHandle)
{
DWORD Flag = 0;
DWORD State = 0x10;
if (Enabled(hHandle))
{
if (GetCommModemStatus(hHandle, &Flag))
{
if (Assigned(m_CommError))
{
for (BYTE i = 0; i < 4; i++)
{
char Msg[MAX_PATH];
if (Flag&State)
{
sprintf(Msg,"%s",tagCSTATESTR[i]);
m_CommError(m_Handles.hHandle,0,Msg);
};
State *= 2;
};
};
};
COMSTAT stat;
DWORD Errors;
if ((ClearCommError(hHandle, &Errors, &stat))&&(Assigned(m_CommError)))
{
if(stat.fCtsHold)
m_CommError(m_Handles.hHandle,0,"Tx waiting for CTS signal ");
if(stat.fDsrHold)
m_CommError(m_Handles.hHandle,0,"Tx waiting for DSR signal ");
if(stat.fRlsdHold)
m_CommError(m_Handles.hHandle,0,"Tx waiting for RLSD signal ");
if(stat.fXoffHold)
m_CommError(m_Handles.hHandle,0,"Tx waiting, XOFF char received ");
if(stat.fXoffSent)
m_CommError(m_Handles.hHandle,0,"Tx waiting, XOFF char sent ");
};
return Flag;
};
return false;
}
BOOL WaitFor(EVENT event, DWORD TimeOut)
{
switch(WaitForSingleObject(event,TimeOut))
{
case WAIT_ABANDONED: return false; // The specified object is a mutex object that was not released by the thread that owned the mutex object before the owning thread terminated. Ownership of the mutex object is granted to the calling thread, and the mutex is set to nonsignaled.
break;
case WAIT_OBJECT_0: return true; // The state of the specified object is signaled.
break;
case WAIT_TIMEOUT: return false; // The time-out interval elapsed, and the object's state is nonsignaled.
default :return false;
};
}
BOOL C_RS232 ::
ComWrite(void* Buffer, DWORD BufferSize)
{
OVERLAPPED Overlapped;
DWORD BytesWritten;
if (!Enabled(m_Write))
m_Write = CreateEvent(NULL,FALSE,FALSE,NULL);
memset(&Overlapped, OFF, sizeof(Overlapped));
Overlapped.hEvent = m_Write;
if (!WriteFile( m_Handles.hHandle,
Buffer,
BufferSize,
&BytesWritten,
&Overlapped))
{
switch(GetLastError())
{
case ERROR_IO_PENDING:
{
GetOverlappedResult(m_Handles.hHandle,
&Overlapped,
&BytesWritten,
!(WaitFor(Overlapped.hEvent,m_Timeout))
);
break;
};
default: return (BufferSize == BytesWritten);
};
}
else
{
GetOverlappedResult( m_Handles.hHandle,
&Overlapped,
&BytesWritten,
!(WaitFor(Overlapped.hEvent,m_Timeout))
);
};
return (BufferSize == BytesWritten);
}
DWORD C_RS232 ::
ComRead(void* Buffer, DWORD* BufferSize)
{
OVERLAPPED Overlapped;
DWORD BytesRead;
if (!Enabled(m_Read))
m_Read = CreateEvent(NULL,FALSE,FALSE,NULL);
memset(&Overlapped, OFF, sizeof(Overlapped));
Overlapped.hEvent = m_Read;
if (!ReadFile( m_Handles.hHandle,
Buffer,
*BufferSize,
&BytesRead,
&Overlapped))
{
switch(GetLastError())
{
case ERROR_IO_PENDING:
{
GetOverlappedResult(m_Handles.hHandle,
&Overlapped,
&BytesRead,
!(WaitFor(Overlapped.hEvent,m_Timeout))
);
return (BytesRead);
};
default: return (BytesRead);
};
}
else
{
GetOverlappedResult( m_Handles.hHandle,
&Overlapped,
&BytesRead,
!(WaitFor(Overlapped.hEvent,m_Timeout))
);
};
return (BytesRead);
}
BOOL C_RS232 ::
Assigned(void* Pointer)
{
return (NULL != Pointer);
}
BOOL C_RS232 ::
Enabled(HANDLE hHandle)
{
return ((0!=hHandle)&&(INVALID_HANDLE_VALUE!=hHandle));
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -