1

PC の通常のシリアル ポートを使用して、Java アプリケーションでデータを送受信しています。PC は Java 1.6.0 で Windows XP SP3 を実行します。コードは次のとおりです。

import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.util.concurrent.ArrayBlockingQueue;

// Open the serial port.
CommPortIdentifier portId;
SerialPort serialPort;
portId = CommPortIdentifier.getPortIdentifier("COM1");
serialPort = (SerialPort) portId.open("My serial port", 1000 /* 1 second timeout */);
serialPort.setSerialPortParams(115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

// Set up input and output streams which will be used to receive and transmit data on the UART.
InputStream input;
OutputStream output;
input = serialPort.getInputStream();
output = serialPort.getOutputStream();

// Wrap the input and output streams in buffers to improve performance. 1024 is the buffer size in bytes. 
input = new BufferedInputStream(input, 1024);
output = new BufferedOutputStream(output, 1024);

// Sync connection.
// Validate connection.
// Start Send- and Receive threads (see below).
// Send a big chunk of data.

データを送信するために、キュー (ArrayBlockingQueue) からパッケージを取得して UART で送信するスレッドをセットアップしました。受信についても同様です。アプリケーションの他の部分は、単純にパッケージを送信キューに挿入し、受信キューをポーリングして応答を取得できます。

private class SendThread extends Thread {
  public void run() {
    try {
      SendPkt pkt = SendQueue.take();
      // Register Time1.
      output.write(pkt.data);
      output.flush();
      // Register Time2.
      // Put the data length and Time2-Time1 into an array.

      // Receive Acknowledge.
      ResponsePkt RspPkt = new ResponsePkt();
      RspPkt.data = receive(); // This function calls "input.read" and checks for errors.
      ReceiveQueue.put(RspPkt);
    } catch (IOException e) { ... }
  }

各送信パケットは最大 256 バイトで、転送には 256*8 ビット / 115200 ビット/秒 = 17,7ms かかります。

Time2-Time1 の測定値、つまり送信時刻を配列に入れ、後で確認します。256 バイトの転送には転送に 15 ミリ秒かかる場合があることがわかりました。これは、理論上の最小値に近いため、問題ないようです。理論よりも実際に高速である理由はわかりません。ただし、問題は、256 バイトの転送に 32 ミリ秒、つまり必要な時間の 2 倍かかる場合があることです。何が原因でしょうか?

/ヘンリック

4

2 に答える 2

3

(Windows) PC はリアルタイム マシンではありません。つまり、アプリケーションがハードウェア レイヤーにアクセスする必要があるときはいつでも、遅延が発生する可能性があります。これを制御することはできません。また、システム (カーネル) の仕組みにより、関数に入ってから関数を終了するまでの一定の時間もありません。

ほとんどの Linux マシンは同じように動作します。バックグラウンドで実行されている他のタスク (アプリケーション) が処理能力を消費するため、アプリケーションは実際のデータを送信する前にプロセス キュー内で少し移動する可能性があります。

送信プロセスでも、送信される各バイト間に遅延が生じる場合があります。これはすべてカーネル/ハードウェア層によって処理され、ソフトウェアはそれを変更できません。

リアルタイム実行が必要な場合は、リアルタイム オペレーティング システムを探す必要があります。

この行はそれをかなりうまくまとめています:

RTOS の重要な特徴は、アプリケーションのタスクを受け入れて完了するのにかかる時間に関する一貫性のレベルです。変動性はジッタです。

RTOS ではこのジッターは既知/定義されていますが、通常の OS ではこのジッターは不明/未定義です。

于 2012-05-22T11:07:34.693 に答える
0

System.nanoTime() で時間を計測していますか?

System.currentTimeMillis() で使用される Windows クロックの解像度は、デフォルトで約 15 ミリ秒であるため、おそらくリアルタイムで各タスクに 20 ミリ秒かかりますが、1 ティックではなく 2 ティックにまたがるものもあります。

詳細については、 System.currentTimeMillis と System.nanoTimeを参照してください。

于 2012-05-22T14:42:58.807 に答える