www.mikrocontroller.net

Serielle Schnittstelle unter Java

Unter Java entwickelte Programme können ohne weiteres zwischen verschiedenen Betriebssystemen portiert werden und bietet gleichzeitig eine leistungsfähige grafische Oberfläche. Aufgrund der portabilität ist die Kommunikation mit Hardware schwierig, da die Systeme sich hier erheblich unterscheiden, das gilt auch für die beliebte serielle Schnittstelle.

Aus diesem Grund wurde die Comm-API geschaffen, über die der Zugriff auf die serielle Schnittstelle und den Parallelport möglich wird. Neben der offiziellen Umsetzung von SUN gibt es alternativ RXTX. In der aktuellen Windows-Installation von SUN-Java sind die notwendigen Dateien bereits enthalten.

Inhaltsverzeichnis

[Bearbeiten] Installation

[Bearbeiten] RXTX

Bei vielen Distributionen bereits als vorinstalliertes Paket vorhanden, ansonsten manuell nach Anleitung in README-Datei ausführen. (Ubuntu 7.10 hat zwar ein Installationspaket dabei, jedoch nur in den für Anwendungen mit graphischer Oberfläche ungeeigneten Gnu Compiler Java. Für SUN-Java (mit Swing) muss auch dort RXTX von Hand installiert werden.)

Einbinden der Bibliothek erfolgt mit:

import gnu.io.*;

[Bearbeiten] SUN

Download von sun.com und Installation nach Anleitung (nicht mehr für Windows)

Einbinden der Bibliothek erfolgt mit:

import javax.comm.*;

[Bearbeiten] Erste Schritte

Das nachfolgende einfache Programm dient erstmal als Funktionstest, erfolgt die Ausführung ohne Fehlermeldungen wurden die Bibliotheken korrekt installiert. Der Zweck des Programms ist das Auslesen aller verfügbaren Serialports über eine while-Schleife.


import gnu.io.*; // RXTX
// import javax.comm.*; // SUN
import java.util.Enumeration;


public class ErsteSchritte {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		System.out.println("Program started");
		
		//System.out.println(java.library.path);
	    CommPortIdentifier serialPortId;
	    //static CommPortIdentifier sSerialPortId;
	    Enumeration enumComm;
	    //SerialPort serialPort;

	    enumComm = CommPortIdentifier.getPortIdentifiers();
	    while (enumComm.hasMoreElements()) {
	     	serialPortId = (CommPortIdentifier) enumComm.nextElement();
	     	if(serialPortId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
	    		System.out.println(serialPortId.getName());
	    	}
	    }

		System.out.println("Finished successfully");
	}
}
 
Ausgaben auf der Console
Program started
Stable Library
=========================================
Native lib Version = RXTX-2.1-7
Java lib Version   = RXTX-2.1-7
/dev/ttyS1
/dev/ttyS0
Finished successfully
Experimental:  JNI_OnLoad called.
 

[Bearbeiten] Mögliche Fehlermeldungen

java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path thrown
  while loading gnu.io.RXTXCommDriver
Exception in thread "main" java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path

→ Die Binaries (.so/.dll) befinden sich nicht im richtigen Verzeichnis

Exception in thread "main" java.lang.NoClassDefFoundError: gnu/io/CommPortIdentifier
	at ErsteSchritte.main(ErsteSchritte.java:21)

→ Die Schnittstelle (.jar) befindet sich nicht im richtigen Verzeichnis

[Bearbeiten] Einfaches Beispiel für Daten senden

[Bearbeiten] Programmablauf

main()
* neues Objekt erzeugen
* neuen Thread erzeugen

ENDE main()


Einfachsenden.run():

Serialport öffnen
	→ EinfachSenden.oeffnen(String portName)

        * CommPortIdentifier für ''portName'' finden
	* Port öffnen
	* OutputStream für Port auslesen
	* Parameter der Schnittstelle festlegen
	
+-> sende ''Testnachricht\n'' über serielle Schnittstelle
|   Warte 1s
+-- zähle von herunter von ''secondsRuntime'' bis 0

Serialport schließen

ENDE run()

 

weiter mit Beispiel EinfachEmpfangen

[Bearbeiten] Quelltext

import gnu.io.*;

import java.io.IOException;
//import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
//import java.util.TooManyListenersException;

//import OeffnenUndSenden.serialPortEventListener;



public class EinfachSenden implements Runnable {

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		Runnable runnable = new EinfachSenden();
		new Thread(runnable).start();
		System.out.println("main finished");
	}
	
	/**
	 * 
	 */

	CommPortIdentifier serialPortId;
	Enumeration enumComm;
	SerialPort serialPort;
	OutputStream outputStream;
	// InputStream inputStream;
	Boolean serialPortGeoeffnet = false;

	int baudrate = 9600;
	int dataBits = SerialPort.DATABITS_8;
	int stopBits = SerialPort.STOPBITS_1;
	int parity = SerialPort.PARITY_NONE;
	String portName = "/dev/ttyS0";
	
	int secondsRuntime = 20;

	public EinfachSenden()
	{
		System.out.println("Konstruktor: EinfachSenden");
	}
	
    public void run()
    {
        Integer secondsRemaining = secondsRuntime;
        if (oeffneSerialPort(portName) != true)
        	return;
        
	while (secondsRemaining > 0) {
		System.out.println("Sekunden verbleiben: " + secondsRemaining.toString() );
		secondsRemaining--;
		try {
			Thread.sleep(1000);
		} catch(InterruptedException e) { }
		sendeSerialPort("Testnachricht\n");
		}
	schliesseSerialPort();
}
    
	boolean oeffneSerialPort(String portName)
	{
		Boolean foundPort = false;
		if (serialPortGeoeffnet != false) {
			System.out.println("Serialport bereits geöffnet");
			return false;
		}
		System.out.println("Öffne Serialport");
		enumComm = CommPortIdentifier.getPortIdentifiers();
		while(enumComm.hasMoreElements()) {
			serialPortId = (CommPortIdentifier) enumComm.nextElement();
			if (portName.contentEquals(serialPortId.getName())) {
				foundPort = true;
				break;
			}
		}
		if (foundPort != true) {
			System.out.println("Serialport nicht gefunden: " + portName);
			return false;
		}
		try {
			serialPort = (SerialPort) serialPortId.open("Öffnen und Senden", 500);
		} catch (PortInUseException e) {
			System.out.println("Port belegt");
		}
		try {
			outputStream = serialPort.getOutputStream();
		} catch (IOException e) {
			System.out.println("Keinen Zugriff auf OutputStream");
		}
/*
		try {
			inputStream = serialPort.getInputStream();
		} catch (IOException e) {
			System.out.println("Keinen Zugriff auf InputStream");
		}
		try {
			serialPort.addEventListener(new serialPortEventListener());
		} catch (TooManyListenersException e) {
			System.out.println("TooManyListenersException für Serialport");
		}
		serialPort.notifyOnDataAvailable(true);
*/
		try {
			serialPort.setSerialPortParams(baudrate, dataBits, stopBits, parity);
		} catch(UnsupportedCommOperationException e) {
			System.out.println("Konnte Schnittstellen-Paramter nicht setzen");
		}
		
		serialPortGeoeffnet = true;
		return true;
	}

	void schliesseSerialPort()
	{
		if ( serialPortGeoeffnet == true) {
			System.out.println("Schließe Serialport");
			serialPort.close();
			serialPortGeoeffnet = false;
		} else {
			System.out.println("Serialport bereits geschlossen");
		}
	}
	
	void sendeSerialPort(String nachricht)
	{
		System.out.println("Sende: " + nachricht);
		if (serialPortGeoeffnet != true)
			return;
		try {
			outputStream.write(nachricht.getBytes());
		} catch (IOException e) {
			System.out.println("Fehler beim Senden");
		}
	}
}
 

[Bearbeiten] Einfaches Beispiel für Daten empfangen

[Bearbeiten] Programmablauf

main()
* neues Objekt erzeugen
* neuen Thread erzeugen

ENDE main()


EinfachEmpfangen.run()

Serialport öffnen
	→ EinfachEmpfangen.oeffnen(String portName)

        * CommPortIdentifier für ''portName'' finden
	* Port öffnen
	* InputStream für Port auslesen
	* EventListener für Serialport einrichten
	* Event für eingehende Daten freischalten
	* Parameter der Schnittstelle festlegen
	
+-> Warte 1s (asynchrone Events parallel)
|   
+-- zähle von von ''secondsRuntime'' bis 0 herunter

Serialport schließen

ENDE run()


EinfachEmpfangen.serialPortEventListener:
→ Event ausgelöst durch eingehende Daten

* Eingehende Daten einlesen
	→ EinfachEmpfangen.serialPortDatenVerfuegbar
	* Puffer ''data'' anlegen
	+->  wiederhole solange Daten im InputStream warten
	|    Daten aus InputStream in Puffer ''data'' übertragen
	+--  Eingehende Daten über Console ausgeben
	
 

weiter mit Beispiel für GUI

[Bearbeiten] Quelltext

import gnu.io.*;

import java.io.IOException;
import java.io.InputStream;
//import java.io.OutputStream;
import java.util.Enumeration;
import java.util.TooManyListenersException;

//import OeffnenUndSenden.serialPortEventListener;



public class EinfachEmpfangen implements Runnable {

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		Runnable runnable = new EinfachEmpfangen();
		new Thread(runnable).start();
		System.out.println("main finished");
	}
	
	/**
	 * 
	 */

	CommPortIdentifier serialPortId;
	Enumeration enumComm;
	SerialPort serialPort;
	//OutputStream outputStream;
	InputStream inputStream;
	Boolean serialPortGeoeffnet = false;

	int baudrate = 9600;
	int dataBits = SerialPort.DATABITS_8;
	int stopBits = SerialPort.STOPBITS_1;
	int parity = SerialPort.PARITY_NONE;
	String portName = "/dev/ttyUSB0";
	
	int secondsRuntime = 60;

	public EinfachEmpfangen()
	{
		System.out.println("Konstruktor: EinfachSenden");
	}
	
    public void run()
    {
        Integer secondsRemaining = secondsRuntime;
        if (oeffneSerialPort(portName) != true)
        	return;
        
		while (secondsRemaining > 0) {
			System.out.println("Sekunden verbleiben: " + secondsRemaining.toString() );
			secondsRemaining--;
			try {
				Thread.sleep(1000);
			} catch(InterruptedException e) { }
		}
		schliesseSerialPort();
    	
    }
    
	boolean oeffneSerialPort(String portName)
	{
		Boolean foundPort = false;
		if (serialPortGeoeffnet != false) {
			System.out.println("Serialport bereits geöffnet");
			return false;
		}
		System.out.println("Öffne Serialport");
		enumComm = CommPortIdentifier.getPortIdentifiers();
		while(enumComm.hasMoreElements()) {
			serialPortId = (CommPortIdentifier) enumComm.nextElement();
			if (portName.contentEquals(serialPortId.getName())) {
				foundPort = true;
				break;
			}
		}
		if (foundPort != true) {
			System.out.println("Serialport nicht gefunden: " + portName);
			return false;
		}
		try {
			serialPort = (SerialPort) serialPortId.open("Öffnen und Senden", 500);
		} catch (PortInUseException e) {
			System.out.println("Port belegt");
		}
/*
		try {
			outputStream = serialPort.getOutputStream();
		} catch (IOException e) {
			System.out.println("Keinen Zugriff auf OutputStream");
		}
*/
		try {
			inputStream = serialPort.getInputStream();
		} catch (IOException e) {
			System.out.println("Keinen Zugriff auf InputStream");
		}
		try {
			serialPort.addEventListener(new serialPortEventListener());
		} catch (TooManyListenersException e) {
			System.out.println("TooManyListenersException für Serialport");
		}
		serialPort.notifyOnDataAvailable(true);
		try {
			serialPort.setSerialPortParams(baudrate, dataBits, stopBits, parity);
		} catch(UnsupportedCommOperationException e) {
			System.out.println("Konnte Schnittstellen-Paramter nicht setzen");
		}
		
		serialPortGeoeffnet = true;
		return true;
	}

	void schliesseSerialPort()
	{
		if ( serialPortGeoeffnet == true) {
			System.out.println("Schließe Serialport");
			serialPort.close();
			serialPortGeoeffnet = false;
		} else {
			System.out.println("Serialport bereits geschlossen");
		}
	}
	
	void serialPortDatenVerfuegbar() {
		try {
			byte[] data = new byte[150];
			int num;
			while(inputStream.available() > 0) {
				num = inputStream.read(data, 0, data.length);
				System.out.println("Empfange: "+ new String(data, 0, num));
			}
		} catch (IOException e) {
			System.out.println("Fehler beim Lesen empfangener Daten");
		}
	}

	class serialPortEventListener implements SerialPortEventListener {
		public void serialEvent(SerialPortEvent event) {
			System.out.println("serialPortEventlistener");
			switch (event.getEventType()) {
			case SerialPortEvent.DATA_AVAILABLE:
				serialPortDatenVerfuegbar();
				break;
			case SerialPortEvent.BI:
			case SerialPortEvent.CD:
			case SerialPortEvent.CTS:
			case SerialPortEvent.DSR:
			case SerialPortEvent.FE:
			case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
			case SerialPortEvent.PE:
			case SerialPortEvent.RI:
			default:
			}
		}
	}	
}

 

[Bearbeiten] Beispiel mit der graphischen Oberfläche Swing

Ein noch nicht ganz vollständiges Beispiel zeigt den Zugriff auf die serielle Schnittstelle über eine graphische Oberfläche. Die Funktionen sind nahezu identisch mit den zuvor aufgeführten Beispielen.

weiter mit Weblinks

[Bearbeiten] Quelltext


import gnu.io.*;
// import javax.comm.*; 
import java.util.Enumeration;
import java.io.*;
import java.util.TooManyListenersException;

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

// TODO Dialog zur Konfiguration der Schnittstellenparameter


public class OeffnenUndSenden extends JFrame{

	/**
	 * Variable declaration
	 */
	CommPortIdentifier serialPortId;
	Enumeration enumComm;
	SerialPort serialPort;
	OutputStream outputStream;
	InputStream inputStream;
	Boolean serialPortGeoeffnet = false;

	int baudrate = 9600;
	int dataBits = SerialPort.DATABITS_8;
	int stopBits = SerialPort.STOPBITS_1;
	int parity = SerialPort.PARITY_NONE;
	
	/**
	 * Fenster
	 */
	JPanel panel = new JPanel (new GridBagLayout());
	
	JPanel panelSetup = new JPanel(new GridBagLayout());
	JPanel panelKommuniziere = new JPanel(new GridBagLayout());
	
	JComboBox auswahl = new JComboBox();
	JButton oeffnen = new JButton("Öffnen");
	JButton schliessen = new JButton("Schließen");
	JButton aktualisieren = new JButton("Aktualisieren");
	
	JButton senden = new JButton("Nachricht senden");
	JTextField nachricht = new JTextField();
	JCheckBox echo = new JCheckBox("Echo");
	
	JTextArea empfangen = new JTextArea();
	JScrollPane empfangenJScrollPane = new JScrollPane();
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println("Programm gestartet");
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				new OeffnenUndSenden();
			}
		});
		System.out.println("Main durchlaufen");
	}
	
	/**
	 * Konstruktor
	 */
	public OeffnenUndSenden()
	{
		System.out.println("Konstruktor aufgerufen");
		initComponents();
	}
	protected void finalize()
	{
		System.out.println("Destruktor aufgerufen");
	}
    
	void initComponents()
	{
		GridBagConstraints constraints = new GridBagConstraints();
		
		setTitle("Öffnen und Senden");
		addWindowListener(new WindowListener());
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		// TODO schliessen.setEnabled(false);
		// TODO senden.setEnabled(false);
		
		oeffnen.addActionListener( new oeffnenActionListener());
		schliessen.addActionListener(new schliessenActionListener());
		aktualisieren.addActionListener(new aktualisierenActionListener());
		senden.addActionListener(new sendenActionListener());
		
		empfangenJScrollPane.setVerticalScrollBarPolicy(
				JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		empfangenJScrollPane.setHorizontalScrollBarPolicy(
				JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		empfangenJScrollPane.setViewportView(empfangen);
		
		constraints.gridx = 0;
		constraints.gridy = 0;
		constraints.fill = GridBagConstraints.HORIZONTAL;
		constraints.weightx = 0.5;
		constraints.insets = new Insets(5, 5, 5, 5);
		panelSetup.add(auswahl, constraints);
		
		constraints.gridx = 1;
		constraints.weightx = 0;
		panelSetup.add(oeffnen, constraints);
		
		constraints.gridx = 2;
		panelSetup.add(schliessen, constraints);
		
		constraints.gridx = 3;
		panelSetup.add(aktualisieren, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 0;
		constraints.weightx = 1;
		panel.add(panelSetup, constraints);

		constraints.gridx = 0;
		constraints.gridy = 0;
		constraints.weightx = 0;
		panelKommuniziere.add(senden, constraints);
		
		constraints.gridx = 1;
		constraints.weightx = 1;
		panelKommuniziere.add(nachricht, constraints);
		
		constraints.gridx = 2;
		constraints.weightx = 0;
		panelKommuniziere.add(echo, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 1;
		constraints.weightx = 1;
		panel.add(panelKommuniziere, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 2;
		constraints.weightx = 1;
		constraints.weighty = 1;
		constraints.fill = GridBagConstraints.BOTH;
		panel.add(empfangenJScrollPane, constraints);
		
		aktualisiereSerialPort();
		
		add(panel);
		pack();
		setSize(600, 300);
		setVisible(true);

		System.out.println("Fenster erzeugt");
	}
	
	boolean oeffneSerialPort(String portName)
	{
		Boolean foundPort = false;
		if (serialPortGeoeffnet != false) {
			System.out.println("Serialport bereits geöffnet");
			return false;
		}
		System.out.println("Öffne Serialport");
		enumComm = CommPortIdentifier.getPortIdentifiers();
		while(enumComm.hasMoreElements()) {
			serialPortId = (CommPortIdentifier) enumComm.nextElement();
			if (portName.contentEquals(serialPortId.getName())) {
				foundPort = true;
				break;
			}
		}
		if (foundPort != true) {
			System.out.println("Serialport nicht gefunden: " + portName);
			return false;
		}
		try {
			serialPort = (SerialPort) serialPortId.open("Öffnen und Senden", 500);
		} catch (PortInUseException e) {
			System.out.println("Port belegt");
		}
		try {
			outputStream = serialPort.getOutputStream();
		} catch (IOException e) {
			System.out.println("Keinen Zugriff auf OutputStream");
		}
		try {
			inputStream = serialPort.getInputStream();
		} catch (IOException e) {
			System.out.println("Keinen Zugriff auf InputStream");
		}
		try {
			serialPort.addEventListener(new serialPortEventListener());
		} catch (TooManyListenersException e) {
			System.out.println("TooManyListenersException für Serialport");
		}
		serialPort.notifyOnDataAvailable(true);
		try {
			serialPort.setSerialPortParams(baudrate, dataBits, stopBits, parity);
		} catch(UnsupportedCommOperationException e) {
			System.out.println("Konnte Schnittstellen-Paramter nicht setzen");
		}
		
		serialPortGeoeffnet = true;
		return true;
	}
	
	void schliesseSerialPort()
	{
		if ( serialPortGeoeffnet == true) {
			System.out.println("Schließe Serialport");
			serialPort.close();
			serialPortGeoeffnet = false;
		} else {
			System.out.println("Serialport bereits geschlossen");
		}
	}
	
	void aktualisiereSerialPort()
	{
		System.out.println("Akutalisiere Serialport-Liste");
		if (serialPortGeoeffnet != false) {
			System.out.println("Serialport ist geöffnet");
			return;
		}
		auswahl.removeAllItems();
		enumComm = CommPortIdentifier.getPortIdentifiers();
		while(enumComm.hasMoreElements()) {
			serialPortId = (CommPortIdentifier) enumComm.nextElement();
			if (serialPortId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
				System.out.println("Found:" + serialPortId.getName());
				auswahl.addItem(serialPortId.getName());
			}
		}
	}
	
	void sendeSerialPort(String nachricht)
	{
		System.out.println("Sende: " + nachricht);
		if (serialPortGeoeffnet != true)
			return;
		try {
			outputStream.write(nachricht.getBytes());
		} catch (IOException e) {
			System.out.println("Fehler beim Senden");
		}
	}
	
	void serialPortDatenVerfuegbar() {
		try {
			byte[] data = new byte[150];
			int num;
			while(inputStream.available() > 0) {
				num = inputStream.read(data, 0, data.length);
				System.out.println("Empfange: "+ new String(data, 0, num));
				empfangen.append(new String(data, 0, num));
			}
		} catch (IOException e) {
			System.out.println("Fehler beim Lesen empfangener Daten");
		}
	}
	
	class WindowListener extends WindowAdapter {
		public void windowClosing(WindowEvent event) {
			schliesseSerialPort();
			System.out.println("Fenster wird geschlossen");
		}
	}
	
	class oeffnenActionListener implements ActionListener {
		public void actionPerformed (ActionEvent event) {
			System.out.println("oeffnenActionListener");
			// TODO sperre Button Öffnen und Aktualisieren
			// TODO entsperre Nachricht senden und Schließen
			oeffneSerialPort((String) auswahl.getSelectedItem());
		}
	}
	class schliessenActionListener implements ActionListener {
		public void actionPerformed (ActionEvent event) {
			System.out.println("schliessenActionListener");
			// TODO entsperre Button Öffnen und Aktualisieren
			// TODO sperre Nachricht senden und Schließen
			schliesseSerialPort();
		}
	}
	class aktualisierenActionListener implements ActionListener {
		public void actionPerformed (ActionEvent event) {
			System.out.println("aktualisierenActionListener");
			aktualisiereSerialPort();
		}
	}
	class sendenActionListener implements ActionListener {
		public void actionPerformed (ActionEvent event) {
			System.out.println("sendenActionListener");
			if ( echo.isSelected() == true)
				empfangen.append(nachricht.getText() + "\n");
			sendeSerialPort(nachricht.getText() + "\n");
		}
	}
	/**
	 * 
	 */
	class serialPortEventListener implements SerialPortEventListener {
		public void serialEvent(SerialPortEvent event) {
			System.out.println("serialPortEventlistener");
			switch (event.getEventType()) {
			case SerialPortEvent.DATA_AVAILABLE:
				serialPortDatenVerfuegbar();
				break;
			case SerialPortEvent.BI:
			case SerialPortEvent.CD:
			case SerialPortEvent.CTS:
			case SerialPortEvent.DSR:
			case SerialPortEvent.FE:
			case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
			case SerialPortEvent.PE:
			case SerialPortEvent.RI:
			default:
			}
		}
	}	
}
 

[Bearbeiten] Siehe auch

[Bearbeiten] Weblinks

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net