【问题标题】:writing and reading to/from a serial port with a timeout in c++ and Linux在 C++ 和 Linux 中使用超时写入和读取串行端口
【发布时间】:2014-09-01 16:36:58
【问题描述】:

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

  • 这样的任务最简单的实现是什么?
  • 我需要使用 boost 之类的东西吗?

明确一点:我正在寻找实现这一目标的最简单方法。

对不起,如果我的问题很愚蠢,但我是这个话题的新手,在此先感谢!

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

【问题讨论】:

  • 好吧,好吧,..但正如文件中所写:如果没有收到数据,这个函数将挂起,因为没有设置超时。 - 我认为这是我最大的问题。
  • 请看我的编辑(回答)

标签: c++ linux serial-port


【解决方案1】:

这应该与您的声明类似:

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

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

读取数据:

// 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));

更多细节可以在这里找到代码项目:http://www.codeproject.com/Articles/992/Serial-library-for-C

请注意:我习惯于用 c# 编写串行端口,因此(据我所知)相信这对你有用。 (我还想指出,所有串口通信实际上是通过十六进制发送的,但可以通过缓冲区读取为十进制值(请参阅http://www.asciitable.com/进行转换,或使用类似于UTF8编码的东西)

编辑 - 根据评论;

串口读/写超时详情请参考:http://msdn.microsoft.com/en-gb/library/windows/hardware/hh439614(v=vs.85).aspx

写入超时将类似于;

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

它允许您获取或设置超时属性

完整计划

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 ^) { }
        }
    }

编辑 2

请参阅Linux Serial Port: Blocking Read with Timeout,其中已在问题中声明了这一点,并且某些答案也可能对您有用! :)

【讨论】:

  • 嗯,这一切在我看来很像我只能在 Windows 上使用它?对不起,我忘了提到它应该在 linux 系统上使用,我相应地更新了我的问题。
【解决方案2】:

我最近遇到了同样的问题,我使用 select() 找到了一个很好的解决方案 在此处阅读文档:manpages.courirer-mta.org/htmlman2/select2.html

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

    struct timeval timeout;

    timeout.tv_sec = 0 ; // seconds

    timeout.tv_usec = 1000 ; // microseconds

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2012-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-21
    • 2014-10-01
    相关资源
    最近更新 更多