CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2

Threaded View

  1. #1
    Join Date
    Aug 2009
    Posts
    7

    Compiling problem: Read serial data

    Hi,

    Learnt some basic C++ about 4 years ago, so pretty new here. Thanks for your patience.

    I just got 2 sets of codes from code project. It is supposed to read stuff off a serial port. (they will be at the end of the post). I have tried compiling by adding both the files into my project. but it just cannot compile because it says "Serial.h : no such file or directory, even if I have placed it there.

    Anyways,

    what I would want my program to do is to wait for a string coming in from the serial port,
    once it detects a certain string, it will save some bytes into a variable...

    so for example, I have some data

    ABCDE 123,456,789,
    DEFGH 99A,86H,I73
    QWERT 124,987,566

    coming in through the port,
    I want to to acquire the data "99A,86H,I73", which is from the second line, which occurs after DEFGH

    Read:
    if DetectString("DEFGH")
    Variable = Read_The_Next_9_Bytes;
    go to Read

    I have tried googling and searching around, I just keep getting programmes that either lacks some library, or couldn't compile for some reason.

    Appreciate your help! Otherwise, thanks for reading to the end anyway

    Joel

    website for the files:
    http://www.codeproject.com/KB/system/serial.aspx

    Codes
    // Listener.cpp - Sample application for CSerial
    //
    // Copyright (C) 1999-2003 Ramon de Klein ([email protected])
    //
    // This program is free software; you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation; either version 2 of the License, or
    // (at your option) any later version.
    //
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    // GNU General Public License for more details.
    //
    // You should have received a copy of the GNU General Public License
    // along with this program; if not, write to the Free Software
    // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    #define STRICT
    #include <tchar.h>
    #include <windows.h>
    #include <stdio.h>
    #include <string.h>

    #include "Serial.h"

    enum { EOF_Char = 27 };

    int ShowError (LONG lError, LPCTSTR lptszMessage)
    {
    // Generate a message text
    TCHAR tszMessage[256];
    wsprintf(tszMessage,_T("%s\n(error code %d)"), lptszMessage, lError);

    // Display message-box and return with an error-code
    ::MessageBox(0,tszMessage,_T("Listener"), MB_ICONSTOP|MB_OK);
    return 1;
    }

    int __cdecl _tmain (int /*argc*/, char** /*argv*/)
    {
    CSerial serial;
    LONG lLastError = ERROR_SUCCESS;

    // Attempt to open the serial port (COM1)
    lLastError = serial.Open(_T("COM1"),0,0,false);
    if (lLastError != ERROR_SUCCESS)
    return ::ShowError(serial.GetLastError(), _T("Unable to open COM-port"));

    // Setup the serial port (4800,8N1, which is the default setting)
    lLastError = serial.Setup(CSerial::EBaud4800,CSerial::EData8,CSerial::EParNone,CSerial::EStop1);
    if (lLastError != ERROR_SUCCESS)
    return ::ShowError(serial.GetLastError(), _T("Unable to set COM-port setting"));

    // Register only for the receive event
    lLastError = serial.SetMask(CSerial::EEventBreak |
    CSerial::EEventCTS |
    CSerial::EEventDSR |
    CSerial::EEventError |
    CSerial::EEventRing |
    CSerial::EEventRLSD |
    CSerial::EEventRecv);
    if (lLastError != ERROR_SUCCESS)
    return ::ShowError(serial.GetLastError(), _T("Unable to set COM-port event mask"));

    // Use 'non-blocking' reads, because we don't know how many bytes
    // will be received. This is normally the most convenient mode
    // (and also the default mode for reading data).
    lLastError = serial.SetupReadTimeouts(CSerial::EReadTimeoutNonblocking);
    if (lLastError != ERROR_SUCCESS)
    return ::ShowError(serial.GetLastError(), _T("Unable to set COM-port read timeout."));

    // Keep reading data, until an EOF (CTRL-Z) has been received
    bool fContinue = true;
    do
    {
    // Wait for an event
    lLastError = serial.WaitEvent();
    if (lLastError != ERROR_SUCCESS)
    return ::ShowError(serial.GetLastError(), _T("Unable to wait for a COM-port event."));

    // Save event
    const CSerial::EEvent eEvent = serial.GetEventType();

    // Handle break event
    if (eEvent & CSerial::EEventBreak)
    {
    printf("\n### BREAK received ###\n");
    }

    // Handle CTS event
    if (eEvent & CSerial::EEventCTS)
    {
    printf("\n### Clear to send %s ###\n", serial.GetCTS()?"on":"off");
    }

    // Handle DSR event
    if (eEvent & CSerial::EEventDSR)
    {
    printf("\n### Data set ready %s ###\n", serial.GetDSR()?"on":"off");
    }

    // Handle error event
    if (eEvent & CSerial::EEventError)
    {
    printf("\n### ERROR: ");
    switch (serial.GetError())
    {
    case CSerial::EErrorBreak: printf("Break condition"); break;
    case CSerial::EErrorFrame: printf("Framing error"); break;
    case CSerial::EErrorIOE: printf("IO device error"); break;
    case CSerial::EErrorMode: printf("Unsupported mode"); break;
    case CSerial::EErrorOverrun: printf("Buffer overrun"); break;
    case CSerial::EErrorRxOver: printf("Input buffer overflow"); break;
    case CSerial::EErrorParity: printf("Input parity error"); break;
    case CSerial::EErrorTxFull: printf("Output buffer full"); break;
    default: printf("Unknown"); break;
    }
    printf(" ###\n");
    }

    // Handle ring event
    if (eEvent & CSerial::EEventRing)
    {
    printf("\n### RING ###\n");
    }

    // Handle RLSD/CD event
    if (eEvent & CSerial::EEventRLSD)
    {
    printf("\n### RLSD/CD %s ###\n", serial.GetRLSD()?"on":"off");
    }

    // Handle data receive event
    if (eEvent & CSerial::EEventRecv)
    {
    // Read data, until there is nothing left
    DWORD dwBytesRead = 0;
    char szBuffer[101];
    do
    {
    // Read data from the COM-port
    lLastError = serial.Read(szBuffer,sizeof(szBuffer)-1,&dwBytesRead);
    if (lLastError != ERROR_SUCCESS)
    return ::ShowError(serial.GetLastError(), _T("Unable to read from COM-port."));

    if (dwBytesRead > 0)
    {
    // Finalize the data, so it is a valid string
    szBuffer[dwBytesRead] = '\0';

    // Display the data
    printf("%s", szBuffer);

    // Check if EOF (CTRL+'[') has been specified
    if (strchr(szBuffer,EOF_Char))
    fContinue = false;
    }
    }
    while (dwBytesRead == sizeof(szBuffer)-1);
    }
    }
    while (fContinue);

    // Close the port again
    serial.Close();
    return 0;
    }



    header of Serial.h


    // Serial.h - Definition of the CSerial class
    //
    // Copyright (C) 1999-2003 Ramon de Klein ([email protected])
    //
    // This library is free software; you can redistribute it and/or
    // modify it under the terms of the GNU Lesser General Public
    // License as published by the Free Software Foundation; either
    // version 2.1 of the License, or (at your option) any later version.
    //
    // This library is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    // Lesser General Public License for more details.
    //
    // You should have received a copy of the GNU Lesser General Public
    // License along with this library; if not, write to the Free Software
    // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA


    #ifndef __SERIAL_H
    #define __SERIAL_H


    //////////////////////////////////////////////////////////////////////
    // The SERIAL_DEFAULT_OVERLAPPED defines if the default open mode uses
    // overlapped I/O. When overlapped I/O is available (normal Win32
    // platforms) it uses overlapped I/O. Windows CE doesn't allow the use
    // of overlapped I/O, so it is disabled there by default.

    #ifndef SERIAL_DEFAULT_OVERLAPPED
    #ifndef SERIAL_NO_OVERLAPPED
    #define SERIAL_DEFAULT_OVERLAPPED true
    #else
    #define SERIAL_DEFAULT_OVERLAPPED false
    #endif
    #endif


    //////////////////////////////////////////////////////////////////////
    //
    // CSerial - Win32 wrapper for serial communications
    //
    // Serial communication often causes a lot of problems. This class
    // tries to supply an easy to use interface to deal with serial
    // devices.
    //
    // The class is actually pretty ease to use. You only need to open
    // the COM-port, where you need to specify the basic serial
    // communication parameters. You can also choose to setup handshaking
    // and read timeout behaviour.
    //
    // The following serial classes are available:
    //
    // CSerial - Serial communication support.
    // CSerialEx - Serial communication with listener thread for events
    // CSerialSync - Serial communication with synchronized event handler
    // CSerialWnd - Asynchronous serial support, which uses the Win32
    // message queue for event notification.
    // CSerialMFC - Preferred class to use in MFC-based GUI windows.
    //
    //
    // Pros:
    // -----
    // - Easy to use (hides a lot of nasty Win32 stuff)
    // - Fully ANSI and Unicode aware
    //
    // Cons:
    // -----
    // - Little less flexibility then native Win32 API, however you can
    // use this API at the same time for features which are missing
    // from this class.
    // - Incompatible with Windows 95 or Windows NT v3.51 (or earlier),
    // because CancelIo isn't support on these platforms. Define the
    // SERIAL_NO_CANCELIO macro for support of these platforms as
    // well. When this macro is defined, then only time-out values of
    // 0 or INFINITE are valid.
    //
    //
    // Copyright (C) 1999-2003 Ramon de Klein
    // ([email protected])

    class CSerial
    {
    // Class enumerations
    public:
    // Communication event
    typedef enum
    {
    EEventUnknown = -1, // Unknown event
    EEventNone = 0, // Event trigged without cause
    EEventBreak = EV_BREAK, // A break was detected on input
    EEventCTS = EV_CTS, // The CTS signal changed state
    EEventDSR = EV_DSR, // The DSR signal changed state
    EEventError = EV_ERR, // A line-status error occurred
    EEventRing = EV_RING, // A ring indicator was detected
    EEventRLSD = EV_RLSD, // The RLSD signal changed state
    EEventRecv = EV_RXCHAR, // Data is received on input
    EEventRcvEv = EV_RXFLAG, // Event character was received on input
    EEventSend = EV_TXEMPTY, // Last character on output was sent
    EEventPrinterError = EV_PERR, // Printer error occured
    EEventRx80Full = EV_RX80FULL, // Receive buffer is 80 percent full
    EEventProviderEvt1 = EV_EVENT1, // Provider specific event 1
    EEventProviderEvt2 = EV_EVENT2, // Provider specific event 2
    }
    EEvent;

    // Baudrate
    typedef enum
    {
    EBaudUnknown = -1, // Unknown
    EBaud110 = CBR_110, // 110 bits/sec
    EBaud300 = CBR_300, // 300 bits/sec
    EBaud600 = CBR_600, // 600 bits/sec
    EBaud1200 = CBR_1200, // 1200 bits/sec
    EBaud2400 = CBR_2400, // 2400 bits/sec
    EBaud4800 = CBR_4800, // 4800 bits/sec
    EBaud9600 = CBR_9600, // 9600 bits/sec
    EBaud14400 = CBR_14400, // 14400 bits/sec
    EBaud19200 = CBR_19200, // 19200 bits/sec (default)
    EBaud38400 = CBR_38400, // 38400 bits/sec
    EBaud56000 = CBR_56000, // 56000 bits/sec
    EBaud57600 = CBR_57600, // 57600 bits/sec
    EBaud115200 = CBR_115200, // 115200 bits/sec
    EBaud128000 = CBR_128000, // 128000 bits/sec
    EBaud256000 = CBR_256000, // 256000 bits/sec
    }
    EBaudrate;

    // Data bits (5-8)
    typedef enum
    {
    EDataUnknown = -1, // Unknown
    EData5 = 5, // 5 bits per byte
    EData6 = 6, // 6 bits per byte
    EData7 = 7, // 7 bits per byte
    EData8 = 8 // 8 bits per byte (default)
    }
    EDataBits;

    // Parity scheme
    typedef enum
    {
    EParUnknown = -1, // Unknown
    EParNone = NOPARITY, // No parity (default)
    EParOdd = ODDPARITY, // Odd parity
    EParEven = EVENPARITY, // Even parity
    EParMark = MARKPARITY, // Mark parity
    EParSpace = SPACEPARITY // Space parity
    }
    EParity;

    // Stop bits
    typedef enum
    {
    EStopUnknown = -1, // Unknown
    EStop1 = ONESTOPBIT, // 1 stopbit (default)
    EStop1_5 = ONE5STOPBITS,// 1.5 stopbit
    EStop2 = TWOSTOPBITS // 2 stopbits
    }
    EStopBits;

    // Handshaking
    typedef enum
    {
    EHandshakeUnknown = -1, // Unknown
    EHandshakeOff = 0, // No handshaking
    EHandshakeHardware = 1, // Hardware handshaking (RTS/CTS)
    EHandshakeSoftware = 2 // Software handshaking (XON/XOFF)
    }
    EHandshake;

    // Timeout settings
    typedef enum
    {
    EReadTimeoutUnknown = -1, // Unknown
    EReadTimeoutNonblocking = 0, // Always return immediately
    EReadTimeoutBlocking = 1 // Block until everything is retrieved
    }
    EReadTimeout;

    // Communication errors
    typedef enum
    {
    EErrorUnknown = 0, // Unknown
    EErrorBreak = CE_BREAK, // Break condition detected
    EErrorFrame = CE_FRAME, // Framing error
    EErrorIOE = CE_IOE, // I/O device error
    EErrorMode = CE_MODE, // Unsupported mode
    EErrorOverrun = CE_OVERRUN, // Character buffer overrun, next byte is lost
    EErrorRxOver = CE_RXOVER, // Input buffer overflow, byte lost
    EErrorParity = CE_RXPARITY,// Input parity error
    EErrorTxFull = CE_TXFULL // Output buffer full
    }
    EError;

    // Port availability
    typedef enum
    {
    EPortUnknownError = -1, // Unknown error occurred
    EPortAvailable = 0, // Port is available
    EPortNotAvailable = 1, // Port is not present
    EPortInUse = 2 // Port is in use

    }
    EPort;

    // Construction
    public:
    CSerial();
    virtual ~CSerial();

    // Operations
    public:
    // Check if particular COM-port is available (static method).
    static EPort CheckPort (LPCTSTR lpszDevice);

    // Open the serial communications for a particular COM port. You
    // need to use the full devicename (i.e. "COM1") to open the port.
    // It's possible to specify the size of the input/output queues.
    virtual LONG Open (LPCTSTR lpszDevice, DWORD dwInQueue = 0, DWORD dwOutQueue = 0, bool fOverlapped = SERIAL_DEFAULT_OVERLAPPED);

    // Close the serial port.
    virtual LONG Close (void);

    // Setup the communication settings such as baudrate, databits,
    // parity and stopbits. The default settings are applied when the
    // device has been opened. Call this function if these settings do
    // not apply for your application. If you prefer to use integers
    // instead of the enumerated types then just cast the integer to
    // the required type. So the following two initializations are
    // equivalent:
    //
    // Setup(EBaud9600,EData8,EParNone,EStop1)
    //
    // or
    //
    // Setup(EBaudrate(9600),EDataBits(8),EParity(NOPARITY),EStopBits(ONESTOPBIT))
    //
    // In the latter case, the types are not validated. So make sure
    // that you specify the appropriate values.
    virtual LONG Setup (EBaudrate eBaudrate = EBaud9600,
    EDataBits eDataBits = EData8,
    EParity eParity = EParNone,
    EStopBits eStopBits = EStop1);

    // Set/clear the event character. When this byte is being received
    // on the serial port then the EEventRcvEv event is signalled,
    // when the mask has been set appropriately. If the fAdjustMask flag
    // has been set, then the event mask is automatically adjusted.
    virtual LONG SetEventChar (BYTE bEventChar, bool fAdjustMask = true);

    // Set the event mask, which indicates what events should be
    // monitored. The WaitEvent method can only monitor events that
    // have been enabled. The default setting only monitors the
    // error events and data events. An application may choose to
    // monitor CTS. DSR, RLSD, etc as well.
    virtual LONG SetMask (DWORD dwMask = EEventBreak|EEventError|EEventRecv);

    // The WaitEvent method waits for one of the events that are
    // enabled (see SetMask).
    virtual LONG WaitEvent (LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);

    // Setup the handshaking protocol. There are three forms of
    // handshaking:
    //
    // 1) No handshaking, so data is always send even if the receiver
    // cannot handle the data anymore. This can lead to data loss,
    // when the sender is able to transmit data faster then the
    // receiver can handle.
    // 2) Hardware handshaking, where the RTS/CTS lines are used to
    // indicate if data can be sent. This mode requires that both
    // ports and the cable support hardware handshaking. Hardware
    // handshaking is the most reliable and efficient form of
    // handshaking available, but is hardware dependant.
    // 3) Software handshaking, where the XON/XOFF characters are used
    // to throttle the data. A major drawback of this method is that
    // these characters cannot be used for data anymore.
    virtual LONG SetupHandshaking (EHandshake eHandshake);

    // Read operations can be blocking or non-blocking. You can use
    // this method to setup wether to use blocking or non-blocking
    // reads. Non-blocking reads is the default, which is required
    // for most applications.
    //
    // 1) Blocking reads, which will cause the 'Read' method to block
    // until the requested number of bytes have been read. This is
    // useful if you know how many data you will receive.
    // 2) Non-blocking reads, which will read as many bytes into your
    // buffer and returns almost immediately. This is often the
    // preferred setting.
    virtual LONG SetupReadTimeouts (EReadTimeout eReadTimeout);

    // Obtain communication settings
    virtual EBaudrate GetBaudrate (void);
    virtual EDataBits GetDataBits (void);
    virtual EParity GetParity (void);
    virtual EStopBits GetStopBits (void);
    virtual EHandshake GetHandshaking (void);
    virtual DWORD GetEventMask (void);
    virtual BYTE GetEventChar (void);

    // Write data to the serial port. Note that we are only able to
    // send ANSI strings, because it probably doesn't make sense to
    // transmit Unicode strings to an application.
    virtual LONG Write (const void* pData, size_t iLen, DWORD* pdwWritten = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);
    virtual LONG Write (LPCSTR pString, DWORD* pdwWritten = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);

    // Read data from the serial port. Refer to the description of
    // the 'SetupReadTimeouts' for an explanation about (non) blocking
    // reads and how to use this.
    virtual LONG Read (void* pData, size_t iLen, DWORD* pdwRead = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);

    // Send a break
    LONG Break (void);

    // Determine what caused the event to trigger
    EEvent GetEventType (void);

    // Obtain the error
    EError GetError (void);

    // Obtain the COMM and event handle
    HANDLE GetCommHandle (void) { return m_hFile; }

    // Check if com-port is opened
    bool IsOpen (void) const { return (m_hFile != 0); }

    // Obtain last error status
    LONG GetLastError (void) const { return m_lLastError; }

    // Obtain CTS/DSR/RING/RLSD settings
    bool GetCTS (void);
    bool GetDSR (void);
    bool GetRing (void);
    bool GetRLSD (void);

    // Purge all buffers
    LONG Purge (void);

    protected:
    // Internal helper class which wraps DCB structure
    class CDCB : public DCB
    {
    public:
    CDCB() { DCBlength = sizeof(DCB); }
    };

    // Attributes
    protected:
    LONG m_lLastError; // Last serial error
    HANDLE m_hFile; // File handle
    EEvent m_eEvent; // Event type
    DWORD m_dwEventMask; // Event mask

    #ifndef SERIAL_NO_OVERLAPPED
    HANDLE m_hevtOverlapped; // Event handle for internal overlapped operations
    #endif

    protected:
    // Check the requirements
    void CheckRequirements (LPOVERLAPPED lpOverlapped, DWORD dwTimeout) const;

    // CancelIo wrapper (for Win95 compatibility)
    BOOL CancelCommIo (void);
    };

    #endif // __SERIAL_H
    Last edited by joellee; August 29th, 2009 at 06:31 PM. Reason: forgot to attach files

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured