//--------------------------------------------------------------------------- #include #pragma hdrstop #include "Com.h" //--------------------------------------------------------------------------- #pragma package(smart_init) //--------------------------------------------------------------------------- __fastcall TCom::TCom() : System::TObject() { InTime = &TTimer(NULL); InTime->Enabled = false; InTime->Interval = 25; InTime->OnTimer = InTimeTimer; } //--------------------------------------------------------------------------- __fastcall TCom::~TCom() { InTime->Free(); //Release the memory used by the read event if (osReader.hEvent) CloseHandle(osReader.hEvent); //Release the COM port if (hCom != INVALID_HANDLE_VALUE) CloseHandle(hCom); } //--------------------------------------------------------------------------- bool __fastcall TCom::OpenCom(unsigned char Port) { COMMTIMEOUTS Tim; AnsiString ComStr; bool Result; if (InTime->Enabled) return(false); ComStr = "\\\\.\\COM" + IntToStr(Port); //asynchronous hCom = CreateFile(ComStr.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if (hCom == INVALID_HANDLE_VALUE) //If failed to open COM port return(false) ; //Else we can use the port, so let's set up communications SetupComm(hCom, 1026, 255); //In buffer = 1026 bytes, out buffer = 255 bytes Tim.ReadIntervalTimeout = 5; Tim.ReadTotalTimeoutConstant = 0; //No read total timeout, we want to get all the data that comes our way Tim.ReadTotalTimeoutMultiplier = 0; Tim.WriteTotalTimeoutConstant = 0; //No write timeout. Tim.WriteTotalTimeoutMultiplier = 0; SetCommTimeouts(hCom, &Tim); GetCommState(hCom, &ComDCB); //Fill ComDCB with current data ComDCB.BaudRate = 9600; ComDCB.ByteSize = 7; ComDCB.Parity = EVENPARITY; ComDCB.StopBits = ONESTOPBIT; SetCommState(hCom, &ComDCB); Result = StartRead(); if (!Result) CloseCom(); return(Result); } //--------------------------------------------------------------------------- void __fastcall TCom::SetBaud(unsigned long Baud) { if (!InTime->Enabled) return; ComDCB.BaudRate = Baud; ComDCB.ByteSize = 7; ComDCB.Parity = EVENPARITY; ComDCB.StopBits = ONESTOPBIT; SetCommState(hCom, &ComDCB); } //--------------------------------------------------------------------------- void __fastcall TCom::CloseCom() { if (!InTime->Enabled) return; InTime->Enabled = false; //Release the COM port CloseHandle(hCom); hCom = INVALID_HANDLE_VALUE; InTime->Enabled = false; } //--------------------------------------------------------------------------- unsigned long __fastcall TCom::WriteCom(AnsiString Data) { AnsiString Buf; unsigned long Result = 0, ILen; if (!InTime->Enabled) return(0); Buf = Data + "\r"; ILen = Buf.Length(); WriteFile(hCom, Buf.c_str(), ILen, &Result, &osWriter); GetOverlappedResult(hCom, &osWriter, &ILen, true); return(Result); } //--------------------------------------------------------------------------- bool __fastcall TCom::StartRead() { static bool FirstRead = true; bool Done = false; InTime->Enabled = false; if (FirstRead) { //Handle creation of the asynchronous structures and read event osWriter.Internal = 0; osWriter.InternalHigh = 0; osWriter.Offset = 0; osWriter.OffsetHigh = 0; osWriter.hEvent = 0; osReader.Internal = 0; osReader.InternalHigh = 0; osReader.Offset = 0; osReader.OffsetHigh = 0; osReader.hEvent = CreateEvent(NULL, True, False, NULL); FirstRead = false; }; do { if (ReadFile(hCom, &InBuf[1], 255, &BytesRead, &osReader)) { //if read completed immediately InBuf[0] = BytesRead; //Note the length of the incoming string InLin = InLin + InBuf; } else if (GetLastError() == ERROR_IO_PENDING) //elseif the problem was that we'll have to wait, good - setup reading Done = true; else return(false) ; } while (!Done); InTime->Enabled = true; return(true); } //--------------------------------------------------------------------------- void __fastcall TCom::InTimeTimer(TObject *Sender) { static bool Parsing = false; unsigned long I; if (!GetOverlappedResult(hCom, &osReader, &BytesRead, false)) { if (Parsing) return; Parsing = true; if (InLin.Length()) { I = InLin.Pos("\r"); while (I) { if (OnReadCom) OnReadCom(InLin.SubString(1, I-1)); InLin = InLin.SubString(I+1, InLin.Length()); I = InLin.Pos("\r"); }; }; Parsing = false; } else { InBuf[0] = BytesRead; //Note the length of the incoming string InLin = InLin + InBuf; StartRead(); }; }