Java串口通信实例
前言:
如果你对串口了解的不是太多,还请你稍微拿出点时间来学习点(大致了解下就行,毕竟本篇文档主要是软件的通信开发)。在初次做这个java串口实现时,如果你用的是台式机,那么机箱后面一般有一个串口的(笔记本现在一般很少有了,USB技术通信逐渐流行开来)。
在真正用java实现串口之前,大家可以下载一个虚拟串口生成工具,以及串口调试工具,来模拟一下串口通信的大致情况。
正文:
这是一个用java代码实现的串口通信的小实例,仅供大家学习参考。下面共有六个java文件
(SerialDemo.java,SerialConnection.java,AlertDialog.java,PortRequestedDialog.java,SerialConnectionException.java,SerialParameters.java)
以下的java代码放在一个java包下面即可。
Java串口,本实例大致工作流程是:将以下的所有java类都放在一个包下面,runas ---java application ,打开的是一个图形化界面,最上面的是一个输入文本框(也就是你要发射的指令输入框),下面是一个接收的返回数据显示框,最下面的是串口的配置参数设置,最低端是几个按钮(打开串口,发送指令,关闭串口,发送中断,将接收数据框清空)。图形化界面的左上角有个File字样,这是个menu点击后可以看到有,save ,load ,exit(save 用于以文件的形式保存设置的串口通信参数,load 正好相反,是读取串口通信的参数文件,exit 是退出整个程序)。
使用此代码之前的环境配置:
首先用的是 javacomm20-win32.zip 这个压缩包 (javax.comm,自己可以到网上下载)
前提条件是:将这种配置放在外部的JDK环境之下(供参考)
①.解压完之后将win32com.dll 放到 C:\Program Files\Java\jdk1.7.0_03\bin下
②.将comm.jar 价包拷贝到 C:\Program Files\Java\jre7\lib\ext
③.javax.comm.properties 拷贝到 C:\Program Files\Java\jre7\lib
用rxtxComm来配置环境的话步骤如下:
step1.在eclipse中新建一个工程(根据你自己的需要,Applet,tomcat,java工程等均可)。
step2.在工程下建一个lib文件夹。
step3.将rxtx-2.1-7-bins-r2.zip解压缩,得到文件夹[rxtx-2.1-7-bins-r2]。
step4.将[rxtx-2.1-7-bins-r2]/RXTXcomm.jar这个文件copy到step2创建的lib中。
step5.将[rxtx-2.1-7-bins-r2]/Windows/i368-mingw32目录下的两个dll文件copy到step2创建的lib中。
step6.在工程上右键 ->Properties -> Java Builder Path -> Libraries -> Add JARs -> 选择step2中创建的lib目录下的RXTXcomm.jar -> OK。
step7.最关键的一步。点RXTXcomm.jar前面的小加号(+) -> 选择Native library location -> 点右边一列按钮中的Edit… -> 选择step2中创建的lib目录 -> OK。
补充:如果你的代码需要调用本地dll,你可以通过同样的方式设置Native library location。
注意:电脑上有一个默认的物理串口COM1,使用虚拟串口生成器时,会自动从COM2开始(一般一次生成两个虚拟的,与COM1有区别),用JavaxComm 环境配置时(由于其版本的不再升级),可能做的程序界面上不会显示COM1,可以用RxtxComm来配置,或者两种配置都用上(应该不会出现不兼容)。自己在测试时用的是COM1串口(直接就是在机箱后面接上通信线)。
Ps:java串口实现有很多种方法,希望这个实例能帮助java开发专业人员及爱好者进一步地学习。
代码:
SerialDemo.java
import java.awt.Button;
import java.awt.Choice;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FileDialog;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Properties;
import javax.comm.CommPortIdentifier;
import javax.swing.JComboBox;
/**
*Main file for SerialDemo program. This program illustrates many of the
*abilities of the javax.comm api. This file contains the GUI framework that
*the program runs in.
*/
public class SerialDemo extends Frameimplements ActionListener {
finalint HEIGHT = 450;
finalint WIDTH = 410;
privateMenuBar mb;
privateMenu fileMenu;
privateMenuItem openItem;
privateMenuItem saveItem;
privateMenuItem exitItem;
private JComboBox type;
privateButton openButton;
privateButton closeButton;
privateButton breakButton;
privateButton sendButton;
privateButton clearButton;
privatePanel buttonPanel;
privatePanel messagePanel;
privateTextArea messageAreaOut;
privateTextArea messageAreaIn;
privateConfigurationPanel configurationPanel;
privateSerialParameters parameters;
privateSerialConnection connection;
privateProperties props = null;
/**
* Main method. Checks to see if the commandline agrument is requesting
* usage informaition (-h, -help), if it is,display a usage message and
* exit, otherwise create a new<code>SerialDemo</code> and set it visible.
*/
publicstatic void main(String[] args) {
System.out.println("进入主函数");
if((args.length > 0)
&&(args[0].equals("-h") || args[0].equals("-help"))) {
System.out.println("usage:java SerialDemo [configuration File]");
System.exit(1);
}
SerialDemoserialDemo = new SerialDemo(args);
serialDemo.setVisible(true);
serialDemo.repaint();
}
/**
* Create new<code>SerialDemo</code> and initilizes it. Parses args to find
* configuration file. If found, initial stateit set to parameters in
* configuration file.
*
* @param args
* command line arguments used when program was invoked.
*/
publicSerialDemo(String[] args) {
super("SerialDemo");
if(!(args.length > 0)) {
System.out.println("serialdemo的args传过来还是为空");
}
//添加到面板的初始化参数
parameters= new SerialParameters();
//Set up the GUI for the program
addWindowListener(newCloseHandler(this));
mb= new MenuBar();
fileMenu= new Menu("File");
openItem= new MenuItem("Load");
openItem.addActionListener(this);
fileMenu.add(openItem);
saveItem= new MenuItem("Save");
saveItem.addActionListener(this);
fileMenu.add(saveItem);
exitItem= new MenuItem("Exit");
exitItem.addActionListener(this);
fileMenu.add(exitItem);
mb.add(fileMenu);
setMenuBar(mb);
messagePanel= new Panel();
messagePanel.setLayout(newGridLayout(2, 1));
//信息码的输入(并且应该是可以编辑的):
messageAreaOut= new TextArea();
messagePanel.add(messageAreaOut);
//解析信息码(只可接收不可编辑)
messageAreaIn= new TextArea();
messageAreaIn.setEditable(false);
messagePanel.add(messageAreaIn);
add(messagePanel,"Center");
//底面的button
configurationPanel= new ConfigurationPanel(this);
buttonPanel= new Panel();
openButton= new Button("Open Port");
openButton.addActionListener(this);
buttonPanel.add(openButton);
sendButton= new Button("Send Data");
sendButton.addActionListener(this);
sendButton.setEnabled(false);
buttonPanel.add(sendButton);
closeButton= new Button("Close Port");
closeButton.addActionListener(this);
closeButton.setEnabled(false);
buttonPanel.add(closeButton);
breakButton= new Button("Send Break");
breakButton.addActionListener(this);
breakButton.setEnabled(false);
buttonPanel.add(breakButton);
clearButton= new Button("Clear");
clearButton.addActionListener(this);
clearButton.setEnabled(false);
buttonPanel.add(clearButton);
PanelsouthPanel = new Panel();
GridBagLayoutgridBag = new GridBagLayout();
GridBagConstraintscons = new GridBagConstraints();
southPanel.setLayout(gridBag);
cons.gridwidth= GridBagConstraints.REMAINDER;
gridBag.setConstraints(configurationPanel,cons);
cons.weightx= 1.0;
southPanel.add(configurationPanel);
gridBag.setConstraints(buttonPanel,cons);
southPanel.add(buttonPanel);
add(southPanel,"South");
parseArgs(args);
connection= new SerialConnection(this, parameters, messageAreaOut,
messageAreaIn);
//将设置好的参数传到connection
setConfigurationPanel();
DimensionscreenSize = Toolkit.getDefaultToolkit().getScreenSize();
setLocation(screenSize.width/ 2 - WIDTH / 2, screenSize.height / 2
-HEIGHT / 2);
setSize(WIDTH,HEIGHT);
}
/**
* Sets the GUI elements on theconfigurationPanel.
*/
publicvoid setConfigurationPanel() {
configurationPanel.setConfigurationPanel();
}
/**
* Responds to the menu items and buttons.
*/
//监听选择及按钮操作
publicvoid actionPerformed(ActionEvent e) {
Stringcmd = e.getActionCommand();
//Loads a configuration file.应该就是将配置好的参数的文件从外部直接导入
if(cmd.equals("Load")) {
if(connection.isOpen()) {
AlertDialogad = new AlertDialog(this, "Port Open!",
"Configurationmay not", "be loaded",
"whilea port is open.");
}else {
FileDialogfd = new FileDialog(this, "Load Port Configuration",
FileDialog.LOAD);
fd.setVisible(true);
Stringfile = fd.getFile();
if(file != null) {
String dir =fd.getDirectory();
Filef = new File(dir + file);
try{
FileInputStreamfis = new FileInputStream(f);
props= new Properties();
props.load(fis);
fis.close();
}catch (FileNotFoundException e1) {
System.err.println(e1);
}catch (IOException e2) {
System.err.println(e2);
}
loadParams();
}
}
}
//Saves a configuration file.应该就是将配置好的参数以文件的形式保存
if(cmd.equals("Save")) {
configurationPanel.setParameters();
FileDialogfd = new FileDialog(this, "Save Port Configuration",
FileDialog.SAVE);
fd.setFile("serialdemo.properties");
fd.setVisible(true);
StringfileName = fd.getFile();
Stringdirectory = fd.getDirectory();
if((fileName != null) && (directory != null)) {
writeFile(directory+ fileName);
}
}
//Calls shutdown, which exits the program.
if(cmd.equals("Exit")) {
shutdown();
}
//Opens a port.打开串口
if(cmd.equals("Open Port")) {
portOpened();
}
if(cmd.equals("Send Data")) {
openButton.setEnabled(false);
//将光标等待
CursorpreviousCursor = getCursor();
setNewCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
//参数已经设置完成,然后再打开串口后将参数一并记录下来
configurationPanel.setParameters();
try{
connection.openConnection();
}catch (SerialConnectionException e1) {
//TODO Auto-generated catch block
e1.printStackTrace();
}
setNewCursor(previousCursor);
}
//Closes a port.
if(cmd.equals("Close Port")) {
portClosed();
}
//Sends a break signal to the port.
if(cmd.equals("Send Break")) {
connection.sendBreak();
}
//将接收到得数据清空处理
if(cmd.equals("Clear")) {
clear_data();
}
}
/**
* Toggles the buttons to an open port state.
*/
publicvoid portOpened() {
openButton.setEnabled(false);
closeButton.setEnabled(true);
breakButton.setEnabled(true);
sendButton.setEnabled(true);
clearButton.setEnabled(true);
}
/**
* Calls closeConnection on theSerialConnection and toggles the buttons to
* a closed port state.
*/
publicvoid portClosed() {
connection.closeConnection();
openButton.setEnabled(true);
closeButton.setEnabled(false);
breakButton.setEnabled(false);
sendButton.setEnabled(false);
clearButton.setEnabled(false);
}
publicvoid clear_data() {
messageAreaIn.setText("");
}
/**
* Sets the <code>Cursor</code> forthe application.
*
* @param c
* New <code>Cursor</code>
*/
privatevoid setNewCursor(Cursor c) {
setCursor(c);
messageAreaIn.setCursor(c);
messageAreaOut.setCursor(c);
}
/**
* Writes the current parameters to aconfiguration file of the
* java.properties style.
*/
//以文件的形式保存设置的参数
privatevoid writeFile(String path) {
PropertiesnewProps;
FileOutputStreamfileOut = null;
newProps= new Properties();
newProps.put("portName",parameters.getPortName());
newProps.put("baudRate",parameters.getBaudRateString());
newProps.put("flowControlIn",parameters.getFlowControlInString());
newProps.put("flowControlOut",parameters.getFlowControlOutString());
newProps.put("parity",parameters.getParityString());
newProps.put("databits",parameters.getDatabitsString());
newProps.put("stopbits",parameters.getStopbitsString());
try{
fileOut= new FileOutputStream(path);
} catch (IOException e) {
System.out.println("Couldnot open file for writiing");
}
newProps.save(fileOut,"Serial Demo poperties");
try{
fileOut.close();
}catch (IOException e) {
System.out.println("Couldnot close file for writiing");
}
}
/**
* Cleanly shuts down the applicaion. firstcloses any open ports and cleans
* up, then exits.
*/
privatevoid shutdown() {
connection.closeConnection();
System.exit(1);
}
/**
* Finds configuration file in arguments andcreates a properties object
* from that file.
*/
privatevoid parseArgs(String[] args) {
if(args.length < 1) {
return;
}
Filef = new File(args[0]);
if(!f.exists()) {
f= new File(System.getProperty("user.dir")
+System.getProperty("path.separator") + args[0]);
}
if(f.exists()) {
try{
FileInputStreamfis = new FileInputStream(f);
props= new Properties();
props.load(fis);
fis.close();
loadParams();
}catch (IOException e) {
}
}
}
/**
* Set the parameters object to the settings inthe properties object.
*/
privatevoid loadParams() {
parameters.setPortName(props.getProperty("portName"));
parameters.setBaudRate(props.getProperty("baudRate"));
parameters.setFlowControlIn(props.getProperty("flowControlIn"));
parameters.setFlowControlOut(props.getProperty("flowControlOut"));
parameters.setParity(props.getProperty("parity"));
parameters.setDatabits(props.getProperty("databits"));
parameters.setStopbits(props.getProperty("stopbits"));
setConfigurationPanel();
}
/**
* GUI element that holds the user changableelements for connection
* configuration.
*/
//参数控制面板的制作
classConfigurationPanel extends Panel implements ItemListener {
privateFrame parent;
privateLabel portNameLabel;
privateChoice portChoice;
privateLabel baudLabel;
privateChoice baudChoice;
privateLabel flowControlInLabel;
privateChoice flowChoiceIn;
privateLabel flowControlOutLabel;
privateChoice flowChoiceOut;
privateLabel databitsLabel;
privateChoice databitsChoice;
privateLabel stopbitsLabel;
privateChoice stopbitsChoice;
privateLabel parityLabel;
privateChoice parityChoice;
/**
* Creates and initilizes the configurationpanel. The initial settings
* are from the parameters object.
*/
publicConfigurationPanel(Frame parent) {
this.parent= parent;
setLayout(newGridLayout(4, 4));
portNameLabel= new Label("Port Name:", Label.LEFT);
add(portNameLabel);
portChoice= new Choice();
portChoice.addItemListener(this);
add(portChoice);
listPortChoices();
portChoice.select(parameters.getPortName());
baudLabel= new Label("Baud Rate:", Label.LEFT);
add(baudLabel);
baudChoice= new Choice();
baudChoice.addItem("300");
baudChoice.addItem("2400");
baudChoice.addItem("9600");
baudChoice.addItem("14400");
baudChoice.addItem("28800");
baudChoice.addItem("38400");
baudChoice.addItem("57600");
baudChoice.addItem("152000");
baudChoice.select(Integer.toString(parameters.getBaudRate()));
baudChoice.addItemListener(this);
add(baudChoice);
flowControlInLabel= new Label("Flow Control In:", Label.LEFT);
add(flowControlInLabel);
flowChoiceIn= new Choice();
flowChoiceIn.addItem("None");
flowChoiceIn.addItem("Xon/XoffIn");
flowChoiceIn.addItem("RTS/CTSIn");
flowChoiceIn.select(parameters.getFlowControlInString());
flowChoiceIn.addItemListener(this);
add(flowChoiceIn);
flowControlOutLabel= new Label("Flow Control Out:", Label.LEFT);
add(flowControlOutLabel);
flowChoiceOut= new Choice();
flowChoiceOut.addItem("None");
flowChoiceOut.addItem("Xon/XoffOut");
flowChoiceOut.addItem("RTS/CTSOut");
flowChoiceOut.select(parameters.getFlowControlOutString());
flowChoiceOut.addItemListener(this);
add(flowChoiceOut);
databitsLabel= new Label("Data Bits:", Label.LEFT);
add(databitsLabel);
databitsChoice= new Choice();
databitsChoice.addItem("5");
databitsChoice.addItem("6");
databitsChoice.addItem("7");
databitsChoice.addItem("8");
databitsChoice.select(parameters.getDatabitsString());
databitsChoice.addItemListener(this);
add(databitsChoice);
stopbitsLabel= new Label("Stop Bits:", Label.LEFT);
add(stopbitsLabel);
stopbitsChoice= new Choice();
stopbitsChoice.addItem("1");
stopbitsChoice.addItem("1.5");
stopbitsChoice.addItem("2");
stopbitsChoice.select(parameters.getStopbitsString());
stopbitsChoice.addItemListener(this);
add(stopbitsChoice);
parityLabel= new Label("Parity:", Label.LEFT);
add(parityLabel);
parityChoice= new Choice();
parityChoice.addItem("None");
parityChoice.addItem("Even");
parityChoice.addItem("Odd");
parityChoice.select("None");
parityChoice.select(parameters.getParityString());
parityChoice.addItemListener(this);
add(parityChoice);
}
/**
* Sets the configuration panel to the settingsin the parameters
* object.
*/
publicvoid setConfigurationPanel() {
portChoice.select(parameters.getPortName());
baudChoice.select(parameters.getBaudRateString());
flowChoiceIn.select(parameters.getFlowControlInString());
flowChoiceOut.select(parameters.getFlowControlOutString());
databitsChoice.select(parameters.getDatabitsString());
stopbitsChoice.select(parameters.getStopbitsString());
parityChoice.select(parameters.getParityString());
}
/**
* Sets the parameters object to the settingsin the configuration
* panel.
*/
publicvoid setParameters() {
parameters.setPortName(portChoice.getSelectedItem());
parameters.setBaudRate(baudChoice.getSelectedItem());
parameters.setFlowControlIn(flowChoiceIn.getSelectedItem());
parameters.setFlowControlOut(flowChoiceOut.getSelectedItem());
parameters.setDatabits(databitsChoice.getSelectedItem());
parameters.setStopbits(stopbitsChoice.getSelectedItem());
parameters.setParity(parityChoice.getSelectedItem());
}
/**
* Sets the elements for the portChoice fromthe ports available on the
* system. Uses an emuneration of comm portsreturned by
* CommPortIdentifier.getPortIdentifiers(),then sets the current choice
* to a mathing element in the parametersobject.
*/
voidlistPortChoices() {
CommPortIdentifierportId;
Enumerationen = CommPortIdentifier.getPortIdentifiers();
//iterate through the ports.
while(en.hasMoreElements()) {
portId= (CommPortIdentifier) en.nextElement();
if(portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
portChoice.addItem(portId.getName());
}
}
portChoice.select(parameters.getPortName());
}
/**
* Event handler for changes in the currentselection of the Choices. If
* a port is open the port can not be changed.If the choice is
* unsupported on the platform then the userwill be notified and the
* settings will revert to their pre-selectionstate.
*/
publicvoid itemStateChanged(ItemEvent e) {
//Check if port is open.
if(connection.isOpen()) {
//If port is open do not allow port to change.
if(e.getItemSelectable() == portChoice) {
//Alert user.
AlertDialogad = new AlertDialog(parent, "Port Open!",
"Portcan not", "be changed",
"whilea port is open.");
//Return configurationPanel to pre-choice settings.
setConfigurationPanel();
return;
}
//Set the parameters from the choice panel.
setParameters();
try{
//Attempt to change the settings on an open port.
connection.setConnectionParameters();
}catch (SerialConnectionException ex) {
//If setting can not be changed, alert user, return to
//pre-choice settings.
AlertDialogad = new AlertDialog(parent,
"UnsupportedConfiguration!",
"ConfigurationParameter unsupported,",
"selectnew value.",
"Returningto previous configuration.");
setConfigurationPanel();
}
}else {
//Since port is not open just set the parameter object.
setParameters();
}
}
}
/**
* Handles closing down system. Allowsapplication to be closed with window
* close box.
*/
classCloseHandler extends WindowAdapter {
SerialDemosd;
publicCloseHandler(SerialDemo sd) {
this.sd= sd;
}
publicvoid windowClosing(WindowEvent e) {
sd.shutdown();
}
}
}
SerialConnection.java
import javax.comm.*;
import java.io.*;
import java.awt.TextArea;
import java.awt.event.*;
import java.util.TooManyListenersException;
/**
* Aclass that handles the details of a serial connection. Reads from one
*TextArea and writes to a second TextArea. Holds the state of the connection.
*/
public class SerialConnection implementsSerialPortEventListener {
privateSerialDemo parent;
privateTextArea messageAreaOut;
privateTextArea messageAreaIn;
privateSerialParameters parameters;
privateOutputStream os;
privateInputStream is;
privateCommPortIdentifier portId;
privateSerialPort sPort;
privateboolean open;
/**
* Creates a SerialConnection object andinitilizes variables passed in as
* params.
*
* @param parent
* A SerialDemo object.
* @param parameters
* A SerialParameters object.
* @param messageAreaOut
* The TextArea that messages that are to besent out of the
* serial port are entered into.
* @param messageAreaIn
* The TextArea that messages comming into the serial port are
* displayed on.
*/
publicSerialConnection(SerialDemo parent, SerialParameters parameters,
TextAreamessageAreaOut, TextArea messageAreaIn) {
this.parent= parent;
this.parameters= parameters;
this.messageAreaOut= messageAreaOut;
this.messageAreaIn= messageAreaIn;
open= false;
}
publicvoid openPort() throws SerialConnectionException {
//Obtain a CommPortIdentifier object for the port you want to open.
}
/**
* Attempts to open a serial connection andstreams using the parameters in
* the SerialParameters object. If it isunsuccesfull at any step it returns
* the port to a closed state, throws a
*<code>SerialConnectionException</code>, and returns.
*
* Gives a timeout of 30 seconds on theportOpen to allow other applications
* to reliquish the port if have it open and nolonger need it.
*/
publicvoid openConnection() throws SerialConnectionException {
//Open the input and output streams for the connection. If they won't
//open, close the port before throwing an exception.
try{
portId= CommPortIdentifier.getPortIdentifier(parameters
.getPortName());
System.out.println("串口号是:" + portId.getName());
}catch (NoSuchPortException e) {
thrownew SerialConnectionException(e.getMessage());
}
//Open the port represented by the CommPortIdentifier object. Give
//the open call a relatively long timeout of 30 seconds to allow
//a different application to relinquish the port if the user
//wants to.
//打开需要的延迟,并获取commPort对象
//可以再打开sPort后多次得到发送与解析的数据
if(portId.isCurrentlyOwned()) {
sPort.close();
}
try{
sPort= (SerialPort) portId.open("SerialDemo", 30000);
System.out.println("sPort串口已打开");
}catch (PortInUseException e) {
thrownew SerialConnectionException(e.getMessage());
}
//Set the parameters of the connection. If they won't set, close the
//port before throwing an exception.
//再次设置连接时的参数
try{
setConnectionParameters();
}catch (SerialConnectionException e) {
sPort.close();
throwe;
}
try{
//发送的
os= sPort.getOutputStream();// OutputStream object that can be used
//to write to the port
//System.out.println("输入流是:"+os);
}catch (IOException e) {
sPort.close();
thrownew SerialConnectionException("Error opening i/o streams");
}
System.out.println("发送的指令在这里获取了" +messageAreaOut.getText());
Stringosstr = messageAreaOut.getText();
byte[]b = hexStringToBytes(osstr);
System.out.println("16进制的字符串已经导入到byte[],其中b[0]:" + b[0]);
try{
os.write(b);
System.out.println("os开始发送指令了");
}catch (IOException e) {
System.err.println("OutputStreamwrite error: " + e);
}
try{
//接收的
is= sPort.getInputStream();// InputStream object that can be used
//to read from the port
}catch (IOException e) {
sPort.close();
thrownew SerialConnectionException("Error opening i/o streams");
}
//Add this object as an event listener for the serial port.
try{
sPort.addEventListener(this);
System.out.println("对象sPort进行监听");
}catch (TooManyListenersException e) {
sPort.close();
thrownew SerialConnectionException("too many listeners added");
}
//Set notifyOnDataAvailable to true to allow event driven input.
//主要是这一部分起监听执行接收返回数据的作用
if(b[0] == 72 && b[1] == 69 && b[2] == 65 && b[3] == 68){
sPort.notifyOnDataAvailable(true);
}else{
messageAreaIn.append("\n---Dataanalytical failure!---\n");
}
//Set notifyOnBreakInterrup to allow event driven break handling.设置中断事件
sPort.notifyOnBreakInterrupt(true);
//Set receive timeout to allow breaking out of polling loop during
//input handling.
try{
sPort.enableReceiveTimeout(30);
}catch (UnsupportedCommOperationException e) {
}
//Add ownership listener to allow ownership event handling.
//portId.addPortOwnershipListener(this);
open= true;
}
//这是将16进形式的字符串要转化为byte[],就是要以两位的形式读取
publicstatic final byte[] hexStringToBytes(String s) {
byte[]bytes;
bytes= new byte[s.length() / 2];
for(int i = 0; i < bytes.length; i++) {
bytes[i]= (byte) Integer.parseInt(s.substring(2 * i, 2 * i + 2),
16);
}
returnbytes;
}
/**
* Sets the connection parameters to thesetting in the parameters object.
* If set fails return the parameters object toorigional settings and throw
* exception.
*/
publicvoid setConnectionParameters() throws SerialConnectionException {
System.out.println("开始设置参数");
//Save state of parameters before trying a set.
intoldBaudRate = sPort.getBaudRate();
intoldDatabits = sPort.getDataBits();
intoldStopbits = sPort.getStopBits();
intoldParity = sPort.getParity();
intoldFlowControl = sPort.getFlowControlMode();
//Set connection parameters, if set fails return parameters object
//to original state.
try{
sPort.setSerialPortParams(parameters.getBaudRate(),
parameters.getDatabits(),parameters.getStopbits(),
parameters.getParity());
}catch (UnsupportedCommOperationException e) {
parameters.setBaudRate(oldBaudRate);
parameters.setDatabits(oldDatabits);
parameters.setStopbits(oldStopbits);
parameters.setParity(oldParity);
thrownew SerialConnectionException("Unsupported parameter");
}
//Set flow control.
try{
sPort.setFlowControlMode(parameters.getFlowControlIn()
|parameters.getFlowControlOut());
}catch (UnsupportedCommOperationException e) {
thrownew SerialConnectionException("Unsupported flow control");
}
}
/**
* Close the port and clean up associatedelements.
*/
publicvoid closeConnection() {
//If port is alread closed just return.
if(!open) {
return;
}
//Check to make sure sPort has reference to avoid a NPE.
if(sPort != null) {
try{
//close the i/o streams.
os.close();
is.close();
}catch (IOException e) {
System.err.println(e);
}
//Close the port.
sPort.close();
//Remove the ownership listener.
//portId.removePortOwnershipListener(this);
}
open= false;
}
/**
* Send a one second break signal.
*/
publicvoid sendBreak() {
System.out.println("写入中断");
sPort.sendBreak(1000);
messageAreaIn.append("\n---BREAK RECEIVED ---\n");
}
/**
* Reports the open status of the port.
*
* @return true if port is open, false if portis closed.
*/
publicboolean isOpen() {
return open;
}
/**
* Handles SerialPortEvents. The two types ofSerialPortEvents that this
* program is registered to listen for areDATA_AVAILABLE and BI. During
* DATA_AVAILABLE the port buffer is read untilit is drained, when no more
* data is availble and 30ms has passed themethod returns. When a BI event
* occurs the words BREAK RECEIVED are writtento the messageAreaIn.
*/
/**
* Handles ownership events. If aPORT_OWNERSHIP_REQUESTED event is received
* a dialog box is created asking the user ifthey are willing to give up
* the port. No action is taken on other typesof ownership events.
*/
publicvoid ownershipChange(int type) {
if(type == CommPortOwnershipListener.PORT_OWNERSHIP_REQUESTED) {
PortRequestedDialogprd = new PortRequestedDialog(parent);
}
}
/**
* A class to handle<code>KeyEvent</code>s generated by the messageAreaOut.
* When a <code>KeyEvent</code>occurs the <code>char</code> that is
* generated by the event is read, converted toan <code>int</code> and
* writen to the<code>OutputStream</code> for the port.
*/
@Override
publicvoid serialEvent(SerialPortEvent e) {
//TODO Auto-generated method stub
//Create a StringBuffer and int to receive input data.
StringBufferinputBuffer = new StringBuffer();
System.out.println("进入到了SerialEvent 来读取返回的数据");
intnewData = 0;
//Determine type of event.
switch(e.getEventType()) {
//Read data until -1 is returned. If \r is received substitute
//\n for correct newline handling.
caseSerialPortEvent.DATA_AVAILABLE:
while(newData != -1) {
try{
newData= is.read();
if(newData == -1) {
break;
}
if('\r' == (char) newData) {
inputBuffer.append('\n');
}else {
inputBuffer.append(Integer
.toHexString(
((newData& 0x000000FF) | 0xFFFFFF00))
.substring(6).toUpperCase()
+" ");
}
}catch (IOException ex) {
System.err.println(ex);
return;
}
}
//Append received data to messageAreaIn.
messageAreaIn.append("Dataanalytical results:"+ new String(inputBuffer) + "\n");
System.out.println("看到了返回的数据"+messageAreaIn.getText());
break;
//If break event append BREAK RECEIVED message.
caseSerialPortEvent.BI:
messageAreaIn.append("\n---BREAK RECEIVED ---\n");
}
}
}
AlertDialog.java
import java.awt.*;
import java.awt.event.*;
/**
A single response modal alert dialog. Thisclass is configurable for message
and title. The width of the dialog will belonger than the longest message
line. When the OK button is pressed the dialog returns.
*/
public class AlertDialog extends Dialogimplements ActionListener {
/**
Creates a new <code>AlertDialog</code> with three lines ofmessage and
atitle.
@param parent Any Frame.
@paramtitle The title to appear in the border of the dialog.
@param lineOne The first line of the message in the dialog.
@param lineTwo The second line of the message in the dialog.
@param lineThree The third line of the message in the dialog.
*/
public AlertDialog(Frame parent,
String title,
String lineOne,
String lineTwo,
String lineThree) {
super(parent,title, true);
PanellabelPanel = new Panel();
labelPanel.setLayout(newGridLayout(3, 1));
labelPanel.add(newLabel(lineOne, Label.CENTER));
labelPanel.add(newLabel(lineTwo, Label.CENTER));
labelPanel.add(newLabel(lineThree, Label.CENTER));
add(labelPanel,"Center");
PanelbuttonPanel = new Panel();
ButtonokButton = new Button("OK");
okButton.addActionListener(this);
buttonPanel.add(okButton);
add(buttonPanel,"South");
FontMetricsfm = getFontMetrics(getFont());
intwidth = Math.max(fm.stringWidth(lineOne),
Math.max(fm.stringWidth(lineTwo),fm.stringWidth(lineThree)));
setSize(width+ 40, 150);
setLocation(parent.getLocationOnScreen().x+ 30,
parent.getLocationOnScreen().y + 30);
setVisible(true);
}
/**
Handles events from the OK button. When OK is pressed the dialog becomes
invisible, disposes of its self, and retruns.
*/
public void actionPerformed(ActionEvent e) {
setVisible(false);
dispose();
}
}
PortRequestedDialog.java
import java.awt.*;
import java.awt.event.*;
import javax.comm.*;
/**
Informs the user that an other applicationhas requested the port they
are using, and then asks if they arewilling to give it up. If the user
answers "Yes"
the port is closed and the dialog isclosed, if the user
answers "No" the dialog closesand no other action is taken.
*/
public class PortRequestedDialog
extends Dialog implements ActionListener {
private SerialDemo parent;
/**
Creates the a dialog with two buttons and a message asking the
user if
they are willing to give up the port they are using.
@param parent The main SerialDemo object.
*/
public PortRequestedDialog
(SerialDemo parent) {
super(parent,"Port Requested!", true);
this.parent= parent;
StringlineOne = "Your port has been requested";
String lineTwo = "by an other application.";
StringlineThree = "Do you want to give up your port?";
PanellabelPanel = new Panel();
labelPanel.setLayout(new GridLayout(3, 1));
labelPanel.add(newLabel(lineOne, Label.CENTER));
labelPanel.add(newLabel(lineTwo, Label.CENTER));
labelPanel.add(new Label(lineThree,Label.CENTER));
add(labelPanel,"Center");
PanelbuttonPanel = new Panel();
ButtonyesButton = new
Button("Yes");
yesButton.addActionListener(this);
buttonPanel.add(yesButton);
ButtonnoButton = new Button("No");
noButton.addActionListener
(this);
buttonPanel.add(noButton);
add(buttonPanel,"South");
FontMetricsfm = getFontMetrics(getFont());
intwidth = Math.max
(fm.stringWidth(lineOne),
Math.max(fm.stringWidth(lineTwo),fm.stringWidth(lineThree)));
setSize(width+ 40, 150);
setLocation
(parent.getLocationOnScreen().x + 30,
parent.getLocationOnScreen().y + 30);
setVisible(true);
}
/**
Handles events generated
by the buttons. If the yes button in pushedthe
port closing routine is called and the dialog is disposed of. If the"No"
button is pushed the dialog
is disposed of.
*/
public void actionPerformed(ActionEvent e) {
Stringcmd = e.getActionCommand();
if (cmd.equals("Yes")) {
parent.portClosed();
}
setVisible(false);
dispose();
}
}
SerialConnectionException.java
public class SerialConnectionExceptionextends Exception {
/**
*Constructs a <code>SerialConnectionException</code>
* with the specified detail message.
*
* @param s the detail message.
*/
public SerialConnectionException(Stringstr) {
super(str);
}
/**
* Constructs a <code>SerialConnectionException</code>
* with no
detail message.
*/
publicSerialConnectionException() {
super();
}
}
SerialParameters.java
import javax.comm.*;
/**
A class that stores parameters for serialports.
*/
public class SerialParameters {
private String portName;
private int baudRate;
privateint flowControlIn;
private int flowControlOut;
private int databits;
private int stopbits;
private int parity;
/**
Default constructer. Sets parameters to no port, 9600 baud, no flow
control, 8 data bits, 1 stop bit, no parity.
*/
public SerialParameters () {
this("",
9600,
SerialPort.FLOWCONTROL_NONE,
SerialPort.FLOWCONTROL_NONE,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE );
}
/**
Paramaterized constructer.
@param portName The name of the port.
@param baudRate The baud rate.
@param flowControlIn Type of flow control for receiving.
@param flowControlOut Type of flow control for sending.
@param databits The number of data bits.
@param stopbits The number of stop bits.
@param parity The type of parity.
*/
public SerialParameters(String portName,
int baudRate,
int flowControlIn,
int flowControlOut,
int databits,
intstopbits,
int parity) {
this.portName = portName;
this.baudRate = baudRate;
this.flowControlIn = flowControlIn;
this.flowControlOut = flowControlOut;
this.databits = databits;
this.stopbits = stopbits;
this.parity = parity;
}
/**
Sets port name.
@param portName New port name.
*/
public void setPortName(String portName) {
this.portName= portName;
}
/**
Gets port name.
@return Current port name.
*/
public String getPortName() {
returnportName;
}
/**
Sets baud rate.
@param baudRate New baud rate.
*/
public void setBaudRate(int baudRate) {
this.baudRate= baudRate;
}
/**
Sets baud rate.
@param baudRate New baud rate.
*/
public void setBaudRate(String baudRate) {
this.baudRate= Integer.parseInt(baudRate);
}
/**
Gets baud rate as an <code>int</code>.
@return Current baud rate.
*/
public int getBaudRate() {
returnbaudRate;
}
/**
Gets baud rate as a <code>String</code>.
@return Current baud rate.
*/
public String getBaudRateString() {
returnInteger.toString(baudRate);
}
/**
Sets flow control for reading.
@param flowControlIn New flow control for reading type.
*/
public void setFlowControlIn(int flowControlIn) {
this.flowControlIn= flowControlIn;
}
/**
Sets flow control for reading.
@param flowControlIn New flow control for reading type.
*/
public void setFlowControlIn(String flowControlIn) {
this.flowControlIn= stringToFlow(flowControlIn);
}
/**
Gets flow control for reading as an <code>int</code>.
@return Current flow control type.
*/
public int getFlowControlIn() {
returnflowControlIn;
}
/**
Gets flow control for reading as a <code>String</code>.
@return Current flow control type.
*/
public String getFlowControlInString() {
returnflowToString(flowControlIn);
}
/**
Sets flow control for writing.
@param flowControlIn New flow control for writing type.
*/
public void setFlowControlOut(int flowControlOut) {
this.flowControlOut= flowControlOut;
}
/**
Sets flow control for writing.
@param flowControlIn New flow control for writing type.
*/
public void setFlowControlOut(String flowControlOut) {
this.flowControlOut= stringToFlow(flowControlOut);
}
/**
Gets flow control for writing as an <code>int</code>.
@return Current flow control type.
*/
public int getFlowControlOut() {
returnflowControlOut;
}
/**
Gets flow control for writing as a <code>String</code>.
@return Current flow control type.
*/
public String getFlowControlOutString() {
returnflowToString(flowControlOut);
}
/**
Sets data bits.
@param databits New data bits setting.
*/
public void setDatabits(int databits) {
this.databits= databits;
}
/**
Sets data bits.
@param databits New data bits setting.
*/
public void setDatabits(String databits) {
if(databits.equals("5")) {
this.databits = SerialPort.DATABITS_5;
}
if(databits.equals("6")) {
this.databits = SerialPort.DATABITS_6;
}
if(databits.equals("7")) {
this.databits = SerialPort.DATABITS_7;
}
if(databits.equals("8")) {
this.databits = SerialPort.DATABITS_8;
}
}
/**
Gets data bits as an <code>int</code>.
@return Current data bits setting.
*/
public int getDatabits() {
returndatabits;
}
/**
Gets data bits as a <code>String</code>.
@return Current data bits setting.
*/
public String getDatabitsString() {
switch(databits){
case SerialPort.DATABITS_5:
return"5";
case SerialPort.DATABITS_6:
return"6";
caseSerialPort.DATABITS_7:
return"7";
case SerialPort.DATABITS_8:
return"8";
default:
return"8";
}
}
/**
Sets stop bits.
@param stopbits New stop bits setting.
*/
public void setStopbits(int stopbits) {
this.stopbits= stopbits;
}
/**
Sets stop bits.
@param stopbits New stop bits setting.
*/
public void setStopbits(String stopbits) {
if(stopbits.equals("1")) {
this.stopbits = SerialPort.STOPBITS_1;
}
if(stopbits.equals("1.5")) {
this.stopbits = SerialPort.STOPBITS_1_5;
}
if(stopbits.equals("2")) {
this.stopbits = SerialPort.STOPBITS_2;
}
}
/**
Gets stop bits setting as an <code>int</code>.
@return Current stop bits setting.
*/
public int getStopbits() {
returnstopbits;
}
/**
Gets stop bits setting as a <code>String</code>.
@return Current stop bits setting.
*/
public String getStopbitsString() {
switch(stopbits){
case SerialPort.STOPBITS_1:
return"1";
case SerialPort.STOPBITS_1_5:
return"1.5";
case SerialPort.STOPBITS_2:
return"2";
default:
return"1";
}
}
/**
Sets parity setting.
@param parity New parity setting.
*/
public void setParity(int parity) {
this.parity= parity;
}
/**
Sets parity setting.
@param parity New parity setting.
*/
public void setParity(String parity) {
if(parity.equals("None")) {
this.parity = SerialPort.PARITY_NONE;
}
if(parity.equals("Even")) {
this.parity = SerialPort.PARITY_EVEN;
}
if(parity.equals("Odd")) {
this.parity = SerialPort.PARITY_ODD;
}
}
/**
Gets parity setting as an <code>int</code>.
@return Current parity setting.
*/
public int getParity() {
returnparity;
}
/**
Gets parity setting as a <code>String</code>.
@return Current parity setting.
*/
public String getParityString() {
switch(parity){
case SerialPort.PARITY_NONE:
return"None";
case SerialPort.PARITY_EVEN:
return"Even";
case SerialPort.PARITY_ODD:
return"Odd";
default:
return"None";
}
}
/**
Converts a <code>String</code> describing a flow controltype to an
<code>int</code> type defined in<code>SerialPort</code>.
@param flowControl A <code>string</code> describing a flowcontrol type.
@return An <code>int</code> describing a flow control type.
*/
private int stringToFlow(String flowControl) {
if(flowControl.equals("None")) {
return SerialPort.FLOWCONTROL_NONE;
}
if(flowControl.equals("Xon/Xoff Out")) {
return SerialPort.FLOWCONTROL_XONXOFF_OUT;
}
if(flowControl.equals("Xon/Xoff In")) {
return SerialPort.FLOWCONTROL_XONXOFF_IN;
}
if(flowControl.equals("RTS/CTS In")) {
return SerialPort.FLOWCONTROL_RTSCTS_IN;
}
if(flowControl.equals("RTS/CTS Out")) {
return SerialPort.FLOWCONTROL_RTSCTS_OUT;
}
returnSerialPort.FLOWCONTROL_NONE;
}
/**
Converts an <code>int</code> describing a flow control typeto a
<code>String</code> describing a flow control type.
@param flowControl An <code>int</code> describing a flowcontrol type.
@return A <code>String</code> describing a flow controltype.
*/
String flowToString(int flowControl) {
switch(flowControl){
case SerialPort.FLOWCONTROL_NONE:
return"None";
case SerialPort.FLOWCONTROL_XONXOFF_OUT:
return"Xon/Xoff Out";
case SerialPort.FLOWCONTROL_XONXOFF_IN:
return"Xon/Xoff In";
case SerialPort.FLOWCONTROL_RTSCTS_IN:
return "RTS/CTS In";
case SerialPort.FLOWCONTROL_RTSCTS_OUT:
return"RTS/CTS Out";
default:
return"None";
}
}
}
2012_04_01_SerialPort_code_java