Picses' sky

          Picses' sky
          posts - 43, comments - 29, trackbacks - 0, articles - 24

          一個(gè)嵌入式系統(tǒng)通常需要通過(guò)串口與其主控系統(tǒng)進(jìn)行全雙工通訊,譬如一個(gè)流水線
          控制系統(tǒng)需要不斷的接受從主控系統(tǒng)發(fā)送來(lái)的查詢和控制信息,并將執(zhí)行結(jié)果或查
          詢結(jié)果發(fā)送回主控系統(tǒng)。本文介紹了一個(gè)簡(jiǎn)單的通過(guò)串口實(shí)現(xiàn)全雙工通訊的Java類
          庫(kù),該類庫(kù)大大的簡(jiǎn)化了對(duì)串口進(jìn)行操作的過(guò)程。

          本類庫(kù)主要包括:SerialBean.java (與其他應(yīng)用程序的接口), SerialBuffer.java
          (用來(lái)保存從串口所接收數(shù)據(jù)的緩沖區(qū)), ReadSerial.java (從串口讀取數(shù)據(jù)的程序)。
          另外本類庫(kù)還提供了一個(gè)例程SerialExample.java 作為示范。在下面的內(nèi)容中將逐
          一對(duì)這幾個(gè)部分進(jìn)行詳細(xì)介紹。

          1. SerialBean

          SerialBean是本類庫(kù)與其他應(yīng)用程序的接口。該類庫(kù)中定義了SerialBean的構(gòu)造方
          法以及初始化串口,從串口讀取數(shù)據(jù),往串口寫(xiě)入數(shù)據(jù)以及關(guān)閉串口的函數(shù)。具體
          介紹如下:

          public SerialBean(int PortID)

          本函數(shù)構(gòu)造一個(gè)指向特定串口的SerialBean,該串口由參數(shù)PortID所指定。
          PortID = 1 表示COM1,PortID = 2 表示COM2,由此類推。

          public int Initialize()

          本函數(shù)初始化所指定的串口并返回初始化結(jié)果。如果初始化成功返回1,否
          則返回-1。初始化的結(jié)果是該串口被SerialBean獨(dú)占性使用,其參數(shù)被設(shè)置
          為9600, N, 8, 1。如果串口被成功初始化,則打開(kāi)一個(gè)進(jìn)程讀取從串口傳
          入的數(shù)據(jù)并將其保存在緩沖區(qū)中。

          public String ReadPort(int Length)

          本函數(shù)從串口(緩沖區(qū))中讀取指定長(zhǎng)度的一個(gè)字符串。參數(shù)Length指定所返
          回字符串的長(zhǎng)度。

          public void WritePort(String Msg)

          本函數(shù)向串口發(fā)送一個(gè)字符串。參數(shù)Msg是需要發(fā)送的字符串。

          public void ClosePort()

          本函數(shù)停止串口檢測(cè)進(jìn)程并關(guān)閉串口。

          SerialBean的源代碼如下:

          package serial;

          import java.io.*;
          import java.util.*;
          import javax.comm.*;

          /**
          *
          * This bean provides some basic functions to implement full dulplex
          * information exchange through the srial port.
          *
          */

          public class SerialBean
          {

          static String PortName;
          CommPortIdentifier portId;
          SerialPort serialPort;
          static OutputStream out;
          static InputStream in;

          SerialBuffer SB;
          ReadSerial RT;

          /**
          *
          * Constructor
          *
          * @param PortID the ID of the serial to be used. 1 for COM1,
          * 2 for COM2, etc.
          *
          */

          public SerialBean(int PortID)
          {
          PortName = "COM" + PortID;
          }

          /**
          *
          * This function initialize the serial port for communication. It starts a
          * thread which consistently monitors the serial port. Any signal captured
          * from the serial port is stored into a buffer area.
          *
          */

          public int Initialize()
          {

          int InitSuccess = 1;
          int InitFail = -1;

          try
          {

          portId = CommPortIdentifier.getPortIdentifier(PortName);

          try
          {
          serialPort = (SerialPort)
          portId.open("Serial_Communication", 2000);
          } catch (PortInUseException e)
          {
          return InitFail;
          }

          //Use InputStream in to read from the serial port, and OutputStream
          //out to write to the serial port.

          try
          {
          in = serialPort.getInputStream();
          out = serialPort.getOutputStream();
          } catch (IOException e)
          {
          return InitFail;
          }

          //Initialize the communication parameters to 9600, 8, 1, none.

          try
          {
          serialPort.setSerialPortParams(9600,
          SerialPort.DATABITS_8,
          SerialPort.STOPBITS_1,
          SerialPort.PARITY_NONE);
          } catch (UnsupportedCommOperationException e)
          {
          return InitFail;
          }
          } catch (NoSuchPortException e)
          {
          return InitFail;
          }

          // when successfully open the serial port, create a new serial buffer,
          // then create a thread that consistently accepts incoming signals from
          // the serial port. Incoming signals are stored in the serial buffer.

          SB = new SerialBuffer();
          RT = new ReadSerial(SB, in);
          RT.start();

          // return success information

          return InitSuccess;
          }

          /**
          *
          * This function returns a string with a certain length from the incoming
          * messages.
          *
          * @param Length The length of the string to be returned.
          *
          */

          public String ReadPort(int Length)
          {
          String Msg;
          Msg = SB.GetMsg(Length);
          return Msg;
          }

          /**
          *
          * This function sends a message through the serial port.
          *
          * @param Msg The string to be sent.
          *
          */

          public void WritePort(String Msg)
          {
          int c;
          try
          {
          for (int i = 0; i < Msg.length(); i++)
          out.write(Msg.charAt(i));
          } catch (IOException e) {}
          }

          /**
          *
          * This function closes the serial port in use.
          *
          */

          public void ClosePort()
          {
          RT.stop();
          serialPort.close();
          }
          }

          2. SerialBuffer

          SerialBuffer是本類庫(kù)中所定義的串口緩沖區(qū),它定義了往該緩沖區(qū)中寫(xiě)入數(shù)據(jù)和
          從該緩沖區(qū)中讀取數(shù)據(jù)所需要的函數(shù)。

          public synchronized String GetMsg(int Length)

          本函數(shù)從串口(緩沖區(qū))中讀取指定長(zhǎng)度的一個(gè)字符串。參數(shù)Length指定所
          返回字符串的長(zhǎng)度。

          public synchronized void PutChar(int c)

          本函數(shù)望串口緩沖區(qū)中寫(xiě)入一個(gè)字符,參數(shù)c 是需要寫(xiě)入的字符。

          在往緩沖區(qū)寫(xiě)入數(shù)據(jù)或者是從緩沖區(qū)讀取數(shù)據(jù)的時(shí)候,必須保證數(shù)據(jù)的同
          步,因此GetMsg和PutChar函數(shù)均被聲明為synchronized并在具體實(shí)現(xiàn)中采
          取措施實(shí)現(xiàn)的數(shù)據(jù)的同步。

          SerialBuffer的源代碼如下:

          package serial;

          /**
          *
          * This class implements the buffer area to store incoming data from the serial
          * port.
          *
          */

          public class SerialBuffer
          {
          private String Content = "";
          private String CurrentMsg, TempContent;
          private boolean available = false;
          private int LengthNeeded = 1;

          /**
          *
          * This function returns a string with a certain length from the incoming
          * messages.
          *
          * @param Length The length of the string to be returned.
          *
          */

          public synchronized String GetMsg(int Length)
          {
          LengthNeeded = Length;
          notifyAll();

          if (LengthNeeded > Content.length())
          {
          available = false;
          while (available == false)
          {
          try
          {
          wait();
          } catch (InterruptedException e) { }
          }
          }

          CurrentMsg = Content.substring(0, LengthNeeded);
          TempContent = Content.substring(LengthNeeded);
          Content = TempContent;
          LengthNeeded = 1;
          notifyAll();
          return CurrentMsg;
          }

          /**
          *
          * This function stores a character captured from the serial port to the
          * buffer area.
          *
          * @param t The char value of the character to be stored.
          *
          */

          public synchronized void PutChar(int c)
          {
          Character d = new Character((char) c);
          Content = Content.concat(d.toString());
          if (LengthNeeded < Content.length())
          {
          available = true;
          }
          notifyAll();
          }
          }

          3. ReadSerial

          ReadSerial是一個(gè)進(jìn)程,它不斷的從指定的串口讀取數(shù)據(jù)并將其存放到緩沖區(qū)中。

          public ReadSerial(SerialBuffer SB, InputStream Port)

          本函數(shù)構(gòu)造一個(gè)ReadSerial進(jìn)程,參數(shù)SB指定存放傳入數(shù)據(jù)的緩沖區(qū),參
          數(shù)Port指定從串口所接收的數(shù)據(jù)流。

          public void run()

          ReadSerial進(jìn)程的主函數(shù),它不斷的從指定的串口讀取數(shù)據(jù)并將其存放到
          緩沖區(qū)中。

          ReadSerial的源代碼如下:

          package serial;

          import java.io.*;

          /**
          *
          * This class reads message from the specific serial port and save
          * the message to the serial buffer.
          *
          */

          public class ReadSerial extends Thread
          {
          private SerialBuffer ComBuffer;
          private InputStream ComPort;

          /**
          *
          * Constructor
          *
          * @param SB The buffer to save the incoming messages.
          * @param Port The InputStream from the specific serial port.
          *
          */

          public ReadSerial(SerialBuffer SB, InputStream Port)
          {
          ComBuffer = SB;
          ComPort = Port;
          }

          public void run()
          {
          int c;
          try
          {
          while (true)
          {
          c = ComPort.read();
          ComBuffer.PutChar(c);
          }
          } catch (IOException e) {}
          }
          }

          4. SerialExample

          SerialExample是本類庫(kù)所提供的一個(gè)例程。它所實(shí)現(xiàn)的功能是打開(kāi)串口COM1,對(duì)
          其進(jìn)行初始化,從串口讀取信息對(duì)其進(jìn)行處理后將處理結(jié)果發(fā)送到串口。

          import serial.*;
          import java.io.*;

          /**
          *
          * This is an example of how to use the SerialBean. It opens COM1 and reads
          * six messages with different length form the serial port.
          *
          */

          class SerialExample
          {
          public static void main(String[] args)
          {
          //TO DO: Add your JAVA codes here

          SerialBean SB = new SerialBean(1);
          String Msg;

          SB.Initialize();
          for (int i = 5; i <= 10; i++)
          {
          Msg = SB.ReadPort(i);
          SB.WritePort("Reply: " + Msg);
          }
          SB.ClosePort();
          }
          }

          5. 編譯與調(diào)試

          本類庫(kù)中使用了Java Communication API (javax.comm)。這是一個(gè)Java擴(kuò)展類庫(kù),
          并不包括在標(biāo)準(zhǔn)的Java SDK當(dāng)中。如果你尚未安裝這個(gè)擴(kuò)展類庫(kù)的話,你應(yīng)該從Sun
          公司的Java站點(diǎn)下載這個(gè)類庫(kù)并將其安裝在你的系統(tǒng)上。在所下載的包里面包括一個(gè)
          安裝說(shuō)明,如果你沒(méi)有正確安裝這個(gè)類庫(kù)及其運(yùn)行環(huán)境的話,運(yùn)行這個(gè)程序的時(shí)候你
          會(huì)找不到串口。

          正確安裝Java Communication API并將上述程序編譯通過(guò)以后,你可以按如下方法測(cè)
          試這個(gè)程序。如果你只有一臺(tái)機(jī)器,你可以利用一條RS-232電纜將COM1和COM2連接起
          來(lái),在COM1上運(yùn)行SerialExample,在COM2上運(yùn)行Windows提供的超級(jí)終端程序。如果
          你有兩臺(tái)機(jī)器的話,你可以利用一條RS-232電纜將兩臺(tái)機(jī)器的COM1(或者是COM2)連接
          起來(lái),在一端運(yùn)行例程,另外一端運(yùn)行Windows提供的超級(jí)終端程序。如果有必要的
          話,可以對(duì)SerialExample中所聲明的串口進(jìn)行相應(yīng)改動(dòng)。

          本程序在Windows 2000 + Java SDK 1.3環(huán)境下編譯通過(guò)并成功運(yùn)行。

            以下是用Java讀取串口的程序。

          這個(gè)簡(jiǎn)單的程序包括以下文件:

                 IMU.java (主程序)
                 ReadBuffer.java (從緩沖區(qū)讀取一個(gè)消息)
                 ReadSerial.java (讀取串口數(shù)據(jù)并放入緩沖區(qū))
                 SerialBuffer.java (緩沖區(qū))
                 WriteSerial.java (不斷的往串口送星號(hào)'*')

          測(cè)試程序:

                 SendCom.java (將一個(gè)數(shù)據(jù)文件往串口發(fā)送)
                 SEND.TXT (供測(cè)試用的數(shù)據(jù)文件)

          在這個(gè)通訊程序中使用了一個(gè)簡(jiǎn)單的協(xié)議,既不同的消息之間用星號(hào)'*'作為分隔。這個(gè)程序中的問(wèn)題是ReadSerial進(jìn)程和WriteSerial進(jìn)程不能夠同時(shí)啟動(dòng),出錯(cuò)信息是不能夠打開(kāi)串口,因?yàn)橥瑯右粋€(gè)串口不能夠同時(shí)被打開(kāi)兩次(在ReadSerial中聲明了FileReader和在WriteSerial中聲明了FileWriter)。這樣是不能夠?qū)崿F(xiàn)全雙工通訊的。

          /*
          *
          * IMU.java 1.0
          * Main Program for Serial Communication
          *
          * Created: March 27, 2001
          *
          * Author : Qingye Jiang (John)
          * American GNC Corporation
          * 888 Easy St, Simi Valley CA 93065-1812
          *
          * Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)
          * qjiang@tsinghua.edu
          *
          */

          import java.io.*;

          class IMU
          {
                 public static void main(String[] args)
                 {
                         //TO DO: Add your JAVA codes here

                         File ComPort = new File("COM1");

                 SerialBuffer SB = new SerialBuffer();
                 ReadSerial r1 = new ReadSerial(SB, ComPort);
                 ReadBuffer r2 = new ReadBuffer(SB);
                 WriteSerial r3 = new WriteSerial(ComPort);

                 r1.start();
                 r2.start();
                 r3.start();
             }
          }

          /*
          *
          * ReadBuffer.java 1.0
          * Program to Read the Serial Buffer
          *
          * Created: March 27, 2001
          *
          * Author : Qingye Jiang (John)
          * American GNC Corporation
          * 888 Easy St, Simi Valley CA 93065-1812
          *
          * Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)
          * qjiang@tsinghua.edu

          *
          */

          import java.io.*;

          public class ReadBuffer extends Thread
          {
             private SerialBuffer ComBuffer;

             public ReadBuffer(SerialBuffer SB)
             {
                 ComBuffer = SB;
             }

             public void run()
             {
                         String Msg;

                 while (true)
                 {
                         Msg = ComBuffer.GetMsg();
                         System.out.println(Msg);
                 }

             }
          }

          /*
          *
          * ReadSerial.java 1.0
          * Program to read characters from the serial port and put it
          * to the buffer
          *
          * Created: March 27, 2001
          *
          * Author : Qingye Jiang (John)
          * American GNC Corporation
          * 888 Easy St, Simi Valley CA 93065-1812
          *
          * Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)
          *       qjiang@tsinghua.edu
          *
          */

          import java.io.*;

          public class ReadSerial extends Thread
          {
             private SerialBuffer ComBuffer;
             private File ComPort;

             public ReadSerial(SerialBuffer SB, File Port)
             {
                 ComBuffer = SB;
                 ComPort = Port;
             }

             public void run()
             {
                         int c;
                         try
                         {
                                 FileReader in = new FileReader(ComPort);

          while (true)
                     {
                         c = in.read();
                         ComBuffer.PutChar(c);
                     }
                         try
                         {
                                 FileReader in = new FileReader(ComPort);
                         while (true)
                     {
                         c = in.read();

                         ComBuffer.PutChar(c);
                     }
                 } catch (IOException e) {}
             }
          }


          /*
          *
          * SerialBuffer.java 1.0
          * Class that implements the serial buffer
          *
          * Created: March 27, 2001
          *
          * Author : Qingye Jiang (John)
          *   American GNC Corporation
          * 888 Easy St, Simi Valley CA 93065-1812
          *
          * Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)
          * qjiang@tsinghua.edu

          *
          */

          public class SerialBuffer
          {
             private String Content = "";
             private String CurrentMsg, TempContent;
             private boolean available = false;

             public synchronized String GetMsg()
             {
                 int SepMark;

                 if ((SepMark = Content.indexOf('*')) == -1)
                 {
                         available = false;
                         while (available == false)
                         {
                         try
                         {
                             wait();
                         } catch (InterruptedException e) { }
                         }
                         SepMark = Content.indexOf('*');
                 }

                 CurrentMsg = Content.substring(0, SepMark);
                 TempContent = Content.substring(SepMark+1);
                 Content = TempContent;
                 notifyAll();
                 return CurrentMsg;
             }

             public synchronized void PutChar(int c)
             {
                 Character d = new Character((char) c);
                 Content = Content.concat(d.toString());
                 if (c == '*')
                 {
                         available = true;
                 }
                 notifyAll();
             }
          }


          /*
          *
          * WriteSerial.java 1.0
          * Program to send a character to the serial port
          *
          * Created: March 27, 2001
          *
          * Author : Qingye Jiang (John)
          * American GNC Corporation
          * 888 Easy St, Simi Valley CA 93065-1812
          *
          * Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)
          * qjiang@tsinghua.edu
          *
          */

          import java.io.*;

          public class WriteSerial extends Thread
          {
             private SerialBuffer ComBuffer;
             private File ComPort;

             public WriteSerial(File Port)
             {
                 ComPort = Port;
             }

             public void run()
             {
                         int c;
                         try
                         {
                                 FileWriter out = new FileWriter(ComPort);
                         while (true)
                     {
                         out.write('*');
                     }
                 } catch (IOException e)
                 {
                         System.out.println(e.getMessage());
                 }
             }
          }


          import java.io.*;

          public class SendCom
          {
             public static void main(String[] args)
             {

                         File OutFile = new File("SEND.TXT");
                         File ComPort = new File("COM2");

                         int c;

                         try
                         {
                                 FileReader in = new FileReader(OutFile);
                                 FileWriter out = new FileWriter(ComPort);
                                 while ((c = in.read()) != -1)
                                         out.write(c);
                                 in.close();
                                 out.close();
                         } catch (IOException e) {}

                 }
          }

           

          SEND.TXT*

          This is a sample of the data file for program testing. *

          It should be in the same directory as the SendCom.class file.*

          When you run this sample program, connect your COM1 and COM2 with a
          serial cable so that you can test this program on one machine. If
          you have two machines, you can connect the two machine via a serial
          cable and test it. Modified the definition of ComPort in the program
          if necessary. *

          Thank you for testing this program. If you have any suggestions please
          kindly let me know. *



          這是一個(gè)通過(guò)JAVA的擴(kuò)展包(javax.comm)從串口讀取值的類,
            本類庫(kù)(javax.comm)主要包括:
           SerialBean.java (與其他應(yīng)用程序的接口),
           SerialBuffer.java (用來(lái)保存從串口所接收數(shù)據(jù)的緩沖區(qū)),
           ReadSerial.java (從串口讀取數(shù)據(jù)的程序)。


           整個(gè)類的設(shè)計(jì)思路大概就是:
           實(shí)現(xiàn)一個(gè)線程一直在監(jiān)聽(tīng)串口中是否有數(shù)據(jù)傳送過(guò)來(lái),
           如果有的話開(kāi)始拍照,并取得照片后,直接打印出來(lái)。因?yàn)樯婕暗缴虡I(yè)秘密,所以拍照函數(shù)和取得照片函數(shù)采用的是空函數(shù),請(qǐng)見(jiàn)諒!
           若要運(yùn)行此函數(shù)必須下載該擴(kuò)展包,并加載到你的CLASSPATH下。當(dāng)然,你若要測(cè)試并運(yùn)行此類的話。可能要花費(fèi)不少的精力。
           如果你只有一臺(tái)機(jī)器,你可以利用一條RS-232電纜將COM1和COM2連接起來(lái),在COM1上運(yùn)行SerialExample,在COM2上運(yùn)行Windows提供的超級(jí)終端程序。
           如果你有兩臺(tái)機(jī)器的話,你可以利用一條RS-232電纜將兩臺(tái)機(jī)器的COM1(或者是COM2)連接起來(lái),在一端運(yùn)行例程,另外一端運(yùn)行Windows提供的超級(jí)終端程序。
           
          該類有相當(dāng)詳細(xì)的注釋。我想應(yīng)該不難理解吧!

          import java.io.*;
          import java.awt.*;
          import java.awt.print.*;
          import javax.print.*;
          import javax.comm.*; //這是一個(gè)Java擴(kuò)展類庫(kù),并不包括在標(biāo)準(zhǔn)的Java SDK當(dāng)中。
          //如果你尚未安裝這個(gè)擴(kuò)展類那么你需要到sun公司的Java站點(diǎn)下載這個(gè)類庫(kù)

          class SuanKou implements Runnable{
            private java.io.FileOutputStream fos=null;
            private Thread th=null;
            private long shiJian=500;//設(shè)置間隔的時(shí)間
             //private int duanKou=1;//設(shè)置端口號(hào)
             private String Msg = null;
             private SerialBean SB=null;
             private int isSucces=-1;
           
             //構(gòu)造函數(shù)
            public SuanKou(long sj,int dk) {
              System.out.println("構(gòu)造函數(shù)");
              try{
              fos=new java.io.FileOutputStream("c:\\log.txt");
             
              this.shiJian=sj;//設(shè)定監(jiān)聽(tīng)端口的時(shí)間
             
              //this.duanKou=dk;//端口號(hào)
             
              SB = new SerialBean(dk);//創(chuàng)建一個(gè)接口對(duì)象,參數(shù)為端口號(hào)
             
             isSucces = SB.Initialize();//初使化所指定的串口并返回初始化結(jié)果。如果初始化成功返回1,否則返回-1
            
              th=new Thread(this);//創(chuàng)建一個(gè)線程對(duì)象
            
              th.start();//創(chuàng)建SuanKou這個(gè)對(duì)象就開(kāi)始啟動(dòng)線程
           }catch(java.io.FileNotFoundException fe){
            fe.printStackTrace();
           }catch(Exception e){
            e.printStackTrace();
           }
            }

          //拍照函數(shù)
            public void snape() {
              System.out.println("拍照函數(shù)");
            }

          //取得照片函數(shù)
            public void getPicture() {
              System.out.println("取得照片函數(shù)");

            }
           
            //實(shí)現(xiàn)線程接口的RUN方法
            public void run(){
              Thread.sleep(shiJian);
              this.ReadSuanKou();
            }
           
            //定期到串口讀取數(shù)據(jù)和函數(shù),如果能讀到數(shù)據(jù)就調(diào)用snape(),getPicture(),函數(shù),寫(xiě)日志,打印
            private void ReadSuanKou() {
            
             //如果初使化成功的話,
              if (isSucces == 1) {
              
                //從串口(緩沖區(qū))中讀取指定長(zhǎng)度的一個(gè)字符串。(500)
               
                try{
                
                Msg = SB.ReadPort(500);

                //如果可以從串口讀到數(shù)據(jù)的話

                if (Msg != null) {
                  this.snape();//調(diào)用拍照函數(shù)
                 
                  this.getPicture();//調(diào)用取得照片函數(shù)
                 
                  java.text.SimpleDateFormat df=new java.text.SimpleDateFormat("EEEE-MMMM-dd-yyyy");

           Date date=new Date();

           String dateFormat=df.format(date);
           
                  fos.write(dateFormat.getBytes());//在日志文件中記錄當(dāng)前時(shí)間
                 
                  fos.write(Msg.getBytes());//將讀到的數(shù)據(jù)寫(xiě)到日志文件中
           
            //調(diào)用打印方法 注:若要打印,要打印的對(duì)象必須實(shí)現(xiàn)java.awt.print.Printable接口。即getPicture
           
            //返回的對(duì)象必須實(shí)現(xiàn)該接口,因?yàn)椴恢纆etPicture返回什么對(duì)象,故這個(gè)打印功能無(wú)法實(shí)現(xiàn),不過(guò)大概的思路是
           
            /** 1,需要一個(gè)打印服務(wù)對(duì)象。這可通過(guò)三種方式實(shí)現(xiàn):
                在jdk1.4之前的版本,必須要實(shí)現(xiàn)java.awt.print.Printable接口
                或通過(guò)Toolkit.getDefaultToolkit().getPrintJob來(lái)獲取打印服務(wù)對(duì)象;
                在jdk1.4中則還可以通過(guò)javax.print.PrintSerivceLookup來(lái)查找定位一個(gè)打印服務(wù)對(duì)象。

                            2、需要開(kāi)始一個(gè)打印工作。這也有幾種實(shí)現(xiàn)方法:在jdk1.4之前可以通過(guò)java.awt.print.PrintJob
             (jdk1.1提供的,現(xiàn)在已經(jīng)很少用了)調(diào)用print或printAll方法開(kāi)始打印工作;
             也可以通過(guò)java.awt.print.PrinterJob的printDialog顯示打印對(duì)話框,
             然后通過(guò)print方法開(kāi)始打印;在jdk1.4中則可以通過(guò)javax.print.ServiceUI的printDialog顯示打印對(duì)話框,
             然后調(diào)用print方法開(kāi)始一個(gè)打印工作。
           
            根據(jù)以上的提示去做,不會(huì)很難!
            */
           
            java.awt.print.PrinterJob pj=new java.awt.print.PrinterJob();
           
            pj.printDialog();//顯示打印對(duì)話框
            pj.print();//開(kāi)始打印
           
                }

                //SB.WritePort("OK");若要向串口返回一個(gè)結(jié)果可以調(diào)用該函數(shù)?

               
           }catch(Exception e){
           
            e.printStackTrace();

           }finally{
            try{
             fos.close();
              //停止串口檢測(cè)進(jìn)程并關(guān)閉串口。
                  SB.ClosePort();
               
            }catch(Exception e){
             e.printStackTrace();
            }
           }

              }
              else {
                throw RuntimeException("讀取串口數(shù)據(jù)時(shí)出錯(cuò)!");
              }

            }

           

            //主函數(shù)
            public static void main(String args[]) {
            
              new SuanKou(1000,1);//參數(shù)為間隔的時(shí)間,和端口號(hào)


            }
          }


           

          關(guān)鍵字:   Java Comm 串口    

          本人因?yàn)轫?xiàng)目開(kāi)發(fā)的需要,需要PC機(jī)和硬件的通訊,而這個(gè)通訊通過(guò)Comm串口實(shí)現(xiàn),而最好又是全雙工的通訊,譬如一個(gè)流水線控制系統(tǒng)需要不斷的接受從主控系統(tǒng)發(fā)送來(lái)的查詢和控制信息,并將執(zhí)行結(jié)果或查詢結(jié)果發(fā)送回主控系統(tǒng)。本文介紹了一個(gè)簡(jiǎn)單的通過(guò)串口實(shí)現(xiàn)全雙工通訊的Java類庫(kù),該類庫(kù)大大的簡(jiǎn)化了對(duì)串口進(jìn)行操作的過(guò)程。
          本類庫(kù)主要包括:SerialBean.java (與其他應(yīng)用程序的接口), SerialBuffer.java (用來(lái)保存從串口所接收數(shù)據(jù)的緩沖區(qū)), ReadSerial.java (從串口讀取數(shù)據(jù)的程序)。另外本類庫(kù)還提供了一個(gè)例程SerialExample.java 作為示范。在下面的內(nèi)容中將逐一對(duì)這幾個(gè)部分進(jìn)行詳細(xì)介紹。
          1. SerialBean
          SerialBean是本類庫(kù)與其他應(yīng)用程序的接口。該類庫(kù)中定義了SerialBean的構(gòu)造方法以及初始化串口,從串口讀取數(shù)據(jù),往串口寫(xiě)入數(shù)據(jù)以及關(guān)閉串口的函數(shù)。具體介紹如下:
          public SerialBean(int PortID)
          本函數(shù)構(gòu)造一個(gè)指向特定串口的SerialBean,該串口由參數(shù)PortID所指定。PortID = 1 表示COM1,PortID = 2 表示COM2,由此類推。
          public int Initialize()
          本函數(shù)初始化所指定的串口并返回初始化結(jié)果。如果初始化成功返回1,否則返回-1。初始化的結(jié)果是該串口被SerialBean獨(dú)占性使用,其參數(shù)被設(shè)置為9600, N, 8, 1。如果串口被成功初始化,則打開(kāi)一個(gè)進(jìn)程讀取從串口傳入的數(shù)據(jù)并將其保存在緩沖區(qū)中。
          public String ReadPort(int Length)
          本函數(shù)從串口(緩沖區(qū))中讀取指定長(zhǎng)度的一個(gè)字符串。參數(shù)Length指定所返回字符串的長(zhǎng)度。
          public void WritePort(String Msg)
          本函數(shù)向串口發(fā)送一個(gè)字符串。參數(shù)Msg是需要發(fā)送的字符串。
          public void ClosePort()
          本函數(shù)停止串口檢測(cè)進(jìn)程并關(guān)閉串口。
          2. SerialBuffer
          SerialBuffer是本類庫(kù)中所定義的串口緩沖區(qū),它定義了往該緩沖區(qū)中寫(xiě)入數(shù)據(jù)和從該緩沖區(qū)中讀取數(shù)據(jù)所需要的函數(shù)。
          public synchronized String GetMsg(int Length)
          本函數(shù)從串口(緩沖區(qū))中讀取指定長(zhǎng)度的一個(gè)字符串。參數(shù)Length指定所返回字符串的長(zhǎng)度。
          public synchronized void PutChar(int c)
          本函數(shù)望串口緩沖區(qū)中寫(xiě)入一個(gè)字符,參數(shù)c 是需要寫(xiě)入的字符。
          在往緩沖區(qū)寫(xiě)入數(shù)據(jù)或者是從緩沖區(qū)讀取數(shù)據(jù)的時(shí)候,必須保證數(shù)據(jù)的同步,因此GetMsg和PutChar函數(shù)均被聲明為synchronized并在具體實(shí)現(xiàn)中采取措施實(shí)現(xiàn)的數(shù)據(jù)的同步。
          3. ReadSerial
          ReadSerial是一個(gè)進(jìn)程,它不斷的從指定的串口讀取數(shù)據(jù)并將其存放到緩沖區(qū)中。
          public ReadSerial(SerialBuffer SB, InputStream Port)
          本函數(shù)構(gòu)造一個(gè)ReadSerial進(jìn)程,參數(shù)SB指定存放傳入數(shù)據(jù)的緩沖區(qū),參數(shù)Port指定從串口所接收的數(shù)據(jù)流。
          public void run()
          ReadSerial進(jìn)程的主函數(shù),它不斷的從指定的串口讀取數(shù)據(jù)并將其存放到緩沖區(qū)中。
          4. SerialExample
          SerialExample是本類庫(kù)所提供的一個(gè)例程。它所實(shí)現(xiàn)的功能是打開(kāi)串口COM1,對(duì)其進(jìn)行初始化,從串口讀取信息對(duì)其進(jìn)行處理后將處理結(jié)果發(fā)送到串口。
          5. 編譯與調(diào)試
          本類庫(kù)中使用了Java Communication API (javax.comm)。這是一個(gè)Java擴(kuò)展類庫(kù),并不包括在標(biāo)準(zhǔn)的Java SDK當(dāng)中。如果你尚未安裝這個(gè)擴(kuò)展類庫(kù)的話,你應(yīng)該從Sun公司的Java站點(diǎn)下載這個(gè)類庫(kù)并將其安裝在你的系統(tǒng)上。在所下載的包里面包括一個(gè)安裝說(shuō)明,如果你沒(méi)有正確安裝這個(gè)類庫(kù)及其運(yùn)行環(huán)境的話,運(yùn)行這個(gè)程序的時(shí)候你會(huì)找不到串口。
          正確安裝Java Communication API并將上述程序編譯通過(guò)以后,你可以按如下方法測(cè)試這個(gè)程序。如果你只有一臺(tái)機(jī)器,你可以利用一條RS-232電纜將COM1和COM2連接起來(lái),在COM1上運(yùn)行SerialExample,在COM2上運(yùn)行Windows提供的超級(jí)終端程序。如果你有兩臺(tái)機(jī)器的話,你可以利用一條RS-232電纜將兩臺(tái)機(jī)器的COM1(或者是COM2)連接起來(lái),在一端運(yùn)行例程,另外一端運(yùn)行Windows提供的超級(jí)終端程序。如果有必要的話,可以對(duì)SerialExample中所聲明的串口進(jìn)行相應(yīng)改動(dòng)。
          本程序在Windows 2000 + Java SDK 1.3環(huán)境下編譯通過(guò)并成功運(yùn)行。

          如想要這幾個(gè)文件的原代碼,請(qǐng)留言,而且也能幫忙調(diào)試,因?yàn)殛P(guān)鍵在環(huán)境部署上,不能出錯(cuò)。

          應(yīng)廣大讀者的需要,本人把代碼簡(jiǎn)單做了整理,特意發(fā)出來(lái)讓大家相互學(xué)習(xí)!

          本文介紹一個(gè)利用Java Comm API (javax.comm)實(shí)現(xiàn)串口全雙工通訊的簡(jiǎn)單程序。這個(gè)程序首先打開(kāi)并初始化一個(gè)串口,然后啟動(dòng)如下三個(gè)進(jìn)程:ReadSerial進(jìn)程從該串口讀取數(shù)據(jù)并放入緩沖區(qū),ReadBuffer進(jìn)程從緩沖區(qū)讀取數(shù)據(jù)并打印到屏幕, WriteSerial進(jìn)程每5秒鐘向該串口發(fā)送一個(gè)星號(hào)(*)。

          在這個(gè)示例程序中使用了一個(gè)簡(jiǎn)單的協(xié)議,既不同的消息之間用星號(hào)'*'作為分隔。緩沖區(qū)程序根據(jù)是否收到星號(hào)作為存在等待處理的消息的判斷依據(jù)。

          Java Comm API不是標(biāo)準(zhǔn)的Java API,因此的標(biāo)準(zhǔn)的運(yùn)行環(huán)境中并不提供這個(gè)包。如果你的系統(tǒng)上還沒(méi)有安裝這個(gè)包,你可以從SUN公司的網(wǎng)站下載。在這個(gè)包里面有一個(gè)安裝指南,如果你沒(méi)有正確安裝這個(gè)包,可能你不能夠正確運(yùn)行這個(gè)例程。

          這個(gè)簡(jiǎn)單的例程包括以下文件:

          IMU.java (主程序)
          ReadBuffer.java (從緩沖區(qū)讀取一個(gè)消息)
          ReadSerial.java (讀取串口數(shù)據(jù)并放入緩沖區(qū))
          SerialBuffer.java (緩沖區(qū))
          WriteSerial.java (每5秒鐘往串口送一個(gè)星號(hào)'*')

          測(cè)試程序:

          SendCom.java (將一個(gè)數(shù)據(jù)文件往串口發(fā)送)
          SEND.TXT (供測(cè)試用的數(shù)據(jù)文件)

          測(cè)試方法:

          1 正確安裝Java Comm API后編譯本例程
          2 將計(jì)算機(jī)的COM1和COM2用一條串口線連接起來(lái)
          3 運(yùn)行IMU。如果你這時(shí)候打開(kāi)Windows自帶的超級(jí)終端并連接到COM2的話,你應(yīng)該能夠看見(jiàn)有星號(hào)出現(xiàn)在超級(jí)終端的屏幕上。超級(jí)終端的參數(shù)設(shè)置為9600, N, 8, 1, none。
          4 關(guān)閉超級(jí)終端,運(yùn)行SendCom。這時(shí)候你應(yīng)該能夠從IMU的屏幕上看到數(shù)據(jù)文件里面的內(nèi)容。

          /*
          *
          * IMU.java 1.0
          * Main Program for Serial Communication
          *
          * Created: March 27, 2001
          *
          * Author : Qingye Jiang (John)
          * American GNC Corporation
          * 888 Easy St, Simi Valley CA 93065-1812
          *
          * Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)
          * qjiang@tsinghua.edu
          *
          */

          import java.io.*;
          import java.util.*;
          import javax.comm.*;

          class IMU
          {

          static CommPortIdentifier portId;
          static SerialPort serialPort;
          static OutputStream out;
          static InputStream in;

          public static void main(String[] args)
          {

          try
          {

          //Declare the serial port, and open it.

          portId = CommPortIdentifier.getPortIdentifier("COM1");
          try
          {

          serialPort = (SerialPort) portId.open("IMU_App", 2000);

          } catch (PortInUseException e)
          {

          System.out.println(e.getMessage());

          }

          //Use InputStream in to read from the serial port, and OutputStream
          //out to write to the serial port.

          try
          {

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

          } catch (IOException e)
          {

          System.out.println(e.getMessage());

          }

          //Initialize the communication parameters to 9600, 8, 1, none.

          try
          {

          serialPort.setSerialPortParams(9600,
                        SerialPort.DATABITS_8,
                        SerialPort.STOPBITS_1,
                        SerialPort.PARITY_NONE);

          } catch (UnsupportedCommOperationException e)
          {

          System.out.println(e.getMessage());

          }

          } catch (NoSuchPortException e)
          {

          System.out.println(e.getMessage());

          }

          //Declare the serial buffer area, a thread to read from the seriial port,
          //a thread to read from the serial buffer for processing, and a thread
          //to write to the serial port.

          SerialBuffer SB = new SerialBuffer();
          ReadSerial r1 = new ReadSerial(SB, in);
          ReadBuffer r2 = new ReadBuffer(SB);
          WriteSerial r3 = new WriteSerial(out);

          //Start all three threads.

          r1.start();
          r2.start();
          r3.start();

          }

          }

          /*
          *
          * SerialBuffer.java 1.0
          * Class that implements the serial buffer
          *
          * Created: March 27, 2001
          *
          * Author : Qingye Jiang (John)
          * American GNC Corporation
          * 888 Easy St, Simi Valley CA 93065-1812
          *
          * Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)
          * qjiang@tsinghua.edu
          *
          */

          public class SerialBuffer
          {

          private String Content = "";
          private String CurrentMsg, TempContent;
          private boolean available = false;


          //read a message from the serial buffer. The star character '*' is used
          //as the seperation mark between different messages.

          public synchronized String GetMsg()
          {

          int SepMark;

          if ((SepMark = Content.indexOf('*')) == -1)
          {

          available = false;
          while (available == false)
          {

          try
          {
                  wait();
          } catch (InterruptedException e) { }

          }
          SepMark = Content.indexOf('*');

          }

          CurrentMsg = Content.substring(0, SepMark);
          TempContent = Content.substring(SepMark+1);
          Content = TempContent;
          notifyAll();
          return CurrentMsg;

          }

          //Put a character to the serial buffer

          public synchronized void PutChar(int c)
          {

          Character d = new Character((char) c);
          Content = Content.concat(d.toString());
          if (c == '*')
          {
                  available = true;
          }
          notifyAll();

          }

          }

          /*
          *
          * ReadSerial.java 1.0
          * Program to read characters from the serial port and put it
          * to the buffer
          *
          * Created: March 27, 2001
          *
          * Author : Qingye Jiang (John)
          * American GNC Corporation
          * 888 Easy St, Simi Valley CA 93065-1812
          *
          * Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)
          * qjiang@tsinghua.edu
          *
          */

          import java.io.*;

          public class ReadSerial extends Thread
          {

          private SerialBuffer ComBuffer;
          private InputStream ComPort;

          public ReadSerial(SerialBuffer SB, InputStream Port)
          {
                  ComBuffer = SB;
                  ComPort = Port;
          }

          public void run()
          {

          int c;
          try
          {

          while (true)
          {
                  c = ComPort.read();
                  ComBuffer.PutChar(c);
          }

          } catch (IOException e) {}

          }

          }

          /*
          *
          * ReadBuffer.java 1.0
          * Program to Read the Serial Buffer
          *
          * Created: March 27, 2001
          *
          * Author : Qingye Jiang (John)
          * American GNC Corporation
          * 888 Easy St, Simi Valley CA 93065-1812
          *
          * Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)
          * qjiang@tsinghua.edu
          *
          */

          import java.io.*;

          public class ReadBuffer extends Thread
          {

          private SerialBuffer ComBuffer;

          public ReadBuffer(SerialBuffer SB)
          {
                  ComBuffer = SB;
          }

          public void run()
          {

          String Msg;
          while (true)
          {
                  Msg = ComBuffer.GetMsg();
                  System.out.println(Msg);
          }

          }

          }

          /*
          *
          * WriteSerial.java 1.0
          * Program to send a star to the serial port every 5 seconds.
          *
          * Created: March 27, 2001
          *
          * Author : Qingye Jiang (John)
          * American GNC Corporation
          * 888 Easy St, Simi Valley CA 93065-1812
          *
          * Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)
          * qjiang@tsinghua.edu
          *
          */

          import java.io.*;

          public class WriteSerial extends Thread
          {

          private SerialBuffer ComBuffer;
          private OutputStream ComPort;

          public WriteSerial(OutputStream Port)
          {
                  ComPort = Port;
          }

          public void run()
          {

          int c;
          try
          {

          while (true)
          {

          ComPort.write('*');
          try
          {
                  wait(5000);
          } catch (InterruptedException e) { }

          }

          } catch (IOException e)
          {
                  System.out.println(e.getMessage());
          }

          }

          }

          /*
          *
          * SendCom.java 1.0
          *
          * Project: Java Based Information Exchange Support System
          * Onboard Plug-in System
          * Sending data through serial port
          *
          * Created: March 15, 2001
          *
          * Author : Qingye Jiang (John)
          * American GNC Corporation
          * 888 Easy St, Simi Valley CA 93065-1812
          *
          * Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)
          *
          */

          import java.io.*;

          public class SendCom
          {

          public static void main(String[] args)
          {

          File OutFile = new File("SEND.TXT");
          File ComPort = new File("COM2");

          int c;

          try
          {

          FileReader in = new FileReader(OutFile);
          FileWriter out = new FileWriter(ComPort);
          while ((c = in.read()) != -1)
                  out.write(c);
          in.close();
          out.close();

          } catch (IOException e) {}

          }

          }

          SEND.TXT*

          This is a sample of the data file for program testing. *

          It should be in the same directory as the SendCom.class file.*

          When you run this sample program, connect your COM1 and COM2 with a
          serial cable so that you can test this program on one machine. If
          you have two machines, you can connect the two machine via a serial
          cable and test it. Modified the definition of ComPort in the program
          if necessary. *

          Thank you for testing this program. If you have any suggestions please
          kindly let me know. *

          小結(jié):

          在上面的例程中,大多數(shù)的程序僅對(duì)我前天發(fā)的《一個(gè)使用Java讀取串口的程序》
          一文做了小篇幅的改動(dòng),有幾個(gè)程序和數(shù)據(jù)文件都沒(méi)有改動(dòng)。但是為了本文的完整
          性,仍然將雷同的內(nèi)容也貼了一遍,還望斑竹多多見(jiàn)諒。

          這個(gè)例程和前面一個(gè)例程的區(qū)別在于前面一個(gè)例程使用了文件IO,而本例程使用了
          Comm API。在C語(yǔ)言里面用fopen()函數(shù)來(lái)打開(kāi)串口是可讀也可寫(xiě)的,但是在Java里
          面聲明了File以后并不立即打開(kāi)文件,文件是在聲明FileReader或者FileWriter時(shí)
          才打開(kāi)的。由于串口不能同時(shí)被打開(kāi)兩次,所以讀操作和寫(xiě)操作不能夠同時(shí)進(jìn)行,
          不能夠?qū)崿F(xiàn)全雙工通訊。

          Comm API雖然能夠?qū)崿F(xiàn)全雙工通訊,但是由于它不是標(biāo)準(zhǔn)的Java API,代碼的可移
          植性難以保證。如果程序并不要求實(shí)現(xiàn)全雙工的話,我認(rèn)為利用文件操作不失為一
          個(gè)好辦法。


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 靖江市| 宁远县| 丹凤县| 平顶山市| 嘉鱼县| 宜昌市| 泰宁县| 前郭尔| 太和县| 崇阳县| 璧山县| 德州市| 安阳市| 普安县| 田东县| 晋宁县| 定边县| 大埔区| 体育| 南和县| 迁安市| 武功县| 元阳县| 伊川县| 蒙城县| 广西| 博爱县| 武安市| 湄潭县| 福安市| 奈曼旗| 梅州市| 临江市| 中超| 通山县| 广宁县| 囊谦县| 饶阳县| 建瓯市| 合山市| 永城市|