2013-11-23 3 views
1

Я использую RXTX для связи между JAVA и микроконтроллером.java rxtx SerialWriter issue

Это 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"; и даже не входит внутрь метода run() SerialWriter.

У вас есть идеи, почему это происходит? Со стороны моего микроконтроллера нет проблем, я проверил все возможности с помощью инструмента.

Надеюсь, я ясно дал понять.

Спасибо!

LE: Я забыл тела вам, что это не бросайте какую-либо ошибки или исключение

ответ

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(); 

, скорее всего, заканчивается I ts осуществление после отправки первый str.

Честно говоря, я не понимаю, как он даже отправляет одну строку, так как str инициализируется нулевым на первом месте и должен выкинуть NullPointerException по адресу str.length().

Я хотел бы предложить вам этот подход:

  • Не инициирующая поток записи, когда установлено соединение, просто вызвать новый, каждый раз, когда сообщение будет отправлено.
  • Правильно используйте шаблон Singleton.
  • Держите ссылку на последовательный порт в классе 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"); 
0

tzortzik,

Я думаю, что это проблема с таймаутом. Попробуйте addding задержку к писателю:

/** */ 
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 

Надеюсь, это может вам помочь.

 Смежные вопросы

  • Нет связанных вопросов^_^