【问题标题】:java rxtx SerialWriter issuejava rxtx SerialWriter 问题
【发布时间】:2013-11-23 21:43:02
【问题描述】:

我正在使用 RXTX 在 JAVA 和微控制器之间进行通信。

这是打开连接,发送和接收数据的JAVA代码

package app;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class SerialCommunication1 {
    private static SerialCommunication1 instance = null;
    private static boolean coonected = false;

    public static SerialCommunication1 getInstance(){
        if(instance == null)
            instance = new SerialCommunication1();
        return instance;
    }

    private SerialCommunication1() {
        super();
        try {
            connect("COM4");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        SerialCommunication1.coonected = true;
    }

    void connect(String portName) throws Exception {
        CommPortIdentifier portIdentifier = CommPortIdentifier
                .getPortIdentifier(portName);
        if (portIdentifier.isCurrentlyOwned()) {
            System.out.println("Error: Port is currently in use");
        } else {
            CommPort commPort = portIdentifier.open(this.getClass().getName(),
                    2000);

            if (commPort instanceof SerialPort) {
                SerialPort serialPort = (SerialPort) commPort;
                serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8,
                        SerialPort.STOPBITS_2, SerialPort.PARITY_NONE);

                InputStream in = serialPort.getInputStream();
                OutputStream out = serialPort.getOutputStream();

                (new Thread(new SerialReader(in))).start();
                (new Thread(new SerialWriter(out))).start();

            } else {
                System.out
                        .println("Error: Only serial ports are handled by this example.");
            }
        }
    }

    /** */
    public static class SerialReader implements Runnable {
        InputStream in;

        public SerialReader(InputStream in) {
            this.in = in;
        }

        public void run() {
            byte[] buffer = new byte[1024];
            int len = -1;
            try {
                while ((len = this.in.read(buffer)) > -1) {
                    System.out.print(new String(buffer, 0, len));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /** */
    public static class SerialWriter implements Runnable {
        OutputStream out;
        static String str = null;

        public SerialWriter(OutputStream out) {
            this.out = out;
        }

        public void run() {
            System.out.println("Will try to execute");
            try {
                if(str.length() > 0){
                    this.out.write(str.getBytes());
                    str = null;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

这是触发事件时调用的 Java 代码

SerialCommunication1.getInstance();
if(ledStatus == true) {SerialCommunication1.SerialWriter.str = "4A01";}
else {SerialCommunication1.SerialWriter.str = "4A00";}
stopProcess();

现在问题来了。我需要使用代码 4A01 向我的微控制器发送一个命令,在收到答案后,我需要使用代码 4A00 再次调用它。这些调用是由我的 Java 界面中的一个按钮触发的。问题是没有执行第二个调用(4A00 没有发送)。我试图反转命令代码,它们运行良好。执行第一个(4A01)后,我的微控制器做出反应并发送由java读取的响应,并且我的界面被更新。当我发送 invers 命令 (4A00) 时,它恰好停在这一行 SerialCommunication1.SerialWriter.str = "4A00"; 处,甚至没有进入 SerialWriter 的 run() 方法。

你知道为什么会这样吗?从我的微控制器方面来说没有问题,我用工具检查了所有可能性。

我希望我说清楚了。

谢谢!

LE:我忘了告诉你它没有抛出任何错误或异常

【问题讨论】:

    标签: java serial-port rxtx


    【解决方案1】:

    我不确定,因为我无法测试您的代码,但我认为您的问题出在 SerialWriter 类中:

    public static class SerialWriter implements Runnable {
        OutputStream out;
        static String str = null; // Here str is initialized to null
    
        public SerialWriter(OutputStream out) {
            this.out = out;
        }
    
        public void run() {
            System.out.println("Will try to execute");
            try {
                if(str.length() > 0) { // this should throw NPE because str is null
                    this.out.write(str.getBytes());
                    str = null;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    由于该方法中没有循环,那么在SerialCommunication1中创建的线程在这一行:

    (new Thread(new SerialWriter(out))).start();
    

    很可能在发送第一个str 后完成它的执行。

    老实说,我什至不明白它是如何发送单个字符串的,因为 str 首先被初始化为 null,它应该在 str.length() 行抛出 NullPointerException

    我建议你采用这种方法:

    • 建立连接时不要触发写入线程,每次发送消息时都触发一个新线程。
    • 正确使用单例模式。
    • SerialCommunication1 类中保留对串行端口的引用。

    翻译成代码是这样的:

    class SerialWriter implements Runnable {
        OutputStream out;
        String message;
    
        public SerialWriter(OutputStream out) {
            this.out = out;
        }
    
        public void setMessage(String msg) {
            this.message = msg;
        }
    
        public void run() {
            try {
                if(message != null) {
                    this.out.write(str.getBytes());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    然后在SerialCommunication1类中添加这个公共方法:

    public void sendMessage(String msg) {
        SerialWriter writer = new SerialWriter(serialPort.getOutputStream()); // of course you'll have to keep reference to serialPort when connection is established
        writer.setMessage(msg);
        (new Thread(writer)).start();
    }
    

    最后这样调用这个方法:

    SerialCommunication1.getInstance().sendMessage("4A01");
    

    【讨论】:

      【解决方案2】:

      zortzik,

      我认为这是一个超时问题。尝试为 writer 添加延迟:

      /** */
      public static class SerialWriter implements Runnable {
          OutputStream out;
          static String str = null;
      
          public SerialWriter(OutputStream out) {
              this.out = out;
          }
      
          public void run() {
              Thread.sleep(500); //<-----------  this should be in mainThread before to SerialWriter.start();
              System.out.println("Will try to execute");
              try {
                  if(str.length() > 0){
                      this.out.write(str.getBytes());
                      str = null;
                  }
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
      

      这件事发生在我身上很多次,“我们应该学会等待回应”(^_^)

      检查你是否很好地执行了类似下一个的secuence:

      Send command 4A01
      Receive response 4A01 from micro
      
      WAIT FOR RESPONSE BEFORE SEND SECOND COMMAND. Thread.sleep(500); //wait for 500 milis or more
      
      Send command 4A00
      Receive response 4A00 from micro
      

      希望对你有帮助。

      【讨论】:

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