目次

テストアプリケーション

 複数のボードを作成したので、各ボードをテストする
 環境が必要になりました。

 C#で、お手軽に作ろうとしましたが、大阪に持参する
 ノートPCのHD容量が小さいので、スクリプトを記述し
 インタプリタで動作させられる、Javaを使うことに。

 Javaでコードを作成するのは、10年以上振りだったため
 1日でできる予定が、2日かかってしまいました。

 Javaは、クラスを定義し、それらを組み合わせることで
 動作させるので、ハードウエアと同じように箱を作成し
 動作を考えます。



 TeraTermをイメージし、操作を考えるためにGUIを
 スケッチして決めました。



 シリアルポートの番号は、利用コンピュータで変わる
 ので、COM1〜COM8から選択できるようにします。

 データ転送速度は、38400bpsで固定ですが、こちらも
 4800、9600、19200、38400、57600から選べるように
 定義しました。

 操作画面が決まったので、最初のクラスを定義します。

    import java.awt.*;
    import java.awt.event.*;

    import javax.swing.*;
    import javax.swing.event.*;

    import gnu.io.*;
    import java.io.*;

    public class McrTst
    {
      private final static int my_frm_width  = 500 ;
      private final static int my_frm_height = 500 ;

      public static void main(String args[])
      {
        MFrame frame = new MFrame();
        // 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // set dimension
        frame.setSize(my_frm_width,my_frm_height);
        // show
        frame.setVisible(true);
      }
    }

 Cと同じように、mainとなる関数を定義し、他のクラスの
 メソッドを利用して、おしまいです。

 ウィンドウを用意し、右上にあるXをクリックすると
 終了する仕様を採用しました。


 シリアル通信に関連するクラスを、自作するのは大変
 なので、RXTXクラスをダウンロードして利用します。

 RXTXクラスのメソッドを利用して、最もマイコンに近い
 部分を抽象化しました。

 クラスを定義するので、実現したい機能を考えます。

 データ受信は、割込み(Javaだとlistenerですが)を利用
 しなければならないので、別クラスで実現します。

 機能を絞って、DTBクラスを定義しました。

    class DtbC
    {
      SerialPort         port;
      CommPortIdentifier comID;

      String comName;
      int    baudRate;

      InputStream  in;
      OutputStream out;
      // open method
      boolean rs_open(String Com_Name,int Baud_Rate)
      {
        comName = Com_Name;
        baudRate = Baud_Rate;
        // get port ID
        try {
          comID = CommPortIdentifier.getPortIdentifier(comName);
        } catch(Exception e) {
          JOptionPane.showMessageDialog(null,"Do not nortify !","DtbC.open()",JOptionPane.INFORMATION_MESSAGE);
          return false;
        }
        // already opened
        if ( comID.isCurrentlyOwned() == false ) {
          try { 
            // generate instance
            port = (SerialPort)comID.open("DTB",2000);
            // baud rate , data length , stop bit , parity 
            port.setSerialPortParams(baudRate,SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE );
            // no flow control
            port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
            // input and output stream
            in = port.getInputStream();
            out = port.getOutputStream();
          } catch(Exception e) {
            JOptionPane.showMessageDialog(null,"Do not open !","DtbC.rs_open()",JOptionPane.INFORMATION_MESSAGE);
            return false;
          }
        } else {
          JOptionPane.showMessageDialog(null,"Already opened !","DtbC.rs_open()",JOptionPane.INFORMATION_MESSAGE);
          return false;
        }
        return true;
      }
      // close method 
      boolean rs_close()
      {
        if ( comID.isCurrentlyOwned() ) {
          try {
            port.close();
            in.close();
            out.close();
          } catch(IOException e) {
            JOptionPane.showMessageDialog(null,"Do not close !","DtbC.rs_close()",JOptionPane.INFORMATION_MESSAGE);
            return false;
          }
        } else {
          JOptionPane.showMessageDialog(null,"Already closed !","DtbC.rs_close()",JOptionPane.INFORMATION_MESSAGE);
          return false; 
        }
        return true;
      }
      // send string
      void Serial_puts(String str)
      {
        byte[] data = str.getBytes();
        try {
          out.write(data);
          out.flush();
        } catch(Exception e) {
        }
      }
    }

 ポートオープンとクローズは、既に開いている、閉じて
  いる場合を考え、try..catchで定義しました。

 文字列送信は、OutputStreamを用意して、その中にある
 文字列を、RXTXのwriteメソッドで出力します。

 データ送受信が楽になるように、InputStream、OutputStreamで
 エンドポイントを用意します。

 シリアルの通信に関連するクラスを定義したので
 シリアル処理を単純にすると同時に、上位クラス
 の負担軽減用ミドルウエアを考えます。

    class Serial_Class extends DtbC
    {
      JComboBox   cbxCom;
      JComboBox   cbxBaud;
      JTextArea   edtText;
      JScrollPane scrPane;
      // constructor
      Serial_Class()
      {
        // generate text area
        edtText = new JTextArea();
        // generate scroll pane
        scrPane = new JScrollPane(edtText);
        scrPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        scrPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        // COM port ComboBox
        cbxCom = new JComboBox();
        cbxCom.addItem("COM1"); cbxCom.addItem("COM2");
        cbxCom.addItem("COM3"); cbxCom.addItem("COM4");
        cbxCom.addItem("COM5"); cbxCom.addItem("COM6");
        cbxCom.addItem("COM7"); cbxCom.addItem("COM8");
        // default port
        cbxCom.setSelectedItem("COM6");
        // Buad rate ComboBox
        cbxBaud = new JComboBox();
        cbxBaud.addItem("4800") ; cbxBaud.addItem("9600");
        cbxBaud.addItem("19200"); cbxBaud.addItem("38400");
        cbxBaud.addItem("57600");
        // default baud rate
        cbxBaud.setSelectedItem("38400");
      }
      // open method
      void open()
      {
        boolean flag;
        // convert COM name to string
        String COM_Name = (cbxCom.getSelectedItem()).toString();
        // get baud rate from ComboBox
        int Baud_Rate = Integer.parseInt((cbxBaud.getSelectedItem()).toString());
        // open 
        flag = rs_open(COM_Name,Baud_Rate);
        // success
        if ( flag ) {
          try {
            // register receive event handler
            port.addEventListener(new SerialPortListener());
            // add event monitor
            port.notifyOnDataAvailable(true);
          } catch(Exception e) {
          }
          edtText.append("Connected\n");
        }
      }
      // close method
      void close()
      {
        boolean flag;
        // close 
        flag = rs_close();
        // success
        if ( flag ) { edtText.append("Disconnected\n"); }
      }
      // event listener
      class SerialPortListener implements SerialPortEventListener
      {
        // event handler
        public void serialEvent(SerialPortEvent Serial_event)
        {
          StringBuffer buffer = new StringBuffer();
          int received_data = 0 ;
          // receive completed 
          if ( Serial_event.getEventType() == SerialPortEvent.DATA_AVAILABLE ) {
          // loop until get 'break'
            while (true) {
              try {
                // get data from input stream
                received_data = in.read();
                // no charactor
                if ( received_data == -1 ) break;
                // store
                if ( (char)received_data != '\r' ) {
                  buffer.append((char)received_data);
                } else {
                // get delimiter
                  // convert 
                  edtText.append(buffer.toString());
                  // clear buffer
                  buffer.delete(0,buffer.length()-1); 
                  // post handling
                  edtText.setCaretPosition(edtText.getText().length());
                  //break;
                }
              } catch(IOException ex){
              }
            }
          }
        }
      }
    }

 コンストラクタで、コンボボックスを生成し
 COMポート番号選択、ボーレート選択ができる
 ようにします。

 さらに、テキストエリアを用意して、送受信の
 内容を表示できるようにします。

 クラスメソッドを利用する側の負担が減るように
 open、closeを用意します。
 openメソッドでは、COMポート番号、ボーレートを
 確定して、DTBクラスのメソッドにパラメータを
 渡します。

 受信データを、テキストエリアに表示するため
 SerialPortEventListenerで、DTBクラスが入力した
 データを、転送する仕掛けを入れました。

 受信データは、'\r'で1区切りと判断しています。

 Serialクラスを定義したので、GUIを担当するフレーム
 クラスを定義します。

 コンストラクタで、GUIに必要なComboBox、Label、Buttonを
 パネルに貼付けていきます。また、パネルは、フレームの中
 に入れるようにします。

 ボタンは、COMポートのオープン、クローズに利用します。
 ボタン操作に関係するイベント処理は、Actionを利用して
 捉まえます。

 マイコンボードに転送するデータを、キーボードから入力
 できるようにします。このとき、'\r'をつけるため、仮想
 キー入力をEnterにバインドします。
 また、キー入力はKeyAdapterクラスのサブクラスになる
 クラスを定義して対応します。

 ここまで考えた仕様をまとめます。

    class MFrame extends JFrame
    {
      Serial_Class serial; 
      // constructor
      MFrame()
      {
        // call super class method
        super("MCR machine test");

        serial = new Serial_Class();
        // generate pane
        JPanel cp = new JPanel();
        // set layout moe
        cp.setLayout(null);
        // add pane to frame
        setContentPane(cp);
        // generate scroll pane
        JScrollPane sp = new JScrollPane(serial.edtText);
        // enable vertical scroll bar
        sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        sp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        // set scroll pane dimension
        sp.setBounds(50,50,400,300);
        // add scroll pane
        cp.add(sp);
        // show COM port
        JLabel com_label = new JLabel("COM port:");
        cp.add(com_label);
        com_label.setBounds(50,20,100,20);
        cp.add(serial.cbxCom);
        serial.cbxCom.setBounds(120,20,80,20);
        // show selected baud rate
        JLabel baud_label = new JLabel("Baud rate : ");
        cp.add(baud_label);
        baud_label.setBounds(250,20,100,20);
        cp.add(serial.cbxBaud);
        serial.cbxBaud.setBounds(350,20,80,20);
        // generate Font
        Font font = new Font("SansSerif",Font.PLAIN,16);
        // add Font information to textarea。
        serial.edtText.setFont(font);
        serial.edtText.setLineWrap(true);
        serial.edtText.addKeyListener(new KeyInput());
        serial.scrPane.setBounds(50,50,400,300);
        cp.add(serial.scrPane);
        // define button
        JButton btnConnect = new JButton(new open_action());
        btnConnect.setBounds(50,400,150,40);
        cp.add(btnConnect);
        JButton btnDisconnect = new JButton(new close_action());
        btnDisconnect.setBounds(300,400,150,40);
        cp.add(btnDisconnect);
        // register KeyInput class to KeyListener
        serial.edtText.addKeyListener(new KeyInput());
      }
      // internal class (bntConnect)
      class open_action extends AbstractAction
      {
        // constructor
        open_action()
        {
          putValue(Action.NAME,"\nConnect");
        }
        // event method
        public void actionPerformed(ActionEvent btnConnect_act)
        {
          serial.open();
        }
      }
      // internal class (bntDisconnect)
      class close_action extends AbstractAction
      {
        // constructor
        close_action()
        {
          putValue(Action.NAME,"\nDisconnect");
        }
        // event method
        public void actionPerformed(ActionEvent btnDisconnect_act)
        {
          serial.close();
        }
      }
      // key event
      class KeyInput extends KeyAdapter
      {
        String   stmp;
        String[] stmp_array;
        int lineNum;

        public void keyPressed(KeyEvent e)
        {
          // get key then echo to textArea
          if ( e.getKeyCode() == KeyEvent.VK_ENTER ) {
            //serial.edtText.append("\n");
            stmp = serial.edtText.getText();
            stmp_array = stmp.split("\n",0);
            lineNum = stmp_array.length - 1;
            // send serial port
            serial.Serial_puts(stmp_array[lineNum]+"\r");
          }
        }
      }
    }


ソースコード

 4つのクラスを、一つのファイルにまとめてみると  次のようになります。 import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import gnu.io.*; import java.io.*; // internal Device Test Box class class DtbC { SerialPort port; CommPortIdentifier comID; String comName; int baudRate; InputStream in; OutputStream out; // open method boolean rs_open(String Com_Name,int Baud_Rate) { comName = Com_Name; baudRate = Baud_Rate; // get port ID try { comID = CommPortIdentifier.getPortIdentifier(comName); } catch(Exception e) { JOptionPane.showMessageDialog(null,"Do not nortify !","DtbC.open()",JOptionPane.INFORMATION_MESSAGE); return false; } // already opened if ( comID.isCurrentlyOwned() == false ) { try { // generate instance port = (SerialPort)comID.open("DTB",2000); // baud rate , data length , stop bit , parity port.setSerialPortParams(baudRate,SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE ); // no flow control port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE); // input and output stream in = port.getInputStream(); out = port.getOutputStream(); } catch(Exception e) { JOptionPane.showMessageDialog(null,"Do not open !","DtbC.rs_open()",JOptionPane.INFORMATION_MESSAGE); return false; } } else { JOptionPane.showMessageDialog(null,"Already opened !","DtbC.rs_open()",JOptionPane.INFORMATION_MESSAGE); return false; } return true; } // close method boolean rs_close() { if ( comID.isCurrentlyOwned() ) { try { port.close(); in.close(); out.close(); } catch(IOException e) { JOptionPane.showMessageDialog(null,"Do not close !","DtbC.rs_close()",JOptionPane.INFORMATION_MESSAGE); return false; } } else { JOptionPane.showMessageDialog(null,"Already closed !","DtbC.rs_close()",JOptionPane.INFORMATION_MESSAGE); return false; } return true; } // send string void Serial_puts(String str) { byte[] data = str.getBytes(); try { out.write(data); out.flush(); } catch(Exception e) { } } } // internal Serial Class (super class => DtbC) class Serial_Class extends DtbC { JComboBox cbxCom; JComboBox cbxBaud; JTextArea edtText; JScrollPane scrPane; // constructor Serial_Class() { // generate text area edtText = new JTextArea(); // generate scroll pane scrPane = new JScrollPane(edtText); scrPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); scrPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); // COM port ComboBox cbxCom = new JComboBox(); cbxCom.addItem("COM1"); cbxCom.addItem("COM2"); cbxCom.addItem("COM3"); cbxCom.addItem("COM4"); cbxCom.addItem("COM5"); cbxCom.addItem("COM6"); cbxCom.addItem("COM7"); cbxCom.addItem("COM8"); // default port cbxCom.setSelectedItem("COM6"); // Buad rate ComboBox cbxBaud = new JComboBox(); cbxBaud.addItem("4800") ; cbxBaud.addItem("9600"); cbxBaud.addItem("19200"); cbxBaud.addItem("38400"); cbxBaud.addItem("57600"); // default baud rate cbxBaud.setSelectedItem("38400"); } // open method void open() { boolean flag; // convert COM name to string String COM_Name = (cbxCom.getSelectedItem()).toString(); // get baud rate from ComboBox int Baud_Rate = Integer.parseInt((cbxBaud.getSelectedItem()).toString()); // open flag = rs_open(COM_Name,Baud_Rate); // success if ( flag ) { try { // register receive event handler port.addEventListener(new SerialPortListener()); // add event monitor port.notifyOnDataAvailable(true); } catch(Exception e) { } edtText.append("Connected\n"); } } // close method void close() { boolean flag; // close flag = rs_close(); // success if ( flag ) { edtText.append("Disconnected\n"); } } // event listener class SerialPortListener implements SerialPortEventListener { // event handler public void serialEvent(SerialPortEvent Serial_event) { StringBuffer buffer = new StringBuffer(); int received_data = 0 ; // receive completed if ( Serial_event.getEventType() == SerialPortEvent.DATA_AVAILABLE ) { // loop until get 'break' while (true) { try { // get data from input stream received_data = in.read(); // no charactor if ( received_data == -1 ) break; // store if ( (char)received_data != '\r' ) { buffer.append((char)received_data); } else { // get delimiter // convert edtText.append(buffer.toString()); // clear buffer buffer.delete(0,buffer.length()-1); // post handling edtText.setCaretPosition(edtText.getText().length()); //break; } } catch(IOException ex){ } } } } } } // internal Frame (window) class class MFrame extends JFrame { Serial_Class serial; // constructor MFrame() { // call super class method super("MCR machine test"); serial = new Serial_Class(); // generate pane JPanel cp = new JPanel(); // set layout moe cp.setLayout(null); // add pane to frame setContentPane(cp); // generate scroll pane JScrollPane sp = new JScrollPane(serial.edtText); // enable vertical scroll bar sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); sp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); // set scroll pane dimension sp.setBounds(50,50,400,300); // add scroll pane cp.add(sp); // show COM port JLabel com_label = new JLabel("COM port:"); cp.add(com_label); com_label.setBounds(50,20,100,20); cp.add(serial.cbxCom); serial.cbxCom.setBounds(120,20,80,20); // show selected baud rate JLabel baud_label = new JLabel("Baud rate : "); cp.add(baud_label); baud_label.setBounds(250,20,100,20); cp.add(serial.cbxBaud); serial.cbxBaud.setBounds(350,20,80,20); // generate Font Font font = new Font("SansSerif",Font.PLAIN,16); // add Font information to textarea。 serial.edtText.setFont(font); serial.edtText.setLineWrap(true); serial.edtText.addKeyListener(new KeyInput()); serial.scrPane.setBounds(50,50,400,300); cp.add(serial.scrPane); // define button JButton btnConnect = new JButton(new open_action()); btnConnect.setBounds(50,400,150,40); cp.add(btnConnect); JButton btnDisconnect = new JButton(new close_action()); btnDisconnect.setBounds(300,400,150,40); cp.add(btnDisconnect); // register KeyInput class to KeyListener serial.edtText.addKeyListener(new KeyInput()); } // internal class (bntConnect) class open_action extends AbstractAction { // constructor open_action() { putValue(Action.NAME,"\nConnect"); } // event method public void actionPerformed(ActionEvent btnConnect_act) { serial.open(); } } // internal class (bntDisconnect) class close_action extends AbstractAction { // constructor close_action() { putValue(Action.NAME,"\nDisconnect"); } // event method public void actionPerformed(ActionEvent btnDisconnect_act) { serial.close(); } } // key event class KeyInput extends KeyAdapter { String stmp; String[] stmp_array; int lineNum; public void keyPressed(KeyEvent e) { // get key then echo to textArea if ( e.getKeyCode() == KeyEvent.VK_ENTER ) { //serial.edtText.append("\n"); stmp = serial.edtText.getText(); stmp_array = stmp.split("\n",0); lineNum = stmp_array.length - 1; // send serial port serial.Serial_puts(stmp_array[lineNum]+"\r"); } } } } public class McrTst { private final static int my_frm_width = 500 ; private final static int my_frm_height = 500 ; public static void main(String args[]) { MFrame frame = new MFrame(); // frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // set dimension frame.setSize(my_frm_width,my_frm_height); // show frame.setVisible(true); } }

コンパイル、リンク、実行

 JavaSEのJDKをダウンロードし、インストールしておけば  コンパイル、リンクは単純です。  コンパイル、リンクは次のように入力します。 javac McrTst.java{enter}  実行は、以下です。 java McrTst{enter}  GUIの操作をしてみます。  ボタンクリックで、マイコンに接続します。  キーボードから'?'を入力し、マイコンからの返信を  表示します。  GameBoyCameraに撮影させて、画像データをシリアル  転送しているところです。  ボタンクリックで、マイコンを切断します。  簡単なテストアプリケーションですが  ハードウエアとファームウエアのバグ  を叩出すのに、充分役に立ちました。
目次

inserted by FC2 system