转自BBS水木清华站Java讨论区 利用Java实现串口全双工通讯 qyjohn , 3月30日,2001年 关键字: Java Comm API,串口,全双工通讯 摘要: 
本文介绍一个利用Java Comm API (javax.comm)实现串口全双工通讯的简单程序 本文介绍一个利用Java Comm API (javax.comm)实现串口全双工通讯的简单程序。这个程序首先打开并初始化一个串口,然后启动如下三个进程:ReadSerial进程从该串口读取数据并放入缓冲区,ReadBuffer进程从缓冲区读取数据并打印到屏幕, WriteSerial进程每5秒钟向该串口发送一个星号(*)。  在这个示例程序中使用了一个简单的协议,既不同的消息之间用星号'*'作为分隔。缓冲区程序根据是否收到星号作为存在等待处理的消息的判断依据。  Java Comm API不是标准的Java API,因此的标准的运行环境中并不提供这个包。如果你的系统上还没有安装这个包,你可以从SUN公司的网站下载。在这个包里面有一个安装指南,如果你没有正确安装这个包,可能你不能够正确运行这个例程。  这个简单的例程包括以下文件:  IMU.java (主程序)  
ReadBuffer.java (从缓冲区读取一个消息)  
ReadSerial.java (读取串口数据并放入缓冲区)  
SerialBuffer.java (缓冲区)  
WriteSerial.java (每5秒钟往串口送一个星号'*')  测试程序:  SendCom.java (将一个数据文件往串口发送)  
SEND.TXT (供测试用的数据文件)  测试方法:  1 正确安装Java Comm API后编译本例程  
2 将计算机的COM1和COM2用一条串口线连接起来  
3 运行IMU。如果你这时候打开Windows自带的超级终端并连接到COM2的话,你应该能够看见有星号出现在超级终端的屏幕上。超级终端的参数设置为9600, N, 8, 1, none。  
4 关闭超级终端,运行SendCom。这时候你应该能够从IMU的屏幕上看到数据文件里面的内容。  /*  
*  
* IMU.java 1.0  
* Main Program for Serial Communication  
*  
* Created: March 27, 2001  
*  
* Author : Qingye Jiang (John)  
* American GNC Corporation  
* 888 Easy St, Simi Valley CA 93065-1812  
*  
* Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)  
[email protected]  
*  
*/  import java.io.*;  
import java.util.*;  
import javax.comm.*;  class IMU  
{  static CommPortIdentifier portId;  
static SerialPort serialPort;  
static OutputStream out;  
static InputStream in;  public static void main(String[] args)  
{  try  
{  //Declare the serial port, and open it.  portId = CommPortIdentifier.getPortIdentifier("COM1");  
try  
{  serialPort = (SerialPort) portId.open("IMU_App", 2000);  } catch (PortInUseException e)  
{  System.out.println(e.getMessage());  }  //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)  
{  System.out.println(e.getMessage());  }  //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) 
{  System.out.println(e.getMessage());  }  } catch (NoSuchPortException e)  
{  System.out.println(e.getMessage());  }  //Declare the serial buffer area, a thread to read from the seriial port,  
//a thread to read from the serial buffer for processing, and a thread  
//to write to the serial port.  SerialBuffer SB = new SerialBuffer();  
ReadSerial r1 = new ReadSerial(SB, in);  
ReadBuffer r2 = new ReadBuffer(SB);  
WriteSerial r3 = new WriteSerial(out);  
//Start all three threads.  r1.start();  
r2.start();  
r3.start();  }  }  /*  
*  
* SerialBuffer.java 1.0  
* Class that implements the serial buffer  
*  
* Created: March 27, 2001  
*  
* Author : Qingye Jiang (John)  
* American GNC Corporation  
* 888 Easy St, Simi Valley CA 93065-1812  
*  
* Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)  
[email protected]  
*  
*/  public class SerialBuffer  
{  private String Content = "";  
private String CurrentMsg, TempContent;  
private boolean available = false;  
//read a message from the serial buffer. The star character '*' is used  
//as the seperation  between different messages.  public synchronized String GetMsg()  
{  int SepMark;  if ((SepMark = Content.indexOf('*')) == -1)  
{  available = false;  
while (available == false)  
{  try  
{  
        wait();  
} catch (InterruptedException e) { }  }  
SepMark = Content.indexOf('*');  }  CurrentMsg = Content.substring(0, SepMark);  
TempContent = Content.substring(SepMark+1);  
Content = TempContent;  
notifyAll();  
return CurrentMsg;  }  //Put a character to the serial buffer  public synchronized void PutChar(int c)  
{  Character d = new Character((char) c);  
Content = Content.concat(d.toString());  
if (c == '*')  
{  
        available = true;  
}  
notifyAll();  }  }  /*  
*  
* ReadSerial.java 1.0  
* Program to read characters from the serial port and put it  
* to the buffer  
*  
* Created: March 27, 2001  
*  
* Author : Qingye Jiang (John)  
* American GNC Corporation  
* 888 Easy St, Simi Valley CA 93065-1812  
*  
* Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)  
[email protected]  
*  
*/  import java.io.*;  public class ReadSerial extends Thread  
{  private SerialBuffer ComBuffer;  
private InputStream ComPort;  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) {}  }  }  
/*  
*  
* ReadBuffer.java 1.0  
* Program to Read the Serial Buffer  
*  
* Created: March 27, 2001  
*  
* Author : Qingye Jiang (John)  
* American GNC Corporation  
* 888 Easy St, Simi Valley CA 93065-1812  
*  
* Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)  
[email protected]  
*  
*/  import java.io.*;  public class ReadBuffer extends Thread  
{  private SerialBuffer ComBuffer;  public ReadBuffer(SerialBuffer SB)  
{  
        ComBuffer = SB;  
}  public void run()  
{  String Msg;  
while (true)  
{  
        Msg = ComBuffer.GetMsg();  
        System.out.println(Msg);  
}  }  }  /*  
*  
* WriteSerial.java 1.0  
* Program to send a star to the serial port every 5 seconds.  
*  
* Created: March 27, 2001  
*  
* Author : Qingye Jiang (John)  
* American GNC Corporation  
* 888 Easy St, Simi Valley CA 93065-1812  
*  
* Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)  
[email protected]  
*  
*/  import java.io.*;  public class WriteSerial extends Thread  
{  private SerialBuffer ComBuffer;  
private OutputStream ComPort;  public WriteSerial(OutputStream Port)  
{  
        ComPort = Port;  
}  public void run()  
{  int c;  
try  
{  while (true)  
{ ComPort.write('*');  
try  
{  
        wait(5000);  
} catch (InterruptedException e) { }  }  } catch (IOException e)  
{  
        System.out.println(e.getMessage());  
}  }  }  /*  
*  
* SendCom.java 1.0  
*  
* Project: Java Based Information Exchange Support System  
* Onboard Plug-in System  
* Sending data through serial port  
*  
* Created: March 15, 2001  
*  
* Author : Qingye Jiang (John)  
* American GNC Corporation  
* 888 Easy St, Simi Valley CA 93065-1812  
*  
* Contact: (805) 582-0582 (Tel), (805) 582-0098 (Fax)  
*  
*/  import java.io.*;  public class SendCom  
{  public static void main(String[] args)  
{  File OutFile = new File("SEND.TXT");  
File ComPort = new File("COM2");  int c;  try  
{  FileReader in = new FileReader(OutFile);  
FileWriter out = new FileWriter(ComPort);  
while ((c = in.read()) != -1)  
        out.write(c);  
in.close();  
out.close();  } catch (IOException e) {}  }  }  SEND.TXT*  This is a sample of the data file for program testing. *  It should be in the same directory as the SendCom.class file.*  When you run this sample program, connect your COM1 and COM2 with a  
serial cable so that you can test this program on one machine. If  
you have two machines, you can connect the two machine via a serial  
cable and test it. Modified the definition of ComPort in the program  
if necessary. *  Thank you for testing this program. If you have any suggestions please  
kindly let me know. *  小结:  在上面的例程中,大多数的程序仅对我前天发的《一个使用Java读取串口的程序》 
一文做了小篇幅的改动,有几个程序和数据文件都没有改动。但是为了本文的完整 
性,仍然将雷同的内容也贴了一遍,还望斑竹多多见谅。 这个例程和前面一个例程的区别在于前面一个例程使用了文件IO,而本例程使用了 
Comm API。在C语言里面用fopen()函数来打开串口是可读也可写的,但是在Java里 
面声明了File以后并不立即打开文件,文件是在声明FileReader或者FileWriter时 
才打开的。由于串口不能同时被打开两次,所以读操作和写操作不能够同时进行, 
不能够实现全双工通讯。 Comm API虽然能够实现全双工通讯,但是由于它不是标准的Java API,代码的可移 
植性难以保证。如果程序并不要求实现全双工的话,我认为利用文件操作不失为一 
个好办法。    编辑 guty