Comunicare Seriala
Comunicare Seriala
Most projects that deal with hardware and devices, needs to communicate with
them using the COM port of the PC or Server. For example if there is a modem
that is connected to a server via its COM port and the Java program has to
read the output of the modem then the Java program has to read the COM port
for any incoming data.
This sample Java program can be used to Read from a COM port for incoming
data and process it. Note that you will need to change the Port number to
COM1 or COM2 or any other ports as required.
Also if you are using unix based machines then you will have to uncomment the
/dev/term/a instead of COM.
import java.io.*;
import java.util.*;
import javax.comm.*;
InputStream inputStream;
SerialPort serialPort;
Thread readThread;
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("SimpleReadApp", 2000);
} catch (PortInUseException e)
{System.out.println(e);}
try {
inputStream = serialPort.getInputStream();
} catch (IOException e) {System.out.println(e);}
try {
serialPort.addEventListener(this);
} catch (TooManyListenersException e)
{System.out.println(e);}
serialPort.notifyOnDataAvailable(true);
try {
serialPort.setSerialPortParams(9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
} catch (UnsupportedCommOperationException e)
{System.out.println(e);}
readThread = new Thread(this);
readThread.start();
}
public void run() {
try {
Thread.sleep(20000);
} catch (InterruptedException e)
{System.out.println(e);}
}
try {
while (inputStream.available() > 0) {
int numBytes =
inputStream.read(readBuffer);
}
System.out.print(new String(readBuffer));
} catch (IOException e) {System.out.println(e);}
break;
}
}
}
Comunicarea pe porturile seriale n java
Lucrarea 0. Comunicarea pe porturile seriale n java
1. Obiectivul lucrrii
2. Noiuni preliminare
2.1 Instruciuni de instalare Java Communication API
3. Listare porturi disponibile
4. Deschiderea unui port serial
5. Deschiderea unui port paralel
6. Scrierea i citirea de pe un port
6.1 Scriere i citire n mod sincron
6.2 Scriere i citire n mod asincron
1. Obiectivul lucrrii
2. Noiuni preliminare
n cadrul librriei Communication API sunt definite dou clase principale: clasa
SerialPort i clasa ParallelPort. Aceste clase motenesc clasa CommPort
(aceasta este o clas abstract) i definesc cele dou tipuri de porturi ce pot fi
accesate prin intermediul Communication API.
import javax.comm.*;
import java.io.*;
import java.util.*;
while(portList.hasMoreElements()){
CommPortIdentifier cp = (CommPortIdentifier)portList.nextElement();
System.err.println("Port name="+cp.getName());
//System.out.println(portList.nextElement().toString());
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Main.testComm();
}
}
4. Deschiderea unui port serial
Aceast seciune prezint modul n care poate fi deschis un port serial pentru
a realiza operaii de scriere i citire.
package commtest;
import javax.comm.*;
import java.io.*;
DataInputStream is;
PrintStream os;
serialPort.setSerialPortParams(BAUD, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
try {
is = new DataInputStream(serialPort.getInputStream());
} catch (IOException e) {
System.err.println("Can't open input stream: write-only");
}
os = new PrintStream(serialPort.getOutputStream(), true);
System.out.println("Ready to do read / write on port "+serialPort.getName());
}
}
5. Deschiderea unui port paralel
Aceast seciune prezint modul n care poate fi deschis un port serial pentru
a realiza operaii de scriere i citire.
package commtest;
import javax.comm.*;
import java.io.*;
DataInputStream is;
PrintStream os;
try {
is = new DataInputStream(serialPort.getInputStream());
} catch (IOException e) {
System.err.println("Can't open input stream: write-only");
}
os = new PrintStream(serialPort.getOutputStream(), true);
System.out.println("Ready to do read / write on port "+serialPort.getName());
}
package commtest;
import javax.comm.*;
import java.io.*;
serialPort.setSerialPortParams(BAUD, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
try {
is = new BufferedReader(new InputStreamReader((serialPort.getInputStream())));
} catch (IOException e) {
System.err.println("Can't open input stream: write-only");
}
os = new PrintStream(serialPort.getOutputStream(), true);
System.out.println("Ready to do read / write on port "+serialPort.getName());
}
send("MESSAGE 1");
if(!expect("OK 1"))
System.err.println("ERROR: Device has not sent back expected response.");
send("MESSAGE 2" );
if(!expect("OK 2"))
System.err.println("ERROR: Device has not sent back expected response.");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
is.close();
os.close();
}
serialPort.setSerialPortParams(BAUD, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
try {
is = new BufferedReader(new InputStreamReader((serialPort.getInputStream())));
} catch (IOException e) {
System.err.println("Can't open input stream: write-only");
}
os = new PrintStream(serialPort.getOutputStream(), true);
System.out.println("Ready to do read / write on port "+serialPort.getName());
serialPort.notifyOnDataAvailable(true);
serialPort.addEventListener(this);
}
Abstract: A How-To on accessing serial ports in the Windows environment using the Java
Communications API
Introduction
In this article well discuss using the Java Communications API to access COM ports in
Windows. The following example is taken from a java program that reads barcodes from an
omni-directional scanner. It checks the barcode against a remote object and, based on the
results, sends codes to a PLC (program logic controller) to fire a diverter arm.
Using the API, you can create an object for each port (enumeration), open ports, resolve
port contention between Java objects, and perform asynchronous and synchronous
communications.
comm.jar
win32com.dll
javax.comm.properties
For the JVM to recognize the serial ports, proper placement of these files is important. Ive
read lots of messages on the boards, tried various ways of placing these files in a Windows
system, and have found the following installation methods to be effective:
%JAVA_HOME%/jre/lib/ext
%JAVA_HOME%/bin
%JAVA_HOME%/jre/bin
%windir%System32
%JAVA_HOME%/lib
%JAVA_HOME%/jre/lib
Once youve done this, compile and execute one of the sample programs provided by Sun
to ensure that youve properly installed everything.
Next you need to add the comm.jar package to JBuilder. This is relatively simple. On the
JBuilder Menu across the top click on Project
The Program
The example were going to use reads input from one serial port (COM4) and sends data to
another serial port (COM 5) (note: You do not have to use COM4 and COM5. Use any
available serial ports on your system.). Our program is named ComContol.
ComControl
package serialio;
InputStream inputStream;
OutputStream outputStream;
SerialPort serialPort1, serialPort2;
Thread readThread;
protected String divertCode = "10";
static String TimeStamp;
To access the comm.jar package we must first import javax.comm.*. We also import
java.io.* to gain access to the InputStream and OutputStream classes. Finally, we import
the java.util.* class to provide access to the EventListener class.
Notice that ComControl implements the Runnable interface. We implement the Runnable
interface because we want the class to run as a thread. There are two ways we could do
this. First, we could extend the Thread class. In doing so, we would have access to all of
public methods of Thread. Or, we could implement the Runnable interface. It provides a
single abstract method called run(). Using one or the other really depends on what were
doing. In this example were overriding the run() method and not any other methods of
Thread. A good rule of thumb is to implement Runnable when overriding the only run()
method, extend Thread to access its other methods.
Note: We didnt need to import a package for the Thread class because it is part of the
java.lang package.
We now need to set up some variables. Since were using two serial ports, we define the
objects portId1 and portId2 with a datatype of CommPortIdentifier. CommPortIdentifier is the
main class that controls access to serial ports. CommPortIdentifier is used to negotiate with
the driver to discover which communication ports are available and then select a port for
opening. It uses methods in other classes like CommPort and SerialPort to communicate to
the port.
We must also set up an InputStream (inputStream) to read the data coming through the
serial port and an OutputStream (outputStream) to send data to the serial port. The
InputStream class is part of the java.io package.
main() method
try {
portId1 = CommPortIdentifier.getPortIdentifier("COM4");
portId2 = CommPortIdentifier.getPortIdentifier("COM5");
ComControl reader = new ComControl();
}
catch
(Exception e) {
TimeStamp = new java.util.Date().toString();
System.out.println(TimeStamp + ": COM4 " + portId1);
System.out.println(TimeStamp + ": COM5 " + portId2);
System.out.println(TimeStamp + ": msg1 - " + e);
}
};
Lets now take a look at the main() method. We start by putting everything in a try block. We
do this because it is possible that the serial ports were looking for do not exist or are busy.
Inside our try block we attempt to get a Handle for the serial ports (portId1 and portId2) by
executing the ComPortIdentifier.getPortIdentifer() method. This method returns a
ComPortIdentifier object and throws a NoSuchPortException if a particular port does not
exist. The last thing we do in the try block is instantiate ComControl using a constructor that
we will talk about in the following section.
After the try block, we have a catch block. In this example, were catching any Exception
that may occur. We could just have easily caught just the NoSuchPortException. The first
thing we do is load the current date and time into a string called TimeStamp. While its not
necessary to do this, it is useful if for logging to an external file.
Using System.out.println(), we display the port identifier objects for COM4 and COM5. We
want to see if either of the port identifier objects are nulla null value indicates that the
program could not find the port. Finally, we display the exception itself.
ComControl() Constructor
public ComControl() {
try {
TimeStamp = new java.util.Date().toString();
serialPort1 = (SerialPort) portId1.open("ComControl",
2000);
System.out.println(TimeStamp + ": " + portId1.getName()
+ " opened for scanner input");
serialPort2 = (SerialPort) portId2.open("ComControl",
2000);
System.out.println(TimeStamp + ": " + portId2.getName()
+ " opened for diverter output");
} catch (PortInUseException e) {}
try {
inputStream = serialPort1.getInputStream();
} catch (IOException e) {}
try {
serialPort1.addEventListener(this);
} catch (TooManyListenersException e) {}
serialPort1.notifyOnDataAvailable(true);
try {
serialPort1.setSerialPortParams(9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
serialPort1.setDTR(false);
serialPort1.setRTS(false);
serialPort2.setSerialPortParams(9600,
SerialPort.DATABITS_7,
SerialPort.STOPBITS_1,
SerialPort.PARITY_EVEN);
} catch (UnsupportedCommOperationException e) {}
We start the ComControl() constructor with a try block. In this case, we are instantiating
SerialPort objects (serialPort1 and serialPort2) by executing portId1s and portId2s open()
method. Recall portId1 and portId2 are ComPortIdentifier objects and the open() method
comes from ComPortIdentifier. It throws the PortInUseException. In our example, well
ignore this exception and go on. In the real world you would most likely want to handle this
exception.
The open() method were using in this example has two parameters. The first parameter is a
string containing the name of the application opening or owning the port. This parameter is
useful in resolving contention issues between programs. The next parameter is an int
containing the timeout in milliseconds that the open() method will wait for a port to open.
We have added a couple of System.out.println() methods that use our TimeStamp string
and a ComPortIdentifier.getName() method (portId1.getName() and portId2.getName()
where portId1 and portId2 are ComPortIdentifier objects). The getName() method returns
the system assigned name of the serial port. In our case this should be COM4 and COM5.
In order to check for incoming data on the serialPort1 object we just created, we need to call
its .getInputStream() method. Well see the results of this event later. The .getInputStream()
method throws an IOException. We want to ignore this because often the serial port will be
idle.
After weve opened the ports, we need to register an EventListener for COM4. Again we
create a try block and invoke the addEventListener() method within it. The exception for the
addEventListener is TooManyListenersExeception. In this case, thats not an issue so well
ignore the exception.
Next we define the properties of our serial ports using the setSerialPortParams() method.
This method allows us to set the flow control, data bits, parity, and stop bits. We are
concerned only with the Data bits, stop bits, and parity. The device that were using in this
case does not have the Data Terminal Ready (DTR) wire pinned out so well use the
serialPort1.setDTR() method to set DTR to false. Our input device doesnt support Request
To Send (RTS) handshaking either, well use the serialPort1.setRTS() method to set RTS to
false.
Note: The settings I use in this example apply to the serial devices Im connecting to. Your
serial devices may (probably) have completely different settings. Check with your device
manual for the proper settings.
The last thing we want to do is to create a Thread. This We define a Thread (readThread)
and execute its start() method.
run() method
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
}
As noted earlier, we implemented the Runnable interface. Now, we override the run()
method of that interface. Reviewing the code above youll see that were calling the
Thread.sleep() method within a trycatch block. The sleep() method is actually an
overloaded method within the Thread class. It can be passed either a long that represents
the time in milliseconds that you want the thread to cease execution, or it can be passed a
long and an int that represents the time in milliseconds plus the time in nanoseconds that a
thread will sleep. We want the thread to sleep for 100 milliseconds.
serialEvent() method
Now that weve built the code to create and start a SerialPortEventListener object
(ComControl), we need to do something when events occur. Thus, we override the
SerialPortEventListener interfaces abstract serialEvent() method. This method is executed
when a serial event occurs. It receives a SerialPortEvent object.
break;
}
}
Looking at the code youll see a set of case statements. We test these case statements by
using event.getEventType() method; where event is the object that was passed to the
serialEvent() method. The getEventType() method returns an int.
Although Ive defined several cases here, primarily to show you everything you can check
for in a serial event, in this example you and I are only interested in 2 events:
SerialPortEvent.OUTPUT_BUFFER_EMPTY and SerialPortEvent.DATA_AVAILABLE. In the
case of OUTPUT_BUFFER_EMPTY, we want to break out of the serialEvent method
altogether because weve finished receiving data. In the case of DATA_AVAILABLE, we
want examine the data coming from our serialPort1 object and, if its the data were looking
for, send data to our serialPort2 object.
If you refer back to the ComControl() constructor, youll see that we attempted to read bytes
into our static inputStream object using the serialPort1.getInputStream() method. In the
DATA_AVAILABLE case well interpret the bytes coming from the serialPort1 object. Weve
created a while block that reads each byte coming in from serialPort1 and tests to see
whether the byte is an ANSI character 10 (linefeed) or an ANSI character 13 (carriage
control). The reason we do this is because the input device is sending a carriage
control/linefeed at the end of each transmission. If the inputStream byte is anything other
than a carriage control/linefeed we want to store in our readBuffer object.
If the first character of the scannedInput string is an F then we want to send a signal to the
serialPort2 object. Serial port objects can be written to using OutputStream objects. First,
we obtain serialPort2s OutputStream by calling the getOutptStream() method. Previously
we created a String called divertCode that contains 10. In our example, a divertCode of
10 tells a Program Logic Controller (PLC) to fire a particular diverter. Since we want to
write this string to our serialPort2 object, we use the .write() method of the OutputStream
object outputStream. The write() method is looking for an array of byte datatypes, so we
have to convert the divertCode string to a byte array using the .getbBytes() method. After
weve written to serialPort2, we log the information and break out of the serialEvent method
and wait for the next serialEvent to occur.