comm.jar

所有的comm API位于javax.comm包下面。从Comm API的javadoc来看,它介绍给我们的只有区区以下13个类或接口:

Java代码 复制代码
  1.   javax.comm.CommDriver   
  2.     
  3.   javax.comm.CommPort   
  4.     
  5.   javax.comm.ParallelPort   
  6.     
  7.   javax.comm.SerialPort   
  8.     
  9.   javax.comm.CommPortIdentifier   
  10.     
  11.   javax.comm.CommPortOwnershipListener   
  12.     
  13.   javax.comm.ParallelPortEvent   
  14.     
  15.   javax.comm.SerialPortEvent   
  16.     
  17.   javax.comm.ParallelPortEventListener (extends java.util.EventListener)   
  18.     
  19.   javax.comm.SerialPortEventListener (extends java.util.EventListener)   
  20.     
  21.   javax.comm.NoSuchPortException   
  22.     
  23.   javax.comm.PortInUseException   
  24.     
  25.   javax.comm.UnsupportedCommOperationException  
  javax.comm.CommDriver
 
  javax.comm.CommPort
 
  javax.comm.ParallelPort
 
  javax.comm.SerialPort
 
  javax.comm.CommPortIdentifier
 
  javax.comm.CommPortOwnershipListener
 
  javax.comm.ParallelPortEvent
 
  javax.comm.SerialPortEvent
 
  javax.comm.ParallelPortEventListener (extends java.util.EventListener)
 
  javax.comm.SerialPortEventListener (extends java.util.EventListener)
 
  javax.comm.NoSuchPortException
 
  javax.comm.PortInUseException
 
  javax.comm.UnsupportedCommOperationException


  下面讲解一下几个主要类或接口。

  1.枚举出系统所有的RS232端口

  在开始使用RS232端口通讯之前,我们想知道系统有哪些端口是可用的,以下代码列出系统中所有可用的RS232端口:

Java代码 复制代码
  1.   Enumeration en = CommPortIdentifier.getPortIdentifiers();   
  2.     
  3.   CommPortIdentifier portId;   
  4.     
  5.   while (en.hasMoreElements())   
  6.     
  7.   {   
  8.     
  9.   portId = (CommPortIdentifier) en.nextElement();   
  10.     
  11.   /*如果端口类型是串口,则打印出其端口信息*/  
  12.     
  13.   if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL)   
  14.     
  15.   {   
  16.     
  17.   System.out.println(portId.getName());   
  18.     
  19.   }   
  20.     
  21.   }  
  Enumeration en = CommPortIdentifier.getPortIdentifiers();
 
  CommPortIdentifier portId;
 
  while (en.hasMoreElements())
 
  {
 
  portId = (CommPortIdentifier) en.nextElement();
 
  /*如果端口类型是串口,则打印出其端口信息*/
 
  if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL)
 
  {
 
  System.out.println(portId.getName());
 
  }
 
  }


  在我的电脑上以上程序输出以下结果:

  COM1

  COM2

  CommPortIdentifier类的getPortIdentifiers方法可以找到系统所有的串口,每个串口对应一个CommPortIdentifier类的实例。

  2.打开端口

  如果你使用端口,必须先打开它。

Java代码 复制代码
  1.   try{   
  2.     
  3.   CommPort serialPort = portId.open("My App"60);   
  4.     
  5.   /*从端口中读取数据*/  
  6.     
  7.   InputStream input = serialPort.getInputStream();   
  8.     
  9.   input.read(...);   
  10.     
  11.   /*往端口中写数据*/  
  12.     
  13.   OutputStream output = serialPort.getOutputStream();   
  14.     
  15.   output.write(...)   
  16.     
  17.   ...   
  18.     
  19.   }catch(PortInUseException ex)   
  20.     
  21.   { ... }  
  try{
 
  CommPort serialPort = portId.open("My App", 60);
 
  /*从端口中读取数据*/
 
  InputStream input = serialPort.getInputStream();
 
  input.read(...);
 
  /*往端口中写数据*/
 
  OutputStream output = serialPort.getOutputStream();
 
  output.write(...)
 
  ...
 
  }catch(PortInUseException ex)
 
  { ... }


  通过CommPortIdentifier的open方法可以返回一个CommPort对象。open方法有两个参数,第一个是String,通常设置为你的应用程序的名字。第二个参数是时间,即开启端口超时的毫秒数。当端口被另外的应用程序占用时,将抛出PortInUseException异常。

  在这里CommPortIdentifier类和CommPort类有什么区别呢?其实它们两者是一一对应的关系。CommPortIdentifier主要负责端口的初始化和开启,以及管理它们的占有权。而CommPort则是跟实际的输入和输出功能有关的。通过CommPort的getInputStream()可以取得端口的输入流,它是java.io.InputStream接口的一个实例。我们可以用标准的InputStream的操作接口来读取流中的数据,就像通过FileInputSteam读取文件的内容一样。相应的,CommPort的getOutputStream可以获得端口的输出流,这样就可以往串口输出数据了。

  3.关闭端口

  使用完的端口,必须记得将其关闭,这样可以让其它的程序有机会使用它,不然其它程序使用该端口时可能会抛出端口正在使用中的错误。很奇怪的是,CommPortIdentifier类只提供了开启端口的方法,而要关闭端口,则要调用CommPort类的close()方法。
CommPort的输入流的读取方式与文件的输入流有些不一样,那就是你可能永远不知这个InputStream何时结束,除非对方的OutputStream向你发送了一个特定数据表示发送结束,你收到这个特定字符后,再行关闭你的InputStream。而comm.jar提供了两种灵活的方式让你读取数据。

  1.轮询方式(Polling)

  举个例子,你同GF相约一起出门去看电影,但你的GF好打扮,这一打扮可能就是半小时甚至一小时以上。这时你就耐不住了,每两分钟就催问一次“好了没?”,如此这样,直到你的GF说OK了才算完。这个就叫轮询(Polling)。

  在程序中,轮询通常设计成一个封闭的循环,当满足某个条件时即结束循环。刚才那个例子中,你的GF说“OK了!”,这个就是结束你轮询的条件。在单线程的程序中,当循环一直执行某项任务而又无法预知它何时结束时,此时你的程序看起来可能就像死机一样。在VB程序中,这个问题可以用在循环结构中插入一个doEvent语句来解决。而Java中,最好的方式是使用线程,就像以下代码片断一样。

Java代码 复制代码
  1.   public TestPort extend Thread   
  2.     
  3.   {   
  4.     
  5.   ...   
  6.     
  7.   InputStream input = serialPort.getInputStream();   
  8.     
  9.   StringBuffer buf = new StringBuffer();   
  10.     
  11.   boolean stopped = false;   
  12.     
  13.   ...   
  14.     
  15.   public void run()   
  16.     
  17.   {   
  18.     
  19.   try {   
  20.     
  21.   while( !stopped )   
  22.     
  23.   int ch = input.read();   
  24.     
  25.   if ( ch=='q' || ch=='Q' )   
  26.     
  27.   {   
  28.     
  29.   /*结束读取,关闭端口...*/  
  30.     
  31.   stopped = true;   
  32.     
  33.   ...   
  34.     
  35.   }   
  36.     
  37.   else  
  38.     
  39.   {   
  40.     
  41.   buf.append((char)ch);   
  42.     
  43.   ...   
  44.     
  45.   }   
  46.     
  47.   }catch (InterruptedException e) { }   
  48.     
  49.   }   
  50.     
  51.   }  
  public TestPort extend Thread
 
  {
 
  ...
 
  InputStream input = serialPort.getInputStream();
 
  StringBuffer buf = new StringBuffer();
 
  boolean stopped = false;
 
  ...
 
  public void run()
 
  {
 
  try {
 
  while( !stopped )
 
  int ch = input.read();
 
  if ( ch=='q' || ch=='Q' )
 
  {
 
  /*结束读取,关闭端口...*/
 
  stopped = true;
 
  ...
 
  }
 
  else
 
  {
 
  buf.append((char)ch);
 
  ...
 
  }
 
  }catch (InterruptedException e) { }
 
  }
 
  }


  2.监听方式(listening)

  Comm API支持标准的Java Bean型的事件模型。也就是说,你可以使用类似AddXXXListener这样的方法为一个串口注册自己的监听器,以监听方式进行数据读取。

  如要对端口监听,你必须先取得CommPortIdentifier类的一个实例,

  CommPort serialPort = portId.open("My App", 60);

  从而取得SerialPort,再调用它的addEventListener方法为它添加监听器,

  serialPort.addEventListener(new MyPortListener());

  SerialPort的监听器必须继承于SerialPortEventListener接口。当有任何SerialPort的事件发生时,将自动调用监听器中的serialEvent方法。Serial Event有以下几种类型:

  BI -通讯中断.

  CD -载波检测.

  CTS -清除发送.

  DATA_AVAILABLE -有数据到达.

  DSR -数据设备准备好.

  FE -帧错误.

  OE -溢位错误.

  OUTPUT_BUFFER_EMPTY -输出缓冲区已清空.

  PE -奇偶校验错.

  RI - 振铃指示.

  下面是一个监听器的示例:

Java代码 复制代码
  1.   public void MyPortListener implements SerialPortEventListener   
  2.     
  3.   {   
  4.     
  5.    public void serialEvent(SerialPortEvent evt)   
  6.     
  7.    {   
  8.     
  9.   switch (evt.getEventType())   
  10.     
  11.   {   
  12.     
  13.    case SerialPortEvent.CTS :   
  14.     
  15.     System.out.println("CTS event occured.");   
  16.     
  17.     break;   
  18.     
  19.    case SerialPortEvent.CD :   
  20.     
  21.     System.out.println("CD event occured.");   
  22.     
  23.     break;   
  24.     
  25.    case SerialPortEvent.BI :   
  26.     
  27.     System.out.println("BI event occured.");   
  28.     
  29.     break;   
  30.     
  31.    case SerialPortEvent.DSR :   
  32.     
  33.     System.out.println("DSR event occured.");   
  34.     
  35.     break;   
  36.     
  37.    case SerialPortEvent.FE :   
  38.     
  39.     System.out.println("FE event occured.");   
  40.     
  41.     break;   
  42.     
  43.    case SerialPortEvent.OE :   
  44.     
  45.     System.out.println("OE event occured.");   
  46.     
  47.     break;   
  48.     
  49.    case SerialPortEvent.PE :   
  50.     
  51.     System.out.println("PE event occured.");   
  52.     
  53.     break;   
  54.     
  55.    case SerialPortEvent.RI :   
  56.     
  57.     System.out.println("RI event occured.");   
  58.     
  59.     break;   
  60.     
  61.    case SerialPortEvent.OUTPUT_BUFFER_EMPTY :   
  62.     
  63.     System.out.println("OUTPUT_BUFFER_EMPTY event occured.");   
  64.     
  65.     break;   
  66.     
  67.    case SerialPortEvent.DATA_AVAILABLE :   
  68.     
  69.     System.out.println("DATA_AVAILABLE event occured.");   
  70.     
  71.     int ch;   
  72.     
  73.     StringBuffer buf = new StringBuffer();   
  74.     
  75.     InputStream input = serialPort.getInputStream   
  76.     
  77.     try {   
  78.     
  79.      while ( (ch=input.read()) > 0) {   
  80.     
  81.       buf.append((char)ch);   
  82.     
  83.      }   
  84.     
  85.      System.out.print(buf);   
  86.     
  87.     } catch (IOException e) {}   
  88.     
  89.     break;   
  90.     
  91.    }   
  92.     
  93.   }  
  public void MyPortListener implements SerialPortEventListener
 
  {
 
   public void serialEvent(SerialPortEvent evt)
 
   {
 
  switch (evt.getEventType())
 
  {
 
   case SerialPortEvent.CTS :
 
    System.out.println("CTS event occured.");
 
    break;
 
   case SerialPortEvent.CD :
 
    System.out.println("CD event occured.");
 
    break;
 
   case SerialPortEvent.BI :
 
    System.out.println("BI event occured.");
 
    break;
 
   case SerialPortEvent.DSR :
 
    System.out.println("DSR event occured.");
 
    break;
 
   case SerialPortEvent.FE :
 
    System.out.println("FE event occured.");
 
    break;
 
   case SerialPortEvent.OE :
 
    System.out.println("OE event occured.");
 
    break;
 
   case SerialPortEvent.PE :
 
    System.out.println("PE event occured.");
 
    break;
 
   case SerialPortEvent.RI :
 
    System.out.println("RI event occured.");
 
    break;
 
   case SerialPortEvent.OUTPUT_BUFFER_EMPTY :
 
    System.out.println("OUTPUT_BUFFER_EMPTY event occured.");
 
    break;
 
   case SerialPortEvent.DATA_AVAILABLE :
 
    System.out.println("DATA_AVAILABLE event occured.");
 
    int ch;
 
    StringBuffer buf = new StringBuffer();
 
    InputStream input = serialPort.getInputStream
 
    try {
 
     while ( (ch=input.read()) > 0) {
 
      buf.append((char)ch);
 
     }
 
     System.out.print(buf);
 
    } catch (IOException e) {}
 
    break;
 
   }
 
  }


  这个监听器只是简单打印每个发生的事件名称。而对于大多数应用程序来说,通常关心是DATA_AVAILABLE事件,当数据从外部设备传送到端口上来时将触发此事件。此时就可以使用前面提到过的方法,serialPort.getInputStream()来从InputStream中读取数据了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值