Java USB串口編程(64位和32位)

      最近公司的項目需要和硬件打交道,而我負責硬件對接這塊的主要工作,這幾天把java中的串口編程熟悉了下,其中大多是涉及到環境的配置,接下來我把自己做的過程中遇到的問題整理一下,供大家產考!

      大至的應用場景是這樣的,終端設備(簡稱DTU)通過USB連接到主機上,主機上通過Java 的串口程序把數據發送到DTU,dtu配置好轉發服務器的ip和端口號,這樣主機的數據就可以直接發送至服務器了,可能有人會問爲什麼不直接發送至服務器,因爲我們的應用場景中主機是不可以聯網的。

1.USB端口連接電腦

Usb端口在連接電腦的過程中,打開桌面搜索“設備管理”,查看是否有Usb的端口,

根據電腦的連接設備情況,一般會有一道多個端口,我們只需要記住我們需要的端口就可以了,這裏我們記錄下com4端口即可,但是也有情況是USB插入以後設備管理並沒有識別,是因爲沒有安裝相應的驅動,這個時候我們需要安裝驅動:usb-serial controller驅動,下載安裝即可。

2.win7 32位環境配置

首先我們是在32位的程序下測試,我們需要下載一個安裝包,即javacomm20-win32.zip,下載以後如圖所試

主要用到的是這幾個文件,comm.jar,javax.commm.properties,win32com.dll
comm.jar放在[java-home]/jdk/bin/
javax.commm.propertie 放在 [java-home]/jdk/lib/
comm.jar 放在 [java-home]/jdk/lib/
對應的也放在jre對應的目錄下,至此,在32位系統下的環境配置就已經結束了。

3.32位系統測試

 
<span style="font-size:14px;">SimpleWrite.java</span>
<span style="font-size:14px;">package comm32;
import java.io.*;
import java.util.*;
import javax.comm.*;

public class SimpleWrite {
    static Enumeration portList;
    static CommPortIdentifier portId;
    static String messageString = "Hello, world00000000000000000000000000000!\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) {
            	
            	System.out.println(portId.getName());
            	
                 if (portId.getName().equals("COM4")) {
                    try {
                        serialPort = (SerialPort)
                            portId.open("SimpleWriteApp", 2000);
                    } catch (PortInUseException e) {}
                    try {
                        outputStream = serialPort.getOutputStream();
                    } catch (IOException e) {}
                    try {
                        serialPort.setSerialPortParams(115200,
                            SerialPort.DATABITS_8,
                            SerialPort.STOPBITS_1,
                            SerialPort.PARITY_NONE);
                    } catch (UnsupportedCommOperationException e) {}
                    try {
                        outputStream.write(messageString.getBytes());
                        System.out.println("ok");
                    } catch (IOException e) {}
                }
            }
        }
    }
}</span>

其中需要注意的是com4,以及setSerialPortParams方法中第一個參數115200指的是波特率,運行程序,Hello, world00000000000000000000000000000!就已經通過端口發送了!



4.win7 64位環境配置

首先下載:RXTX的包,(僅64位有效)Rxtx開源包下載地址:1、把rxtxParallel.dll、rxtxSerial.dll拷貝到:C:\WINDOWS\system32下。
2、如果是在開發的時候(JDK),需要把RXTXcomm.jar、rxtxParallel.dll、rxtxSerial.dll拷貝到..\jre...\lib\ext下;如:D:\Program Files\Java\jre1.6.0_02\lib\ext
3、而且需要把項目1.右鍵->2.Preperties(首選項)->3.Java Build Path->4.Libraries->5.展開RXTXcomm.jar->6.Native library location:(None)->
7.瀏覽External Folder(選擇至該項目的lib文件夾,如:E:/Item/MyItem/WebRoot/WEB-INF/lib).

package comme64;
import gnu.io.*;
import java.io.*; 
import java.util.*;  
 
 
public class SerialReader extends Observable implements Runnable,SerialPortEventListener
    {
    static CommPortIdentifier portId;
    int delayRead = 100;
    int numBytes; // 
    private static byte[] readBuffer = new byte[1024]; //
    static Enumeration portList;
    InputStream inputStream;
    OutputStream outputStream;
    static SerialPort serialPort;
    HashMap serialParams;
    Thread readThread;
   
    boolean isOpen = false;
   
    public static final String PARAMS_DELAY = "delay read"; // 
    public static final String PARAMS_TIMEOUT = "timeout"; // 超時時間
    public static final String PARAMS_PORT = "port name"; // 端口名稱
    public static final String PARAMS_DATABITS = "data bits"; //
    public static final String PARAMS_STOPBITS = "stop bits"; //
    public static final String PARAMS_PARITY = "parity"; // 奇偶校驗
    public static final String PARAMS_RATE = "rate"; // 


    public boolean isOpen(){
    <span style="white-space:pre">	</span>return isOpen;
    }
    /**
     * 初始化端口操作的參數.
     * @throws SerialPortException 
     * 
     * @see
     */
    public SerialReader()
    {
    <span style="white-space:pre">	</span>isOpen = false;
    }


    public void open(HashMap params)
    { 
    <span style="white-space:pre">	</span>serialParams = params;
    <span style="white-space:pre">	</span>if(isOpen){
    <span style="white-space:pre">		</span>close();
    <span style="white-space:pre">	</span>}
        try
        {
            // 參數初始
            int timeout = Integer.parseInt( serialParams.get( PARAMS_TIMEOUT )
                .toString() );
            int rate = Integer.parseInt( serialParams.get( PARAMS_RATE )
                .toString() );
            int dataBits = Integer.parseInt( serialParams.get( PARAMS_DATABITS )
                .toString() );
            int stopBits = Integer.parseInt( serialParams.get( PARAMS_STOPBITS )
                .toString() );
            int parity = Integer.parseInt( serialParams.get( PARAMS_PARITY )
                .toString() );
            delayRead = Integer.parseInt( serialParams.get( PARAMS_DELAY )
                .toString() );
            String port = serialParams.get( PARAMS_PORT ).toString();
            // 打開端口
            portId = CommPortIdentifier.getPortIdentifier( port );
            serialPort = ( SerialPort ) portId.open( "SerialReader", timeout );
            inputStream = serialPort.getInputStream();
            serialPort.addEventListener( this );
            serialPort.notifyOnDataAvailable( true );
            serialPort.setSerialPortParams( rate, dataBits, stopBits, parity );
            isOpen = true;
        }
        catch ( PortInUseException e )
        {
           // 端口"+serialParams.get( PARAMS_PORT ).toString()+"已經被佔�?;
        }
        catch ( TooManyListenersException e )
        {
           //"端口"+serialParams.get( PARAMS_PORT ).toString()+"監聽者過�?;
        }
        catch ( UnsupportedCommOperationException e )
        {
           //"端口操作命令不支�?;
        }
        catch ( NoSuchPortException e )
        {
          //"端口"+serialParams.get( PARAMS_PORT ).toString()+"不存�?;
        }
        catch ( IOException e )
        {
           //"打開端口"+serialParams.get( PARAMS_PORT ).toString()+"失敗";
        }
        serialParams.clear();
        Thread readThread = new Thread( this );
        readThread.start();
    }


     
    public void run()
    {
        try
        {
            Thread.sleep(50);
        }
        catch ( InterruptedException e )
        {
        }
    } 
    public void start(){
  try {  
 outputStream = serialPort.getOutputStream();
    } 
 catch (IOException e) {}
  try{ 
    readThread = new Thread(this);
	</span>readThread.start();
	</span>} 
	</span>catch (Exception e) {  }
   }  //start() end




   public void run(String message) {
   try { 
   Thread.sleep(4); 
           } 
   catch (InterruptedException e) {  } 
 try {
 if(message!=null&&message.length()!=0)
    { 
 System.out.println("run message:"+message);
         outputStream.write(message.getBytes());  
 }
} catch (IOException e) {}
   } 
    


    public void close() 
    { 
        if (isOpen)
        {
            try
            {
            <span style="white-space:pre">	</span>serialPort.notifyOnDataAvailable(false);
            <span style="white-space:pre">	</span>serialPort.removeEventListener();
                inputStream.close();
                serialPort.close();
                isOpen = false;
            } catch (IOException ex)
            {
            //"關閉串口失敗";
            }
        }
    }
    
    public void serialEvent( SerialPortEvent event )
    {
        try
        {
            Thread.sleep( delayRead );
        }
        catch ( InterruptedException e )
        {
            e.printStackTrace();
        }
        switch ( event.getEventType() )
        {
            case SerialPortEvent.BI: // 10
            case SerialPortEvent.OE: // 7
            case SerialPortEvent.FE: // 9
            case SerialPortEvent.PE: // 8
            case SerialPortEvent.CD: // 6
            case SerialPortEvent.CTS: // 3
            case SerialPortEvent.DSR: // 4
            case SerialPortEvent.RI: // 5
            case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2
                break;
            case SerialPortEvent.DATA_AVAILABLE: // 1
                try
                {
                    // 多次讀取,將所有數據讀�?
                     while (inputStream.available() > 0) {
                     numBytes = inputStream.read(readBuffer);
                     }
                     
                     //打印接收到的字節數據的ASCII�?
                     for(int i=0;i<numBytes;i++){
                    <span style="white-space:pre">	</span>// System.out.println("msg[" + numBytes + "]: [" +readBuffer[i] + "]:"+(char)readBuffer[i]);
                     }
//                    numBytes = inputStream.read( readBuffer );
                    changeMessage( readBuffer, numBytes );
                }
                catch ( IOException e )
                {
                    e.printStackTrace();
                }
                break;
        }
    }


    // 通過observer pattern將收到的數據發�?給observer
    // 將buffer中的空字節刪除後再發送更新消�?通知觀察�?
    public void changeMessage( byte[] message, int length )
    {
        setChanged();
        byte[] temp = new byte[length];
        System.arraycopy( message, 0, temp, 0, length );
        notifyObservers( temp );
    }


    static void listPorts()
    {
        Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
        while ( portEnum.hasMoreElements() )
        {
            CommPortIdentifier portIdentifier = ( CommPortIdentifier ) portEnum
                .nextElement();
            
        }
    }
    
    
    public void openSerialPort(String message)
    {
        HashMap<String, Comparable> params = new HashMap<String, Comparable>();  
        String port="COM1";
        String rate = "9600";
        String dataBit = ""+SerialPort.DATABITS_8;
        String stopBit = ""+SerialPort.STOPBITS_1;
        String parity = ""+SerialPort.PARITY_NONE;    
        int parityInt = SerialPort.PARITY_NONE; 
        params.put( SerialReader.PARAMS_PORT, port ); // 端口名稱
        params.put( SerialReader.PARAMS_RATE, rate ); // 波特�?
        params.put( SerialReader.PARAMS_DATABITS,dataBit  ); // 數據�?
        params.put( SerialReader.PARAMS_STOPBITS, stopBit ); // 停止�?
        params.put( SerialReader.PARAMS_PARITY, parityInt ); // 無奇偶校�?
        params.put( SerialReader.PARAMS_TIMEOUT, 100 ); // 設備超時時間 1�?
        params.put( SerialReader.PARAMS_DELAY, 100 ); // 端口數據準備時間 1�?
        try {
open(params);//打開串口
//LoginFrame cf=new LoginFrame();
//addObserver(cf);
//也可以像上面�?��通過LoginFrame來綁定串口的通訊輸出.
if(message!=null&&message.length()!=0)
 {
String str="";
for(int i=0;i<10;i++)
{
str+=message;
}
 start(); 
    run(str);  
 } 
} catch (Exception e) { 
}
    }


    static String getPortTypeName( int portType )
    {
        switch ( portType )
        {
            case CommPortIdentifier.PORT_I2C:
                return "I2C";
            case CommPortIdentifier.PORT_PARALLEL:
                return "Parallel";
            case CommPortIdentifier.PORT_RAW:
                return "Raw";
            case CommPortIdentifier.PORT_RS485:
                return "RS485";
            case CommPortIdentifier.PORT_SERIAL:
                return "Serial";
            default:
                return "unknown type";
        }
    }


     
    public  HashSet<CommPortIdentifier> getAvailableSerialPorts()//本來static
    {
        HashSet<CommPortIdentifier> h = new HashSet<CommPortIdentifier>();
        Enumeration thePorts = CommPortIdentifier.getPortIdentifiers();
        while ( thePorts.hasMoreElements() )
        {
            CommPortIdentifier com = ( CommPortIdentifier ) thePorts
                .nextElement();
            switch ( com.getPortType() )
            {
                case CommPortIdentifier.PORT_SERIAL:
                    try
                    {
                        CommPort thePort = com.open( "CommUtil", 50 );
                        thePort.close();
                        h.add( com );
                    }
                    catch ( PortInUseException e )
                    {
                        System.out.println( "Port, " + com.getName()
                            + ", is in use." );
                    }
                    catch ( Exception e )
                    {
                        System.out.println( "Failed to open port "
                            + com.getName() + e );
                    }
            }
        }
        return h;
    }
}
<p>
</p><p></p>package comme64;</p> /*
  *數據位 8
 * 校驗位 0
 * 停止位 1
 * 波特率 115200
 * 端口com3
  */
import gnu.io.SerialPort;


import java.util.*;


public class Test implements Observer{ 
public static void main(String []args)
{
Test test = new Test();
test.send("串口數據發送至DTU轉發至服務器!");
while(true)
{
test.send("串口數據發送至DTU轉發至服務器!");
}
}
SerialReader sr=new SerialReader(); 
//    public Test()
//    {    
//       openSerialPort("COM3"); //打開串口。
//    } 
    public void update(Observable o, Object arg){    
    String mt=new String((byte[])arg);  
    System.out.println("---"+mt); //串口數據 
    } 
    
    /**
     * 往串口發送數據,實現雙向通訊.
     * @param string message
     */
    public  void send(String message)
    {
    <span style="white-space:pre">	</span>Test test = new Test();
    <span style="white-space:pre">	</span>test.openSerialPort(message);
    }
<span style="white-space:pre">	</span>
    /**
     * 打開串口
     * @param String message
     */
<span style="white-space:pre">	</span>public void openSerialPort(String message)
    { 
        HashMap<String, Comparable> params = new HashMap<String, Comparable>();  
        String port="COM3";
        String rate = "115200";
        String dataBit = ""+SerialPort.DATABITS_8;
        String stopBit = ""+SerialPort.STOPBITS_1;
        String parity = ""+SerialPort.PARITY_NONE;    
        int parityInt = SerialPort.PARITY_NONE; 
        params.put( SerialReader.PARAMS_PORT, port ); // 端口名稱
        params.put( SerialReader.PARAMS_RATE, rate ); // 波特率
        params.put( SerialReader.PARAMS_DATABITS,dataBit  ); // 數據位
        params.put( SerialReader.PARAMS_STOPBITS, stopBit ); // 停止位
        params.put( SerialReader.PARAMS_PARITY, parityInt ); // 無奇偶校驗
        params.put( SerialReader.PARAMS_TIMEOUT,100 ); // 設備超時時間 1秒
        params.put( SerialReader.PARAMS_DELAY, 100 ); // 端口數據準備時間 1秒
        try {
sr.open(params);
   sr.addObserver(this);
if(message!=null&&message.length()!=0)
 {  
sr.start();  
sr.run(message);  
 } 
} catch (Exception e) { 
}
    }
    

 public String Bytes2HexString(byte[] b) { 
  String ret = ""; 
  for (int i = 0; i < b.length; i++) { 
     String hex = Integer.toHexString(b[i] & 0xFF); 
    if (hex.length() == 1) { 
      hex = '0' + hex; 
    } 
   ret += hex.toUpperCase(); 
 }
return ret;
  }


 public  String hexString2binaryString(String hexString) {
 if (hexString == null || hexString.length() % 2 != 0)
return null;
 String bString = "", tmp;
for (int i = 0; i < hexString.length(); i++) {
 tmp = "0000" + Integer.toBinaryString(Integer.parseInt(hexString.substring(i, i + 1), 16));
bString += tmp.substring(tmp.length() - 4);
 }
 return bString;
 } 
} 

 通過Test.java的測試,可以成功把數據發送出去,這裏還是要注意端口的以及波特率的正確。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章