简体   繁体   中英

writing and reading to/from a serial port with a timeout in c++ and Linux

I'm trying to send some hex string to a serial port, and directly read its answer in c++. If there is no answer it should timeout after a given period of time.

  • What is the simplest implementation of such a task?
  • Do i need to use stuff like boost?

To be clear: I'm searching for the most simple way to achieve this.

Sorry if my question is dumb, but im new to this topic, thanks in advance!

EDIT: Sorry that I forgot to mention, it should run on Linux.

this should be similar to your declaration:

Setup(CSerial::EBaud9600,CSerial::EData8,CSerial::EParNone,CSerial::EStop1);

Setup(CSerial::EBaudrate(9600),
      CSerial::EDataBits(8),
      CSerial::EParity(NOPARITY),
      CSerial::EStopBits(ONESTOPBIT));

Reading data:

// Read data, until there is nothing left
    DWORD dwBytesRead = 0;
    BYTE  abBuffer[100];
    do
    {
        // Read data from the COM-port
        serial.Read(abBuffer,sizeof(abBuffer),&dwBytesRead);
        if (dwBytesRead > 0)
        {
            // TODO: Process the data
        }
    }
    while (dwBytesRead == sizeof(abBuffer));

More details can be found here on code project: http://www.codeproject.com/Articles/992/Serial-library-for-C

Please note: I am used to programming serial ports in c#, and so (to the best of my knowledge) believe this would work for you. (I would also like to point outall serial port communication is send actually through as hex, but may be read via the buffer as a decimal value ( please refer to http://www.asciitable.com/ for converstion, or use something similar to UTF8 encoding)

EDIT - As per comment;

Please refer to : http://msdn.microsoft.com/en-gb/library/windows/hardware/hh439614(v=vs.85).aspx for details on serial port read/write timeouts

Write timeout will be similar to;

[BrowsableAttribute(true)]
public:
property int WriteTimeout {
    int get ();
    void set (int value);
}

Which allows you to get or set the timeout attribute

Full Program

public:
    static void Main()
    {
        String^ name;
        String^ message;
        StringComparer^ stringComparer = StringComparer::OrdinalIgnoreCase;
        Thread^ readThread = gcnew Thread(gcnew ThreadStart(PortChat::Read));

        // Create a new SerialPort object with default settings.
        _serialPort = gcnew SerialPort();

        // Allow the user to set the appropriate properties.
        _serialPort->PortName = SetPortName(_serialPort->PortName);
        _serialPort->BaudRate = SetPortBaudRate(_serialPort->BaudRate);
        _serialPort->Parity = SetPortParity(_serialPort->Parity);
        _serialPort->DataBits = SetPortDataBits(_serialPort->DataBits);
        _serialPort->StopBits = SetPortStopBits(_serialPort->StopBits);
        _serialPort->Handshake = SetPortHandshake(_serialPort->Handshake);

        // Set the read/write timeouts
        _serialPort->ReadTimeout = 500;
        _serialPort->WriteTimeout = 500;

        _serialPort->Open();
        _continue = true;
        readThread->Start();

        Console::Write("Name: ");
        name = Console::ReadLine();

        Console::WriteLine("Type QUIT to exit");

        while (_continue)
        {
            message = Console::ReadLine();

            if (stringComparer->Equals("quit", message))
            {
                _continue = false;
            }
            else
            {
                _serialPort->WriteLine(
                    String::Format("<{0}>: {1}", name, message) );
            }
        }

        readThread->Join();
        _serialPort->Close();
    }

    static void Read()
    {
        while (_continue)
        {
            try
            {
                String^ message = _serialPort->ReadLine();
                Console::WriteLine(message);
            }
            catch (TimeoutException ^) { }
        }
    }

EDIT 2

Please refer to Linux Serial Port: Blocking Read with Timeout where this has been declared in the question and some of the answers may prove useful to you as well! :)

I recently came for the same issue and I found a good solution using select() Read the documentation here: manpages.courirer-mta.org/htmlman2/select2.html

In your case you need to setup the timeout, which is the 5th argument of select:

    struct timeval timeout;

    timeout.tv_sec = 0 ; // seconds

    timeout.tv_usec = 1000 ; // microseconds

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM