在c++和Linux中使用超时对串行端口进行读写

时间:2021-10-11 04:48:05

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.

我正在尝试将一些十六进制字符串发送到一个串行端口,并直接用c++读取它的答案。如果没有答案,它应该在给定的一段时间后超时。

  • What is the simplest implementation of such a task?
  • 这种任务最简单的实现是什么?
  • Do i need to use stuff like boost?
  • 我需要使用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.

编辑:对不起,我忘了说,它应该在Linux上运行。

2 个解决方案

#1


1  

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

更多的细节可以在代码项目中找到:http://www.codeproject.com/articles/992/seriallibrary 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)

请注意:我习惯于在c#中编程串口,所以(就我所知)相信这对您是有用的。(我还想指出,所有串口通信实际上是通过十六进制发送的,但是可以通过缓冲区以十进制值的形式读取(请参阅http://www.asciitable.com/进行交谈,或者使用类似于UTF8编码的东西)

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

有关串口读/写超时的详细信息,请参阅:http://msdn.microsoft.com/en-gb/library/windows/hardware/hh439614(v=vs.85).aspx

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

它允许您获取或设置timeout属性

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

编辑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! :)

请参考Linux串行端口:阻塞读和超时,在问题中已经声明了这一点,一些答案可能对您也很有用!:)

#2


1  

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

最近我也遇到了同样的问题,我发现使用select()可以找到一个很好的解决方案:manpages.courirer-mta.org/htmlman2/select2.html

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

在您的情况下,您需要设置timeout,这是select的第5个参数:

    struct timeval timeout;

    timeout.tv_sec = 0 ; // seconds

    timeout.tv_usec = 1000 ; // microseconds

Hope this helps.

希望这个有帮助。

#1


1  

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

更多的细节可以在代码项目中找到:http://www.codeproject.com/articles/992/seriallibrary 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)

请注意:我习惯于在c#中编程串口,所以(就我所知)相信这对您是有用的。(我还想指出,所有串口通信实际上是通过十六进制发送的,但是可以通过缓冲区以十进制值的形式读取(请参阅http://www.asciitable.com/进行交谈,或者使用类似于UTF8编码的东西)

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

有关串口读/写超时的详细信息,请参阅:http://msdn.microsoft.com/en-gb/library/windows/hardware/hh439614(v=vs.85).aspx

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

它允许您获取或设置timeout属性

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

编辑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! :)

请参考Linux串行端口:阻塞读和超时,在问题中已经声明了这一点,一些答案可能对您也很有用!:)

#2


1  

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

最近我也遇到了同样的问题,我发现使用select()可以找到一个很好的解决方案:manpages.courirer-mta.org/htmlman2/select2.html

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

在您的情况下,您需要设置timeout,这是select的第5个参数:

    struct timeval timeout;

    timeout.tv_sec = 0 ; // seconds

    timeout.tv_usec = 1000 ; // microseconds

Hope this helps.

希望这个有帮助。