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

      最近公司的项目需要和硬件打交道,而我负责硬件对接这块的主要工作,这几天把java中的串口编程熟悉了下,其中大多是涉及到环境的配置,接下来我把自己做的过程中遇到的问题整理一下,供大家产考!

      大至的应用场景是这样的,终端设备(简称DTU)通过USB连接到主机上,主机上通过Java 的串口程序把数据发送到DTU,dtu配置好转发服务器的ip和端口号,这样主机的数据就可以直接发送至服务器了,可能有人会问为什么不直接发送至服务器,因为我们的应用场景中主机是不可以联网的。

1.USB端口连接电脑

Usb端口在连接电脑的过程中,打开桌面搜索“设备管理”,查看是否有Usb的端口,
Java USB串口编程(64位和32位)_第1张图片
根据电脑的连接设备情况,一般会有一道多个端口,我们只需要记住我们需要的端口就可以了,这里我们记录下com4端口即可,但是也有情况是USB插入以后设备管理并没有识别,是因为没有安装相应的驱动,这个时候我们需要安装驱动: usb-serial controller驱动, 下载安装即可。

2.win7 32位环境配置

首先我们是在32位的程序下测试,我们需要下载一个安装包,即 javacomm20-win32.zip,下载以后如图所试
Java USB串口编程(64位和32位)_第2张图片
主要用到的是这几个文件,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位系统测试

 
SimpleWrite.java
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) {}
                }
            }
        }
    }
}

其中需要注意的是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(){
    	return isOpen;
    }
    /**
     * 初始化端口操作的参数.
     * @throws SerialPortException 
     * 
     * @see
     */
    public SerialReader()
    {
    	isOpen = false;
    }


    public void open(HashMap params)
    { 
    	serialParams = params;
    	if(isOpen){
    		close();
    	}
        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);
	readThread.start();
	} 
	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
            {
            	serialPort.notifyOnDataAvailable(false);
            	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	// 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 params = new HashMap();  
        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 getAvailableSerialPorts()//本来static
    {
        HashSet h = new HashSet();
        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;
    }
}

package comme64;

 /*   *数据位 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)     {     Test test = new Test();     test.openSerialPort(message);     }     /**      * 打开串口      * @param String message      */ public void openSerialPort(String message)     {          HashMap params = new HashMap();           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的测试,可以成功把数据发送出去,这里还是要注意端口的以及波特率的正确。

你可能感兴趣的:(串口通信)