1

我对这个问题有点不确定,但我经常在我目前的设计中遇到麻烦,如果有人能展示出一种不同的方法,那真的很棒。

我的程序通过 rs232 将异步命令写入设备,同时不断读取接收到的数据并做出反应。

这一切都很好,很整洁,但是在我的初始化阶段,我必须发送一堆命令,这些命令必须等待响应,然后才能让程序开始计数。

现在,这部分我必须用纯 C 语言完成,而我所能想到的就是使用全局变量和 while 循环。但我觉得这真的不漂亮。

以此作为伪代码示例:

OnReceive(data){
 switch determineCommand(data)
   case CMD1:
      config.value1 = data.value1             
   case CMD2:
      config.value2 = data.value2
   default:
      print data
}

DoCommandChain(){
  Send(CMD1)
  If("Send(CMD1)" got its response){
    Send(CMD2)
  }
}

现在,问题是“如果 XY 得到它的响应”——因为我不想使用一些变量来检测这一点,而且我不能依赖 Send(CMD1) 的返回值,因为这只是一个指标,即CMD1 已发送 - 没有收到相应的内容。

我在这里问,因为我想知道我可以搜索/阅读什么,以一种很好的方式解决这个烂摊子。

现在,我最好的想法是设置一个计时器保护功能来监控,如果收到特定的响应。然后,根据此响应的状态,转到下一个Send或重试上一个。

像这样:

Instead of `Send(CMD1)` -> `DoUntilResponse(Send(CMD1),Timeout,NumberOfRetries)`

DoUntilResponse(function,Timeout,NumberOfRetries){
   registerExpectedResponse(CMD1, gotResponse) //awaiting some response for CMD1

   for(i=0 ; i!=Numberofretries; i++){
       if (Send(CMD1) == successfulSend ){
          while(not timeout){
             if gotResponse then break;
             }
          if gotResponse then break;
      }           
   }

}

编辑:

澄清一下:我不担心串行连接,也不担心如何触发该OnReceive功能 - 这一切都已经开始工作了。我不清楚的是,如何在不使用轮询的情况下解决上述伪代码,最好在纯 C 中解决。

4

2 回答 2

1

假设写入和读取操作在不同的线程中执行,使用以下算法:

写线程。
    注册预期响应。
    向设备发送数据包
    等待超时的接收事件。如果设置了事件,请继续。超时 -
    报告错误并退出(或进行额外的尝试)。

阅读线程。
对于每个收到的数据包:
    将其添加到输入缓冲区。
    分析缓冲区。如果它包含有效响应,则设置“Received”事件,
    释放写入线程,清除输入缓冲区,然后继续读取。
    如果输入缓冲区包含无法识别的数据,则报告错误,清除缓冲区
    并继续阅读。
    如果输入缓冲区包含预期响应的开头,
    继续阅读。

线程和事件通知是特定于操作系统的。如果您的 C++ 编译器不支持多线程,请使用 Boost 等可移植库,或使用特定于操作系统的 API。请注意,Read 线程实现了流解析逻辑,因为串行通信是面向流的。

编辑。

“注册预期响应”意味着:设置一些程序变量而不是意味着“类型 X 的命令被发送到设备”。根据该变量,Read 线程期望接收数据包,该数据包应由设备根据通信协议(特定于应用程序)发送。另一个接收到的通常有效的数据包应该被视为错误,因为这不是对刚刚发送到设备的命令的响应。

另一种方式:设置预期响应大小。在这种情况下,一旦 Read 线程接收到预期数量的数据,它就会设置 Received 事件,将数据包识别任务留给发送方。

于 2012-11-27T15:24:54.263 回答
0

它是特定于操作系统的。在 Linux 或 Unix 上,您应该考虑使用像poll(2)这样的多路复用系统调用(或者可能是我觉得已经过时的select(2),因为它限制了最大文件描述符数,请参阅C10K问题)。

C标准不知道串行端口。

于 2012-11-27T15:16:33.770 回答