커뮤니티>자료실
   
   
 
    Thread를 이용한 Rs232 데이터 읽고 쓰기   2013.01.26
    Thread를 이용한 Rs232 데이터 읽고 쓰기
   
 
//---------------------------------------------------------------------------
//Basic file event handling thread
class TFileThread : public TThread
{
private:
//Internal routine that will update screen with error message
void __fastcall ShowError(void);
protected:
//Handles for the communications file and an event
HANDLE hFileEvent, hCommDevice;
//Overlap structure for overlapped i/o
OVERLAPPED oOverlap;
//Holding area for the last error message
AnsiString ErrorMess;
//Buffer for communications data
unsigned char Buffer[BUFSIZE];
//Actual error routine
void __fastcall Error(String ErrMess);
public:
//Override constructor, destructor and terminate method
virtual __fastcall TFileThread(HANDLE CommFile);
virtual __fastcall ~TFileThread(void);
void __fastcall Terminate(void);
};
//---------------------------------------------------------------------------
//Thread to manage writing data to comm file
class TFileWriteThread : public TFileThread
{
private:
//Holding area for string to write
unsigned char WriteBuffer[BUFSIZE];
//Critical section used to protect the write string
CRITICAL_SECTION CriticalSection;
unsigned short int usiNrBytes;
//Override TThread main loop
void __fastcall Execute(void);
public:
//Override constructor and destructor
__fastcall TFileWriteThread(HANDLE CommFile);
__fastcall ~TFileWriteThread(void);
//Called by main thread to write data to communications device
void __fastcall WriteData(unsigned char *p, unsigned short int usiNr);
};
//---------------------------------------------------------------------------
//Object to manage reading from comm file
class TFileReadThread : public TFileThread
{
private:
DWORD BytesRead;
//Override TThread main loop
void __fastcall Execute(void);
//Routine to update main window display
void __fastcall UpdateWindow(void);
public:
//Override constructor
__fastcall TFileReadThread(HANDLE);
};
// ---------------------------------------------------------------------------
// TFileThread
// Basic functionality for file reading and file writing threads
// Constructor
__fastcall TFileThread::TFileThread(HANDLE CommFile) : TThread(True)
{
// Initialize an event object
// Initialize an event object
hFileEvent = CreateEvent(NULL, // no security attribute
FALSE, // Auto-reset event
FALSE, // initial state unsignaled
NULL); // Unnamed
// Assign the communications file handle
hCommDevice = CommFile;
// Assign the auto-reset event to the event field of the structure
// used by overlapped i/o calls
oOverlap.hEvent = hFileEvent;
// Initialize the error message
ErrorMess = "";
}
// --------------------------------------------------------------------------
// Destructor
__fastcall TFileThread::~TFileThread(void) {
// Close the event object
CloseHandle(hFileEvent);
}
// --------------------------------------------------------------------------
// Error routine to call
void __fastcall TFileThread::Error(String ErrMess) {
// Set the current error message
ErrorMess = ErrMess;
// Call ShowError in the context of the main thread
Synchronize(ShowError);
// Clear the error message
ErrorMess = "";
}
// --------------------------------------------------------------------------
// Internal error routine
// Must always be called with synchronize
void __fastcall TFileThread::ShowError(void) {
Application->NormalizeTopMosts();
Application->MessageBox(L"ErrorMess.c_str()", L"Errer State", MB_OK);
Application->RestoreTopMosts();
// ShowMessage(ErrorMess.c_str());
}
// --------------------------------------------------------------------------
// Tell the thread to terminate
void __fastcall TFileThread::Terminate(void) {
// Call the parent's terminate event to set the termination flag
TThread::Terminate();
// Raise the file event so that the thread will actually terminate
// see the execute method of TFileWriteThread and TFileReadThread
// for more info
SetEvent(hFileEvent);
}
// -----------------------------------------------------------------------------
// TFileWriteThread
// Manage writing the communications file
// Constructor
__fastcall TFileWriteThread::TFileWriteThread(HANDLE hCommFile)
: TFileThread(hCommFile) {
// Create the critical section
InitializeCriticalSection(&CriticalSection);
usiNrBytes = 0;
memset((unsigned char *)WriteBuffer, 0, sizeof(WriteBuffer));
// Start execution of the thread which was started in the suspended state
Resume();
}
// Destructor
__fastcall TFileWriteThread::~TFileWriteThread(void) {
// Free the memory associated with the critical section
DeleteCriticalSection(&CriticalSection);
}
// --------------------------------------------------------------------------
// Store user input and wake up the thread to process the input
void __fastcall TFileWriteThread::WriteData(unsigned char *p,
unsigned short int usiNr) {
// Start the critical section
EnterCriticalSection(&CriticalSection);
// Set the data to be written
memcpy(WriteBuffer, p, usiNr);
// for(unsigned short int i = 0; i < usiNr; i++) WriteBuffer[i] = p[i];
usiNrBytes = usiNr; // End the critical section
LeaveCriticalSection(&CriticalSection);
// Raise the event so that the waiting data can be written
SetEvent(hFileEvent);
}
// --------------------------------------------------------------------------
void __fastcall TFileWriteThread::Execute(void) {
DWORD BytesWritten;
unsigned short int bufsize;
int ErrCode;
while (!Terminated) {
if (usiNrBytes) {
// if (usiNrBytes > BUFSIZE) throw TCommError(TCommError::WRITE_OVERFLOW);
memset((unsigned char *)Buffer, 0, sizeof(Buffer));
// initialise write buffer
EnterCriticalSection(&CriticalSection);
memcpy(Buffer, WriteBuffer, usiNrBytes);
// for(unsigned short int i = 0; i < usiNrBytes; i++) Buffer[i] = WriteBuffer[i];
memset((unsigned char *)WriteBuffer, 0, sizeof(WriteBuffer));
// clear data
bufsize = usiNrBytes;
usiNrBytes = 0;
LeaveCriticalSection(&CriticalSection);
// Start a pending write operation
if (!WriteFile(hCommDevice, Buffer, bufsize, &BytesWritten,
&oOverlap)) {
// if error occured get error code
if ((ErrCode = GetLastError()) != ERROR_IO_PENDING) {
Error("Error on write file " + IntToStr(ErrCode));
}
}
}
// wait for io to finish (1) or user to enter data (2) or thread to be terminated (3)
// (1) & (3) will raise the event
// (2) event raised by writedata method
WaitForSingleObjectEx(hFileEvent, INFINITE, TRUE);
}
}
// --------------------------------------------------------------------------
// TFileReadThread
// Handle reading the communications file
__fastcall TFileReadThread::TFileReadThread(HANDLE hCommFile)
: TFileThread(hCommFile) {
// mySerialPort = theSerialPort;
hFileEvent = CreateEvent(NULL, false, false, NULL);
oOverlap.hEvent = hFileEvent;
// Start the thread which was born in the suspended state
Resume();
}
// --------------------------------------------------------------------------
void __fastcall TFileReadThread::UpdateWindow(void) {
// DWORD l=BytesRead;
//
// Hva28Form->RxDNumber=BytesRead;
// memcpy(Hva28Form->ReadBuff,Buffer,BytesRead);
// Hva28Form->bReceiveOk=true;
if (BytesRead) {
Hva28Form->Shape1->Brush->Color = clGreen;
}
for (DWORD i = 0; i < BytesRead; i++) {
Hva28Form->ReadBuff[Hva28Form->iBufferRear] = Buffer[i];
Hva28Form->iBufferRear++;
if (Hva28Form->iBufferRear >= RD_BUFSIZE) {
Hva28Form->iBufferRear = 0;
}
}
}
// --------------------------------------------------------------------------
void __fastcall TFileReadThread::Execute(void) {
DWORD ErrCode;
DWORD NrBytesAvail, dummy;
COMSTAT comstat;
while (1) // Thread will destroy itself
{
if (ClearCommError(hCommDevice, &dummy, &comstat)) {
// if (comstat.cbInQue > BUFSIZE) NrBytesAvail = BUFSIZE;
// else NrBytesAvail = comstat.cbInQue;
NrBytesAvail = comstat.cbInQue;
if (NrBytesAvail) {
memset((unsigned char *)Buffer, 0, sizeof(Buffer));
if (ReadFile(hCommDevice, Buffer, NrBytesAvail, &BytesRead,
&oOverlap)) {
if (!Terminated) {
if (BytesRead)
Synchronize(UpdateWindow);
else
Sleep(100);
};
}
else { // Read Error
if ((ErrCode = GetLastError()) != ERROR_IO_PENDING)
// Report the error
Error("Error on read file " + SysErrorMessage
(ErrCode));
}
}
}
Sleep(10);
// Proggie seems to use up a HUGe amount of CPU time without this
}
ClearCommError(hCommDevice, &dummy, &comstat);
/*
//While the thread is not terminated
while (!Terminated)
{
//Initialize the buffer
strnset(Buffer, '\0', sizeof(Buffer));
//Start a pending read operation
if (!ReadFile(hCommDevice, Buffer, BUFSIZE, &BytesRead, &oOverlap))
{
//If an error occured get the error code
//If the error code is not ERROR_IO_PENDING
if ((ErrCode = GetLastError()) != ERROR_IO_PENDING)
//Report the error
Error("Error on read file " + SysErrorMessage(ErrCode));
else
{
// GetQueuedCompletionStatus(hCommDevice,&ReadByte,&CompleteKey,&oOverlap,20);
//Wait for the IO to complete or for the thread to terminate
WaitForSingleObjectEx(hFileEvent, INFINITE, TRUE);
//If there is some data in the buffer
if (strlen(Buffer))
{
// GetOverlappedResult(hCommDevice,&oOverlap,&ReadByte,true);
//Write it to the output window
Synchronize(UpdateWindow);
}
}
}
}
*/
}
// ---------------------------------------------------------------------------
// Start the dumb terminal
void __fastcall THva28Form::ConnectTerminal(int port, int baud, int size,
int pari, int stop, int Rdper) {
DCB dcb;
COMMTIMEOUTS ct;
// If the terminal is already running return
if (TerminalConnected)
return;
TerminalConnected = false;
WCHAR MyPort[20];
// sprintf(MyPort,"COM%d",1+port);
if (port >= 10) {
wsprintf(MyPort, L"\\\\.\\COM%d\0", port);
}
else {
wsprintf(MyPort, L"COM%d\0", port);
}
hCommDevice = CreateFile(MyPort, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
//// hCommDevice=CreateFile(MyPort.c_str(),GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
//// hCommDevice=CreateFile((const wchar_t *)MyPort,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
// hCommDevice=CreateFile(L"COM4\0",GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
// If this is not a valid file handle
if (hCommDevice == INVALID_HANDLE_VALUE) {
// Report the error and return
// mMessage->Lines->Add("Error on open " + IntToStr(GetLastError()));
return;
}
// Get the config of the modem connection
GetCommState(hCommDevice, &dcb);
// Set to 8 bits, no parity, 1 stopbit
dcb.BaudRate = baud;
dcb.ByteSize = size;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.fOutxCtsFlow = FALSE; // CTS output flow control
dcb.fOutxDsrFlow = FALSE; // DSR output flow control
dcb.fDtrControl = DTR_CONTROL_DISABLE; // DTR flow control type
dcb.fDsrSensitivity = FALSE;
dcb.fRtsControl = RTS_CONTROL_DISABLE; // RTS flow control
dcb.fInX = TRUE;
dcb.fOutX = TRUE;
dcb.fTXContinueOnXoff = FALSE;
dcb.fNull = FALSE;
// dcb.XonLim = 100;
// dcb.XoffLim = 100;
dcb.fAbortOnError = FALSE;
// Actually set the config
SetCommState(hCommDevice, &dcb);
// Get timeout information for the communications channel
GetCommTimeouts(hCommDevice, &ct);
// Set the timeout to 10 msec so that a pending read
// will complete when more that 1 second has elapsed between the arrival
// of two consecutive characters
ct.ReadIntervalTimeout = Rdper;
ct.ReadTotalTimeoutConstant = Rdper;
ct.ReadTotalTimeoutMultiplier = Rdper * 10;
ct.WriteTotalTimeoutConstant = Rdper;
ct.WriteTotalTimeoutMultiplier = Rdper * 10;
// Set the new timeout value
SetCommTimeouts(hCommDevice, &ct);
// Start the threads that actually read and write the communications file
FileWriteThread = new TFileWriteThread(hCommDevice);
FileReadThread = new TFileReadThread(hCommDevice);
// Terminal status is connected
TerminalConnected = true;
}
// --------------------------------------------------------------------------
// Stop the dump terminal
void __fastcall THva28Form::ShutdownTerminal(void) {
// If the terminal is connected
if (TerminalConnected) {
// Shutdown the writing thread if it exists
if (FileWriteThread)
FileWriteThread->Terminate();
// Shutdown the reading thread if it exists
if (FileReadThread)
FileReadThread->Terminate();
// Close the communications channel
CloseHandle(hCommDevice);
}
// The terminal is now disconnected
TerminalConnected = false;
}

 
 
   
 
주소: 인천광역시 서구 봉수대로 141 가좌시범공단 B동 505호    대표자 : 김시석    전화번호 : 032)672-2966    팩스번호 : 032)672-2965
사업자등록 번호 : 225-14-00080    콘트롤러개발,전자제품개발 아테크