Java/Comunicazione seriale: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
sintassi colorata
Riga 113:
 
Enumerating and selecting the desired port identifier is typically done in one loop:
<source lang=java>
 
import javax.comm.*;
import java.util.*;
Riga 154:
//
// Use port identifier for acquiring the port
//</source>
...
 
Riga 160:
 
Once a port identifier has been found, it can be used to acquire the desired port:
<source lang=java>
 
//
// Use port identifier for acquiring the port
Riga 177:
// Now we are granted exclusive access to the particular serial
// port. We can configure it and obtain input and output streams.
//</source>
...
 
Riga 185:
 
As part of the initialization process the Input and Output streams for communication will be configured in the example.
<source lang=java>
 
import java.io.*;
...
 
<br>
//
// Set all the params.
Riga 198:
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
 
<br>
//
// Open the input Reader and output stream. The choice of a
Riga 208:
BufferedReader is = null;
PrintStream os = null;
 
<br>
try {
is = new BufferedReader(new InputStreamReader(port.getInputStream()));
Riga 216:
}
os = new PrintStream(port.getOutputStream(), true);
 
<br>
// New Linuxes rely on UNICODE and it is possible you need to specify here the encoding scheme to be used
// for example :
Riga 226:
// performReadWriteCode();
//
<br>
//
 
// It is very important to close output/input streams as well as the port.
// Otherwise Java, driver and OS resources are not released.
Riga 233:
if (is != null) is.close();
if (os != null) os.close();
if (port != null) port.close();</source>
 
=== Simple Data Transfer ===
Riga 248:
* Explain how to mix binary and character I/O over the same stream
* Fix the example to use streams}}
--[[utente:Wim_b|Wim b]]-[[discussioni utente:Wim_b|talk]] 13:39, 30 lug 2007 (CEST)
 
// Write to the output
os.print("AT");
Riga 305:
 
==== Setting up a serial Event Handler ====
<source lang=java>
 
import javax.comm.*;
 
</br>
/**
* Listener to handle all serial port events.
Riga 319:
*/
class SerialListener implements SerialPortEventListener {
</br>
/**
* Handle serial events. Dispatches the event to event-specific
Riga 326:
*/
public void serialEvent(SerialPortEvent event){
</br>
//
// Dispatch event to individual methods, to avoid a
Riga 335:
outputBufferEmpty(event);
break;
</br>
case SerialPortEvent.DATA_AVAILABLE:
dataAvailable(event);
break;
 
</br>
/* Other events, not implemented here ->
case SerialPortEvent.BI:
breakInterrupt(event);
break;
 
</br>
case SerialPortEvent.CD:
carrierDetect(event);
break;
 
</br>
case SerialPortEvent.CTS:
clearToSend(event);
break;
 
</br>
case SerialPortEvent.DSR:
dataSetReady(event);
break;
 
</br>
case SerialPortEvent.FE:
framingError(event);
break;
 
</br>
case SerialPortEvent.OE:
overrunError(event);
break;
 
</br>
case SerialPortEvent.PE:
parityError(event);
Riga 372:
break;
<- other events, not implemented here */
 
</br>
}
}
 
</br>
/**
* Handle output buffer empty events.
Riga 385:
// Implement writing more data here
}
 
</br>
/**
* Handle data available events.
Riga 395:
}
}
</source>
 
Once the listener is implemented, it can be used to listen to particular serial port events. To do so, an instance of the listener needs to be added to the serial port. Further, the reception of each event type needs to be requested individually.
<source lang=java>
 
SerialPort port = ...;
...
//
Riga 405:
// after an event is enabled.
...
 
</br>
//
// Typically, if the current class implements the SerialEventListener interface
Riga 413:
//
port.addEventListener(new SerialListener());
 
</br>
//
// Enable the events we are interested in
Riga 419:
port.notifyOnDataAvailable(true);
port.notifyOnOutputEmpty(true);
 
</br>
/* other events not used in this example ->
port.notifyOnBreakInterrupt(true);
Riga 430:
port.notifyOnRingIndicator(true);
<- other events not used in this example */
</br></source>
 
 
Riga 452:
 
A ring buffer as such is nothing special, and has no special properties regarding threading. It is just that this simple data structure is used here to provide data buffering. The implementation is done so that access to this data structure has been made thread safe.
<source lang=java>
 
/**
* Synchronized ring buffer.
Riga 458:
**/
public '''synchronized''' class RingBuffer {
<br />
/** internal buffer to hold the data **/
protected byte buffer[];
 
<br />
/** size of the buffer **/
protected int size;
 
<br />
/** current start of data area **/
protected int start;
 
<br />
/** current end of data area **/
protected int end;
 
<br />
<br />
/**
* Construct a RingBuffer with a default buffer size of 1k.
Line 478 ⟶ 477:
this(1024);
}
 
<br />
/**
* Construct a RingBuffer with a certain buffer size.
Line 488 ⟶ 487:
clear();
}
 
<br />
/**
* Clear the buffer contents. All data still in the buffer is lost.
Line 497 ⟶ 496:
start = end = 0;
}
 
<br />
/**
* Return used space in buffer. This is the size of the
Line 514 ⟶ 513:
: end - start + size;
}
 
<br />
/**
* Return unused space in buffer. Note: While the value is
Line 529 ⟶ 528:
: start - end;
}
 
<br />
/**
* Write as much data as possible to the buffer.
Line 538 ⟶ 537:
return write(data, 0, data.length);
}
 
<br />
/**
* Write as much data as possible to the buffer.
Line 550 ⟶ 549:
int remain = n;
// @todo check if off is valid: 0= <= off < data.length; throw exception if not
 
<br />
int i = Math.min(remain, (end < start ? start : buffer.length) - end);
if(i > 0) {
Line 558 ⟶ 557:
end += i;
}
 
<br />
i = Math.min(remain, end >= start ? start : 0);
if(i > 0 ) {
Line 567 ⟶ 566:
return n - remain;
}
 
<br />
<br />
/**
* Read as much data as possible from the buffer.
Line 577 ⟶ 575:
return read(data, 0, data.length);
}
 
<br />
/**
* Read as much data as possible from the buffer.
Line 589 ⟶ 587:
int remain = n;
// @todo check if off is valid: 0= <= off < data.length; throw exception if not
 
<br />
int i = Math.min(remain, (end < start ? buffer.length : end) - start);
if(i > 0) {
Line 598 ⟶ 596:
if(start >= buffer.length) start = 0;
}
 
<br />
i = Math.min(remain, end >= start ? 0 : end);
if(i > 0 ) {
Line 608 ⟶ 606:
}
}
</source>
 
With this ring buffer one can now hand over data from one thread to another in a controlled way. Any other thread-safe, non-blocking mechanism would also do. The key point here is that the write does not block when the buffer is full and also does not block when there is nothing to read.
 
Line 618 ⟶ 616:
 
The skeleton event listener proposed a method <code>outputBufferEmpty()</code>, which could be implemented as it follows.
<source lang=java>
 
RingBuffer dataBuffer = ... ;
 
<br />
/**
* Handle output buffer empty events.
Line 631 ⟶ 629:
{{TODO}}
}</source>
 
 
Line 643 ⟶ 641:
 
The following example assumes that the data's destination is some file. Whenever data becomes available it is fetched from the serial port and written to the file. This is an extremely simplified view, because in reality one would need to check the data for an end-of-file indication to, for example, return to the modem command mode.
<source lang=java>
 
import javax.comm.*;
 
<br>
...
InputStream is = port.getInputStream();
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("out.dat"));
 
<br>
/**
* Listen to port events
*/
class FileListener implements SerialPortEventListener {
 
</br>
/**
* Handle serial event.
Line 660 ⟶ 658:
void serialEvent(SerialPortEvent e) {
SerialPort port = (SerialPort) e.getSource();
 
</br>
//
// Discriminate handling according to event type
Line 666 ⟶ 664:
switch(e.getEventType()) {
case SerialPortEvent.DATA_AVAILABLE:
 
</br>
//
// Move all currently available data to the file
Line 686 ⟶ 684:
if (is != null) is.close();
if (port != null) port.close();
}</source>
 
=== Handling multiple Ports in one Application ===