好吧,我会尽力弄清楚我的问题。
我正在通过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(请注意,那里没有监视器,也没有等待;相反,工作是在侦听器/回调中完成的。)

09-04 00:57
查看更多