Windows下利用Javax.comm實現對串口的讀寫

來源:互聯網
上載者:User
Windows下利用Javax.comm實現對串口的讀寫

Javax.comm簡介
    Javax.comm是Sun公司提供的,用於開發平台獨立的通訊應用程式的擴充API。(ps:這裡javax的x很準確地表明了它是一個擴充包,而不是核心包(core package),但由於曆史原因,javax下的並不都是擴充包,比如swing包已經是Java核心架構的一部分了,不過為了與Java1.1編碼相容,仍使用javax.swing。)javax.comm可以訪問RS232介面(串口)及有限制地訪問IEEE-1284(並口)。

下載
    需要到其官方首頁http://java.sun.com/products/javacomm/下載這個API,目前的最新版本是3.0。不過可惜的是,Sun目前沒有推出此API在Windows平台下的3.0版本,首頁上列出的三個版本,分別是運行在x86和Sparc結構下的Solaris系統,以及x86下的Linux系統。要下載Windows版本只能去尋找較老的版本了。我所找到的2個網址是http://llk.media.mit.edu/projects/cricket/software/javaSerial.zip(兩個檔案夾裡面有所需的3個檔案),http://mdubuc.freeshell.org/Jolt/javacomm20-win32.zip和(完整的2.0版本,還有examples)。

安裝
    這裡的所謂安裝就是把三個重要的檔案放到指定的目錄下。
    將下載的檔案解壓縮後,在/javacomm20-win32/commapi目錄下有必需的三個檔案comm.jar,javax.comm. properties和win32comm.dll。將檔案comm.jar拷貝到%JAVA_HOME%/jre/lib/ext;檔案javax.comm. properties拷貝到%JAVA_HOME%/jre/lib; 檔案win32comm.dll拷貝到%JAVA_HOME%/bin。注意%JAVA_HOME%是jdk的路徑,而非jre。

API
在javax.comm下有13個類和介面,分別是

4個介面
CommDriver 可負載裝置(the loadable device)驅動程式介面的一部分
CommPortOwnershipListener 傳遞各種通訊連接埠的所有權事件
ParallelPortEventListener 傳遞並行連接埠事件
SerialPortEventListener 傳遞序列埠事件

6個類
CommPort 通訊連接埠
CommPortIdentifier通訊連接埠管理
ParallelPort 並行通訊連接埠
ParallelPortEvent 並行連接埠事件
SerialPort RS-232串列通訊連接埠
SerialPortEvent 序列埠事件

3個異常類
NoSuchPortException 當驅動程式不能找到指定連接埠時拋出
PortInUseException 當碰到指定連接埠正在使用中時拋出
UnsupportedCommOperationException 驅動程式不允許指定操作時拋出

執行個體
    同API一起下載的還有一個examples檔案,裡面有6個程式。首先看最簡單的讀、寫程式。

讀串口的常式
import java.io.*;
import java.util.*;
import javax.comm.*;

public class SimpleRead implements Runnable, SerialPortEventListener {

    static CommPortIdentifier portId;
    static Enumeration portList;//枚舉類

    InputStream inputStream;
    SerialPort serialPort;
    Thread readThread;

    public static void main(String[] args) {

        portList = CommPortIdentifier.getPortIdentifiers();/*不帶參數的getPortIdentifiers方法獲得一個枚舉對象,該對象又包含了系統中管理每個連接埠的CommPortIdentifier對象。注意這裡的連接埠不僅僅是指串口,也包括並口。這個方法還可以帶參數。getPortIdentifiers(CommPort)獲得與已經被應用程式開啟的連接埠相對應的CommPortIdentifier對象。getPortIdentifier(String portName)擷取指定連接埠名(比如“COM1”)的CommPortIdentifier對象。*/

        while (portList.hasMoreElements()) {
            portId = (CommPortIdentifier) portList.nextElement();
            if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL)/*getPortType方法返回連接埠類型*/ {
                // if (portId.getName().equals("COM1"))/* 找Windows下的第一個串口*/ {
                if (portId.getName().equals("/dev/term/a"))/*找Unix-like系統下的第一個串口*/ {
                    SimpleRead reader = new SimpleRead();
                }
            }
        }
    }

    public SimpleRead() {
        try {
            serialPort = (SerialPort) portId.open("SimpleReadApp", 2000);/* open方法開啟通訊連接埠,獲得一個CommPort對象。它使程式獨佔連接埠。如果連接埠正被其他應用程式佔用,將使用CommPortOwnershipListener事件機制,傳遞一個PORT_OWNERSHIP_REQUESTED事件。每個連接埠都關聯一個InputStream 何一個OutputStream。如果連接埠是用open方法開啟的,那麼任何的getInputStream都將返回相同的資料流對象,除非有close被調用。有兩個參數,第一個為應用程式名稱;第二個參數是在連接埠開啟時阻塞等待的毫秒數。*/
        } catch (PortInUseException e) {}
        try {
            inputStream = serialPort.getInputStream();/*擷取連接埠的輸入資料流對象*/
        } catch (IOException e) {}
    try {
            serialPort.addEventListener(this);/*註冊一個SerialPortEventListener事件來監聽串口事件*/
    } catch (TooManyListenersException e) {}

        serialPort.notifyOnDataAvailable(true);/*資料可用*/

        try {
            serialPort.setSerialPortParams(9600,
                SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1,
                SerialPort.PARITY_NONE);/*設定串口初始化參數,依次是傳輸速率,資料位元,停止位和校正*/
        } catch (UnsupportedCommOperationException e) {}

        readThread = new Thread(this);
        readThread.start();
    }

    public void run() {
        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {}
    }

//串口事件
    public void serialEvent(SerialPortEvent event) {

        switch(event.getEventType()) {
        case SerialPortEvent.BI:/*Break interrupt,通訊中斷*/
        case SerialPortEvent.OE:/*Overrun error,溢位錯誤*/
        case SerialPortEvent.FE:/*Framing error,傳幀錯誤*/
        case SerialPortEvent.PE:/*Parity error,校正錯誤*/
        case SerialPortEvent.CD:/*Carrier detect,偵測載波*/
        case SerialPortEvent.CTS:/*Clear to send,清除發送*/
        case SerialPortEvent.DSR:/*Data set ready,資料裝置就緒*/
        case SerialPortEvent.RI:/*Ring indicator,響鈴指示*/
        case SerialPortEvent.OUTPUT_BUFFER_EMPTY:/*Output buffer is empty,輸出緩衝區清空*/
            break;

        case SerialPortEvent.DATA_AVAILABLE:/*Data available at the serial port,連接埠有可用資料。讀到緩衝數組,輸出到終端*/
            byte[] readBuffer = new byte[20];

            try {
                while (inputStream.available() > 0) {
                    int numBytes = inputStream.read(readBuffer);
                }
                System.out.print(new String(readBuffer));
            } catch (IOException e) {}
            break;
        }
    }
}
(PS:不推薦Thread的這種用法,詳見《Core Java VolumeII》)

寫串口的常式
    把字串"Hello, world!/n"寫到系統的第一個串口

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

public class SimpleWrite {
    static Enumeration portList;
    static CommPortIdentifier portId;
    static String messageString = "Hello, world!/n";
    static SerialPort serialPort;
    static OutputStream outputStream;

    public static void main(String[] args) {
        portList = CommPortIdentifier.getPortIdentifiers();

        while (portList.hasMoreElements()) {
            portId = (CommPortIdentifier) portList.nextElement();
            if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                // if (portId.getName().equals("COM1")) {
                if (portId.getName().equals("/dev/term/a")) {
                    try {
                        serialPort = (SerialPort)
                            portId.open("SimpleWriteApp", 2000);
                    } catch (PortInUseException e) {}
                    try {
                        outputStream = serialPort.getOutputStream();
                    } catch (IOException e) {}
                    try {
                        serialPort.setSerialPortParams(9600,
                            SerialPort.DATABITS_8,
                            SerialPort.STOPBITS_1,
                            SerialPort.PARITY_NONE);
                    } catch (UnsupportedCommOperationException e) {}
                    try {
                        outputStream.write(messageString.getBytes());
                    } catch (IOException e) {}
                }
            }
        }
    }
}

    上面兩個常式都經過了簡化,在開啟連接埠,並且傳輸結束後沒有關閉資料流和串口。在常式中我們看到CommPortIdentifier提供了開啟通訊連接埠的方法open,但卻沒有相應關閉連接埠的方法,關閉連接埠需要調用javax.comm.CommPort類的close()。CommPort是這個包中的一個進階抽象,它定義了連接埠可作的各種事情:擷取I/O資料流對象,控制緩衝區大小,調整輸入的處理。 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.