好吧,我会尽力弄清楚我的问题。
我正在通过veeeeeeery慢速无线电链路(使用raspberry pi上的UART控制器和自制无线电)传输串行数据。它是针对一个非常具体的项目,在该项目中,要求拼写很长,而速度次要。
该程序(Radio.java)正在运行两个线程。一个线程(接收器)使用TCP套接字(非常高的速度,实际上是100mbit)从另一个程序接收遥测数据。该线程将它在TCP套接字上接收到的数据连续保存在ArrayBlockingQueue(大小= 1)中,以便其他线程(发送器)可以访问此数据。接收器线程接收数据的速率非常高。现在,我希望Transmitter线程传输数据,完成后,我希望它再次从Receiver线程获取最新数据,然后通过慢速无线电链路再次传输数据。
因此,在发射器线程中,我希望它像这样工作:
从接收器线程获取最新数据
通过无线电链路传输数据(使用串行端口)
在实际传输数据之前,请勿执行任何操作。
重复。
现在,当我运行程序时,与接收器线程有关的所有内容都可以正常工作。但是在发送器线程内部的行“ this.out.write(output.getBytes());”只需在几毫秒内将所有内容放入OutputStream中,然后再次执行相同的操作。数据没有传输的机会!
我在这里尝试了该示例(仅使用“ SerialWriter”线程):
http://rxtx.qbang.org/wiki/index.php/Two_way_communcation_with_the_serial_port
并且使用长的“ Lirum Ipsum”文本,一切正常,以50baud传输就可以了。因此,基本上,我希望程序中的行为与使用System.in.read> -1 ...相同(我想这是阻塞的,它起作用的原因???)。
我该怎么办?
2015-01-01编辑BEGIN
我发现了问题! SRobertz带我朝正确的方向前进!问题实际上不是UART缓冲区的写入速度。运行“ TwoWayComm”示例和我自己的代码之间的区别在于,我正在运行连接到Raspberry Pi的UART-RX端口的GPS。要从GPS读取数据,请使用“ GPSD”软件(以JSON格式输出数据)。 GPSD软件以9600baud(专门用于此GPS装置)连接到GPS,而我在同一端口上切换到50波特(无需关闭GPSD正在运行的开放连接)!试图以两种不同的波特率打开UART就是搞砸了一切。
我重写了代码,以便:
在9600波特率上打开UART
读取GPS数据
关闭UART
在50波特率下打开UART
将遥测数据发送到UART
关闭UART
重复
现在一切都像魅力一样...
2015-01-01编辑END
所以...这是代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
public class RADIO {
ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(1);
void connect(String portName) throws Exception {
CommPortIdentifier portIdentifier = CommPortIdentifier
.getPortIdentifier(portName);
if (portIdentifier.isCurrentlyOwned()) {
System.out.println("Error: Port is currently in use");
} else {
int timeout = 2000;
CommPort commPort = portIdentifier.open(this.getClass().getName(),
timeout);
if (commPort instanceof SerialPort) {
SerialPort serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(50, SerialPort.DATABITS_7,
SerialPort.STOPBITS_2, SerialPort.PARITY_NONE);
// Open outputstream to write to the serial port
OutputStream out = serialPort.getOutputStream();
(new Thread(new Receiver(queue))).start();
(new Thread(new Transmitter(out, queue))).start();
} else {
System.err.println("Error: Not serial port.");
}
}
}
public static class Receiver implements Runnable {
OutputStream out;
protected ArrayBlockingQueue<String> queue = null;
public Receiver(ArrayBlockingQueue<String> queue) {
this.queue = queue;
}
public void run() {
// Open TCP-connection
try {
ServerSocket serverSocket = new ServerSocket(1002);
Socket clientSocket = serverSocket.accept(); // Wait for the client to start up
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
String inputLine, outputLine;
while ((inputLine = in.readLine()) != null) {
queue.clear();
queue.put(inputLine);
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static class Transmitter implements Runnable {
OutputStream out;
protected ArrayBlockingQueue<String> queue = null;
String output = "";
public Transmitter(OutputStream out, ArrayBlockingQueue<String> queue) {
this.out = out;
this.queue = queue;
}
public void run() {
try {
while (true) {
output = queue.take();
this.out.write(output.getBytes());
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
try {
(new RADIO()).connect("/dev/ttyAMA0");
} catch (Exception e) {
e.printStackTrace();
}
}
}
最佳答案
(一个小警告:我没有在树莓派上使用gnu.io)
首先,要找出问题所在,我将在sleep
之后在发送器线程中放置一个相当长的this.out.write...
,以验证问题不在等待串行端口进入。
完成传输。
如果可行,则可以尝试通过添加一个OUTPUT_BUFFER_EMPTY
SerialPortEventListener
并设置notifyOnOutputEmpty(true)
,SerialPortEventListener
沿着
class ExampleMonitor implements SerialPortEventListener {
boolean condition;
public synchronized serialEvent(SerialPortEvent ev) {
condition = true;
notifyAll();
}
public synchronized void awaitCondition() throws InterruptedException {
while(!condition) wait();
condition = false;
}
然后做
myExampleMonitor.awaitCondition()
而不是传输线程中的sleep
。有关事件的逆用法,请参见http://rxtx.qbang.org/wiki/index.php/Event_based_two_way_Communication(请注意,那里没有监视器,也没有等待;相反,工作是在侦听器/回调中完成的。)