【问题标题】:Issues receiving in RXTXRXTX 接收问题
【发布时间】:2009-09-08 00:23:55
【问题描述】:

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

问题

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

但是,当我运行我编写的用于诊断主应用程序问题的简单超级终端克隆时,根据 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 发送了一堆本应得到响应的命令后打开超级终端时,所有响应都会立即出现,就好像它们已被放入缓冲区中的某个地方,但不可用。

编辑 2:尝试了新的东西,结果相同

我运行了找到here 的代码示例,结果相同。没有数据进来,但是当我切换到一个新程序时,它一下子就进来了。

编辑 3

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

我也开始使用PortMon,它给了我一些有趣的结果。超级终端和 RXTX 没有使用相同的设置,并且 RXTX 总是轮询端口,这与超级终端不同,但我仍然看不到哪些设置会影响这一点。一旦我可以将配置与持续轮询隔离开来,我就会发布我的 PortMon 日志。

编辑 4

是否有可能是过去 3 个月内的某种 Windows 更新导致了这种情况?它曾经把我的一个基于 MATLAB mex 的程序搞砸了。

编辑 5

我还注意到超级终端、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

【问题讨论】:

    标签: java serial-port rxtx


    【解决方案1】:

    好的,抱歉,我花了这么长时间才回到这个问题。以下是我如何让事情发挥作用的方法。

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

    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. 一旦你有一个 SerialPort 对象,调用setFlowControlMode() 方法,并按位或('|')必要的SerialPort.FLOWCONTROL_ 常量
    2. 将适当的流控制设置为 true 或 false(就像我对 port.setRTS(true) 所做的那样)

    对于其他有类似问题的人,如果这不起作用,我建议

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

    【讨论】:

    • @drhorrible 我看到您如何在串行端口对象上设置流控制。这很清楚。但是我想弄清楚您是如何检测到已发送流控制字符的?我像你一样使用 XON XOFF 与 RTS。但是我认为它应该是相似的。 0x13,0x11 是我希望在触发的 serialEvent 中看到的字符吗?您是如何在代码中检测到这一点的?
    • @ril3y 我不记得见过流控制字符。在 Serial Port Monitor 或 PortMon(答案中的链接)中,我在窗口的右下方看到一组红色和绿色的圆圈,其中一个是 CTS,另一个是 XON/XOFF。当一切正常时,它们是绿色的。否则,它们是红色的。
    • 哦,非常感谢详细的解决方案。我花了整整两天的时间来调试它,但我终于有了一个修复。
    【解决方案2】:

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

    BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String line;
    
        while (keepRunning) {
            try {
                while ((br.ready()) && (line = br.readLine()) != null) {
    ....
    }
    

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        (可能太简单了,但不妨从某个地方开始……)

        端口在使用中吗?而不是:

        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?
        }
        

        你是否吞下了任何异常?

        【讨论】:

        • 谢谢,但是 connect() 方法的其余部分会捕获所有这些异常并打印堆栈跟踪并终止。
        【解决方案5】:

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

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

        2. 在我看来,RXTX 的设计是有缺陷的,它的实现也有很多错误(看看它的源代码,真是一团糟!)。我在http://kenai.com/projects/jperipheral 上发布了一个替代库,其中包含以下警告:它仅适用于 Windows,并且没有预构建的二进制文件。这两者都将在不久的将来发生变化。如果您有兴趣试用它,请使用http://desktopbeautifier.com/Main/contactus 给我发送电子邮件,我会向您发送预构建版本。

        【讨论】:

        【解决方案6】:

        如果在您使用 br.readline() 读取字符后,如果有人仍然收到java.io.IOException: Underlying input stream returned zero bytes RXTX(即使您首先检查是否 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 方法。这对我有用。

        【讨论】:

          猜你喜欢
          • 2012-06-02
          • 1970-01-01
          • 2011-07-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多