2012-05-22 39 views
1

我使用PC上的普通串口在Java應用程序中發送和接收數據。 PC使用java 1.6.0運行Windows XP SP3。下面是代碼:爲什麼我在Java中的UART性能有所不同?

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字節的傳輸需要15ms傳輸,這看起來很好,因爲它接近理論最小值。我不確定爲什麼它在實踐中比理論上更快。然而,問題在於,有時256字節的傳輸需要32ms,即需要的兩倍。什麼可能導致這個?

/Henrik

+0

我看到你添加了「input = new BufferedInputStream(input,1024);」我認爲這會解決我的問題,但這似乎沒有做任何事情。看起來你將被限制在實際的UART芯片上的緩衝區大小,沒有什麼比這更少的了。嘗試不同大小然後發送自己的字符,並保持在4096最大。我希望有一種方法可以知道uart的最大緩衝區大小,儘管java –

回答

0

你用System.nanoTime()測量時間嗎?

System.currentTimeMillis()使用的Windows時鐘分辨率默認約爲15ms,因此實時每個任務可能需要20ms,但有些分佈在兩個刻度而不是一個。

查看System.currentTimeMillis vs System.nanoTime瞭解更多信息。

3

A(windows)PC不是實時機器。這意味着,當您的應用程序必須訪問硬件層時,它可能會延遲。由於系統(內核)的工作方式,您無法控制此功能,並且在進入功能和退出功能之間沒有固定時間。

大多數Linux機器的行爲方式相同。在後臺運行的其他任務(應用程序)會消耗處理能力,因此在發送實際數據之前,您的應用程序可能會在進程隊列中移動一段時間。

即使在發送過程中,每個發送的字節之間可能會有延遲。這一切都由內核/硬件層來處理,並且你的軟件不能改變它。

如果您確實需要實時執行,那麼您必須查找real-time operating system

此行概括起來相當漂亮:

實時操作系統的關鍵特性是它關於它需要接受並完成應用程序的任務時間量一致的水平;變化是抖動。

如果使用RTOS,這個抖動是已知/定義的,而且對於正常的OS,這個抖動是未知的/未定義的。

+0

好的謝謝。如果我在Windows中以更高的優先級運行我的Java應用程序,它可以幫助嗎?像這樣在Windows命令提示符下: start/HIGH javaw -jar MyApp.jar – Sp4ceCoder

+0

幾乎沒有。這可能會有所作爲,但我不知道(我從來沒有嘗試過,從來沒有需要它)。 –

+0

另外,您正在使用Java。我不是一個真正的java期望,但afaik Java與調度程序和垃圾收集器一起運行在一個線程上(糾正我,如果我錯了)。這些也佔用了處理時間。如果你的方法被垃圾收集器中斷,那麼你的執行過程仍然會有延遲。 –

相關問題