首页 文章

为什么我在Java中的UART性能有所不同?

提问于
浏览
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位/ s = 17.7ms进行传输 .

我将Time2-Time1的测量值放在一个数组中,即发送时间,然后再检查 . 事实证明,有时传输256字节需要15ms进行传输,这似乎很好,因为它接近理论最小值 . 我不确定为什么它在实践中比在理论上更快 . 然而,问题是有时256字节的传输需要32ms,即所需的两倍 . 可能是什么导致了这个?

/亨里克

2 回答

  • 0

    你用System.nanoTime()来衡量时间吗?

    System.currentTimeMillis()使用的Windows时钟分辨率默认大约为15ms,因此实际上每个任务需要20ms,但有些分布在两个刻度而不是一个 .

    有关详细信息,请参阅System.currentTimeMillis vs System.nanoTime .

  • 3

    (Windows)PC不是实时机器 . 这意味着,当您的应用程序必须访问硬件层时,它可能会被延迟 . 您无法控制这一点,由于系统(内核)的工作原理,在输入函数和退出函数之间没有固定的时间 .

    大多数Linux机器的行为方式相同 . 在后台运行的其他任务(应用程序)消耗处理能力,因此在发送实际数据之前,您的应用程序可能会在进程队列中移动一点 .

    即使在发送过程中,每个发送字节之间也可能存在延迟 . 这全部由内核/硬件层处理,您的软件无法改变这一点 .

    如果您确实需要实时执行,那么您将不得不寻找real-time operating system .

    这条线总结得非常好:

    RTOS的一个关键特性是它在接受和完成应用程序任务所需的时间量方面的一致性水平;可变性是抖动 .

    对于RTOS,此抖动是已知/定义的,并且在正常OS下,此抖动未知/未定义 .

相关问题