如何在运行异步串行通信时等待响应?

时间:2012-11-27 15:14:00

标签: c asynchronous

我对这个问题有些不确定,但我不断遇到目前的设计问题,如果有人能表现出不同的方法,我会非常感激。

我的程序通过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中。

2 个答案:

答案 0 :(得分:1)

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

Write thread.
    Register expected response.
    Send packet to the device
    Wait for Received event with timeout. If event is set, continue. Timeout - 
    report error and exit (or make additional trial).

Read thread.
For every received packet:
    Add it to the input buffer.
    Analyze buffer. If it contains valid response, set "Received" event, 
    releasing the Write thread, clear input buffer, and continue reading. 
    If input buffer contains unrecognized data, report error, clear buffer 
    and continue reading.
    If input buffer contains the beginning of expected response, 
    continue reading.

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

编辑。

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

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

答案 1 :(得分:0)

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

C标准不了解串口。