在RXTX中收到的问题

时间:2009-09-08 00:23:56

标签: java serial-port rxtx

我一直在使用RXTX大约一年,没有太多问题。我刚刚开始一个新的程序与一个新的硬件进行交互,所以我重用了我在其他项目中使用的connect()方法,但是我有一个我以前从未见过的奇怪问题。

问题

设备工作正常,因为当我连接HyperTerminal时,我发送内容并收到我期望的内容,Serial Port Monitor(SPM)反映了这一点。

然而,当我运行简单的HyperTerminal-clone时,我编写了诊断问题,我正在使用我的主应用程序,根据SPM发送字节,但没有收到任何内容,我的SerialPortEventListener永远不会触发。即使我在主循环中检查可用数据,reader.ready()也会返回false。如果我忽略了这个检查,那么我得到一个例外,详情如下。

connect()方法的相关部分

// Configure and open port
port = (SerialPort) CommPortIdentifier.getPortIdentifier(name)
                                      .open(owner,1000)
port.setSerialPortParams(baud, databits, stopbits, parity);
port.setFlowControlMode(fc_mode);
final BufferedReader br = new BufferedReader(
                            new InputStreamReader(
                              port.getInputStream(), 
                              "US-ASCII"));

// Add listener to print received characters to screen
port.addEventListener(new SerialPortEventListener(){
  public void serialEvent(SerialPortEvent ev) {
    try {
      System.out.println("Received: "+br.readLine());
    } catch (IOException e) { e.printStackTrace(); }
  }   
});
port.notifyOnDataAvailable();

异常

java.io.IOException: Underlying input stream returned zero bytes
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:268)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
        at java.io.InputStreamReader.read(InputStreamReader.java:167)
        at java.io.BufferedReader.fill(BufferedReader.java:136)
        at java.io.BufferedReader.read(BufferedReader.java:157)
        at <my code>

重大问题(再次)

我认为我已经消除了所有可能的硬件问题,那么我的代码或RXTX库可能出现什么问题?

编辑:有趣的事情

当我从java发送一堆应该得到响应的命令后打开HyperTerminal时,所有的响应都会立即显示,好像它们已放在缓冲区某处,但不可用。

编辑2:尝试了一些新的,相同的结果

我运行了代码示例here,结果相同。没有数据进入,但当我切换到一个新程序时,它立刻就出现了。

编辑3

硬件很好,即使是不同的计算机也有同样的问题。我没有使用任何类型的USB适配器。

我也开始使用PortMon,它给了我一些有趣的结果。 HyperTerminal和RXTX没有使用相同的设置,并且RXTX总是轮询端口,不像HyperTerminal,但我仍然看不出会影响这个设置。只要我可以将配置与常量轮询隔离开来,我就会发布我的PortMon日志。

编辑4

过去3个月内某种类型的Windows更新是否可能导致此问题?它曾经搞过我的一个基于MATLAB mex的程序。

编辑5

我还注意到HyperTerminal,RXTX和我发现与设备通信的单独程序之间有些不同的东西(但是没有按我想要的那样做,这就是为什么我要编写我自己的程序)

  • 超级终端 - 设置为无流量控制,但串口监视器的RTS和DTR指示灯为绿色
  • 其他程序 - 不确定它认为使用的设置,但只有SPM的RTS指示灯为绿色
  • RXTX - 无论我设置什么流量控制,只有SPM的CTS和DTR指示灯亮起。

来自Serial Port Monitor的帮助文件(转述):

the indicators display the state of the serial control lines

  RTS - Request To Send
  CTS - Clear To Send
  DTR - Data Terminal Ready

6 个答案:

答案 0 :(得分:7)

好的,对不起,我花了很长时间才回到这个问题。这就是我让事情发挥作用的方式。

注意:此方法 NOT 适用于所有人,请在复制/粘贴到您自己的代码之前阅读以下内容

public void connect(CommPortIdentifier portId) throws Failure {
    if (portId == null)
        throw new Failure("No port set");

    try { port = (SerialPort) portId.open(getClass().getName(), 10000); } 
    catch (PortInUseException e) {
        throw new Failure("Port in use by " + e.currentOwner,e); }

    try {
        port.setSerialPortParams(9600, SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
        port.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN
                              | SerialPort.FLOWCONTROL_RTSCTS_OUT);
    } catch (UnsupportedCommOperationException e) { throw new Failure(e); }

    port.setRTS(true);

    // More setup
}

所以,就我而言,问题是我的特定设备需要RTS流控制。其他设备可能需要不同的东西(CTS,XON / XOFF),因此请检查该设备的手册。默认情况下,RXTX禁用所有流量控制机制(与Hypertrm或其他程序不同)。启用每个步骤分为两个步骤。

  1. 拥有Seri​​alPort对象后,请调用setFlowControlMode()方法,并按位或('|')调用必要的SerialPort.FLOWCONTROL_常量
  2. 将适当的流量控制设置为true或false(就像我使用port.setRTS(true)
  3. 对于有类似问题的其他人,如果这不起作用,我建议

    1. 使用Serial Port Monitor和/或PortMon(两个Windows)等串口监控程序来查看实际情况。
    2. 通过rxtx@qbang.org向RXTX开发人员发送电子邮件(非常有帮助)

答案 1 :(得分:3)

这个问题有一个更简单的解决方案。这就是我所做的:

BufferedReader br = new BufferedReader(new InputStreamReader(in));
    String line;

    while (keepRunning) {
        try {
            while ((br.ready()) && (line = br.readLine()) != null) {
....
}

如果在阅读之前检查缓冲区是否“准备就绪”,则应该没有问题。

答案 2 :(得分:2)

好的,我确实意识到这个线程非常陈旧,但这些解决方案都不适用于我。我有同样的问题,我尝试了一切来解决它,无济于事。然后我对导致问题的原因进行了一些研究,并且,当不处理串行通信时,它发生在文件的末尾。所以,我想我需要为Java应用程序接收的内容添加一个结尾,特别是一行返回(\ n)。果然,它解决了我的问题!希望这可以帮助一个新人,因为我不希望这有助于任何已经在这个线程上的人......

答案 3 :(得分:0)

(可能过于简单,但也可能从某处开始......)

端口是否正在使用?而不是:

port = (SerialPort) CommPortIdentifier.getPortIdentifier(name)
                                      .open(owner,1000)

怎么样:

CommPortIdentifier portIdentifier;
try {
    portIdentifier = CommPortIdentifier.getPortIdentifier(name);
} catch (NoSuchPortException nspe) {
    // handle?
}
if (portIdentifier.isCurrentlyOwned()) {
    // handle?
}
port = portIdentifier.open(owner, 1000);
if (!(port instanceof SerialPort)) {
    // handle?
}

你吞下任何例外吗?

答案 4 :(得分:0)

几个月前我尝试过RXTX并遇到了类似的问题。我建议两件事:

  1. 使用com0com创建虚拟comport。启用跟踪日志记录比较使用Hyperterminal时的日志与运行自己的程序时的日志。差异将突出你做错了什么。

  2. 在我的拙见中,RXTX的设计存在缺陷,其实现非常错误(看看它的源代码,真是一团糟!)。我在http://kenai.com/projects/jperipheral发布了一个替代库,但有以下注意事项:它仅限Windows,并且没有预先构建的二进制文件。这些都将在不久的将来发生变化。如果您有兴趣尝试使用http://desktopbeautifier.com/Main/contactus向我发送电子邮件,我会向您发送预建版本。

答案 5 :(得分:0)

如果有人在使用br.readline()为RXTX读取你的角色之后仍然得到java.io.IOException: Underlying input stream returned zero bytes(即使你先检查是否br.readline()== null),这个简单的修复与try / catch:

String line;
while (true){   
    try{
        line = br.readLine();
    }catch(IOException e){
        System.out.println("No more characters received");
        break;
    }
    //Print the line read
    if (line.length() != 0) 
        System.out.println(line);
}

我已经做了一些搜索,看起来这是解决这个问题的最好/最简单的方法。

编辑:我把它拿回来。我试过这个但仍然遇到了一些问题。我建议直接使用原始InputStream,并使用InputStream.read()实现自己的read / readLine方法。这对我有用。