我使用Java CommAPI读取rs232串口的数据,按照网上说的下载Java Comm API配置后,把sun自带的那个示例程序运行了一边,但是什么反映也没有,没有显示任何数据。另外我电脑的rs232串口接了一个IC卡读卡器,在上面刷卡也没反应,100分请哪位帮我解决!QQ,msn联系都行,QQ:78891611,msn:[email protected]。示例代码如下:
/*
 * @(#)SimpleRead.java  1.12 98/06/25 SMI
 *
 * Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Sun grants you ("Licensee") a non-exclusive, royalty free, license 
 * to use, modify and redistribute this software in source and binary
 * code form, provided that i) this copyright notice and license appear
 * on all copies of the software; and ii) Licensee does not utilize the
 * software in a manner which is disparaging to Sun.
 *
 * This software is provided "AS IS," without a warranty of any kind.
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND
 * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
 * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE
 * SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS
 * BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
 * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES,
 * HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING
 * OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * This software is not designed or intended for use in on-line control
 * of aircraft, air traffic, aircraft navigation or aircraft
 * communications; or in the design, construction, operation or
 * maintenance of any nuclear facility. Licensee represents and
 * warrants that it will not use or redistribute the Software for such
 * purposes.
 */import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.TooManyListenersException;import javax.comm.CommPortIdentifier;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
import javax.comm.SerialPortEvent;
import javax.comm.SerialPortEventListener;
import javax.comm.UnsupportedCommOperationException;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();    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")) {
         SimpleRead reader = new SimpleRead();
        }
      }
    }
  }  public SimpleRead() {
    try {
      serialPort = (SerialPort) portId.open("MainClassApp", 2000);
    } catch (PortInUseException e) {
    }
    try {
      inputStream = serialPort.getInputStream();
    } catch (IOException e) {
    }
    try {
      serialPort.addEventListener(this);
      System.out.println("1");
    } catch (TooManyListenersException e) {
    }
    serialPort.notifyOnDataAvailable(true);
    try {
      serialPort.setSerialPortParams(19200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
          SerialPort.PARITY_NONE);
    } catch (UnsupportedCommOperationException e) {
    }
    readThread = new Thread(this);
    readThread.start();
  }  public void run() {
    try {
      Thread.sleep(2000);
      System.out.println("2");
    } catch (InterruptedException e) {
    }
  }  public void serialEvent(SerialPortEvent event) {
  System.out.println("a");
    switch (event.getEventType()) {
    case SerialPortEvent.BI:
    case SerialPortEvent.OE:
    case SerialPortEvent.FE:
    case SerialPortEvent.PE:
    case SerialPortEvent.CD:
    case SerialPortEvent.CTS:
    case SerialPortEvent.DSR:
    case SerialPortEvent.RI:
    case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
      break;
    case SerialPortEvent.DATA_AVAILABLE:
      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;
    }
  }
}

解决方案 »

  1.   

    使用Java CommAPI的时候有一个配置文件,好像是需要放在classpath下吧,我不是很记得了,以前用短信猫的时候用过,其它的好像没有什么。
    我以前写的一个短信发送程序,曾经也碰到过一些问题,后来发现serialPort.setSerialPortParams(19200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, 
              SerialPort.PARITY_NONE); 
    这里面的这些参数也很重要,如果和你的设备不匹配好像也不行。
      

  2.   

    你先用windows自带的超级终端试试,如果能够正常的话,设备和连接应该没有问题,然后再检查程序。
      

  3.   

    我觉得这个有道理啊
    1. 硬件你可以先用一个串口调试器来调一下
    看看通不通,有没有返回数据。2. 也可以先不连硬件,直接自己虚拟两个串口来做调试,3. 接下来是你串口的配置,
    (1).COMM.JAR;
    (2).javax.comm.properties;
    (3).win32com.dll;
    把这三个文件放到如下目录中:
    其中:JDKDIR是JDK的安装目录,JREDIR是JRE的安装目录。
    假如你把JAVA开发包装在C:\Program Files\Java中,里面有两个文件夹,一个是JDK,一个是JRE。
    COMM.JAR放到JDKDIR/jre/lib/ext;
    javax.comm.properties放到JDKDIR/jre/lib。
    win32com.dll放到JDKDIR/bin中,
    如果用ECLIPSE可能需要你手动导入comm.JAR,相信这个大家都会。
    配置到这里就完成了吗?
    没有,有的机器会报错,如果说没有win32com.dll,那么请把win32com.dll放到JreDIR/bin中就可以了。
    如果发现获得的端口列表中为空,那是因为机器没有找到javax.comm.properties文件,同样把javax.comm.properties放到JreDIR/jre/lib中就可以了,具体是放到JDK还是JRE中,我也不太明白。估计和机器和JDK版本有关系了,不过,肯定有效的方法是你把JDK还是JRE,全都放了.这个在我资源里有一个小工具挺好用,LZ也可以在网上直接找。4. 现在就要看你的程序了,你的程序我调了一下,是可以通讯的,不过现在你的程序还是只能收不能发
    我这里有一个封装的简单类库,也是我现在正在用的,感觉还可以,呵呵
    另外还有一个开源的nio框架叫MINA的,也做了封装,支持串口通讯,但是我没有找到它的例子SerialBean.java (与其他应用程序的接口), SerialBuffer.java(用来保存从串口所接收数据的缓冲区), ReadSerial.java (从串口读取数据的程序)。另外本类库还提供了一个例程SerialExample.java 作为示范。在下面的内容中将逐一对这几个部分进行详细介绍。  1. SerialBean  SerialBean是本类库与其他应用程序的接口。该类库中定义了SerialBean的构造方法以及初始化串口,从串口读取数据,往串口写入数据以及关闭串口的函数。具体介绍如下:
      public SerialBean(int PortID)  本函数构造一个指向特定串口的SerialBean,该串口由参数PortID所指定。PortID = 1 表示COM1,PortID = 2 表示COM2,由此类推。
      public int Initialize()  本函数初始化所指定的串口并返回初始化结果。如果初始化成功返回1,否则返回-1。初始化的结果是该串口被SerialBean独占性使用,其参数被设置为9600, N, 8, 1。如果串口被成功初始化,则打开一个进程读取从串口传入的数据并将其保存在缓冲区中。
      public String ReadPort(int Length)  本函数从串口(缓冲区)中读取指定长度的一个字符串。参数Length指定所返回字符串的长度。
      public void WritePort(String Msg)  本函数向串口发送一个字符串。参数Msg是需要发送的字符串。
      public void ClosePort()  本函数停止串口检测进程并关闭串口。  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是本类库中所定义的串口缓冲区,它定义了往该缓冲区中写入数据和从该缓冲区中读取数据所需要的函数。
      public synchronized String GetMsg(int Length)  本函数从串口(缓冲区)中读取指定长度的一个字符串。参数Length指定所返回字符串的长度。
      public synchronized void PutChar(int c)  本函数望串口缓冲区中写入一个字符,参数c 是需要写入的字符。  在往缓冲区写入数据或者是从缓冲区读取数据的时候,必须保证数据的同步,因此GetMsg和PutChar函数均被声明为synchronized并在具体实现中采措施实现的数据的同步。  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是一个进程,它不断的从指定的串口读取数据并将其存放到缓冲区中。
      public ReadSerial(SerialBuffer SB, InputStream Port)  本函数构造一个ReadSerial进程,参数SB指定存放传入数据的缓冲区,参数Port指定从串口所接收的数据流。
      public void run()  ReadSerial进程的主函数,它不断的从指定的串口读取数据并将其存放到缓冲区中。  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是本类库所提供的一个例程。它所实现的功能是打开串口COM1,对其进行初始化,从串口读取信息对其进行处理后将处理结果发送到串口。
    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();
     }
    }
      

  4.   

    这句“这个在我资源里有一个小工具挺好用,LZ也可以在网上直接找。 “
    是跟在”2. 也可以先不连硬件,直接自己虚拟两个串口来做调试, “这里的
    呵呵 太多了希望对LZ有帮助啊
      

  5.   

    comm.jar 
    通过串口,PC机可以获取设备的输入数据,也可以让PC机向设备输出输出。你的设备应该有相关的程序与说明。 
      

  6.   

    没有提供任何程序,只提供了一个dll文件,但是我发现用jni调用那个dll文件更麻烦,所以想用comm.jar。
      

  7.   

    设备既然提供了一个dll,还是建议采用jni比较好,封装dll很简单啊,调用一下不就可以了吗。要是我肯定选择使用jni调用。不就是自己再写一个dll吗,不需要的方法直接不要了,只写自己需要的几个方法。
      

  8.   

    我使用dll试过了,能调用里面的打开串口方法,但是读数据的方法就是调用不正确
      

  9.   

    我用的设备就是学校机房食堂用的那种刷卡机,我问了老师,他说厂商值提供了一个dll文件以及里面可以调用的方法,我试过使用jni调用他的dll,结果还是一样读不出数据,谁用过jni的教我一下,不知道是不是使用jni方法不对