Also wird der Wert von einer Rotuine berechnet und anschliessend in einen Pufferspeicher abgelegt. Eine andere, zeit- und interruptgesteuerte Routine holt dann ein Zeichen nach dem anderen aus dem Puffer und versendet das Zeichen.
Einfach und effizient zu implementieren ist ein Fifo, dessen Größe einer 2er-Potenz entspricht (8, 16, 32, 64...). Dann kann der Indexüberlauf einfach mit einer Bitmaske abgehandelt werden. Hier ist so eine Implementierung:
#define BLEN (16)
#define BMSK (BLEN-1)
typedef struct {
volatile unsigned char w;
volatile unsigned char r;
unsigned char d[BLEN]; // die Daten sind nicht volatil, sie können sich
} fifotyp; // nur geändert haben, wenn der Index sich ändert
fifotyp fifo;
:
:
// Fifo schreiben
if ((fifo.w - fifo.r)&BMSK==BMSK) {
// Fehlerbehandlung: Fifo ist voll
}
else {
// Zeichen eintragen
fifo.d[fifo.w&BMSK] = din;
fifo.w++;
}
// Fifo lesen
if (fifo.w != fifo.r) { // Fifo belegt?
// Zeichen auslesen
dout = fifo.d[fifo.r&BMSK];
fifo.r++;
}
// Fifo leeren
if (cleanupfifo=1) {
fifo.w = fifo.r;
}
Fifo leer: Wenn der Leseindex r gleich dem Schreibindex w ist, dann ist der Fifo leer.
Fifo belegt: Wenn der Leseindex r ungleich dem Schreibindex w ist, dann ist ein Zeichen im Puffer. Wichtig ist, dass zuerst das Zeichen in den Puffer geschrieben (bzw. gelesen) wird, und erst dann der Index erhöht wird. Denn sonst könnte nach der Indexmanipulation ein Interrupt kommen, und weil das Zeichen noch nicht eingetragen wurde, wird mit falschen Daten gearbeitet.
Fifo Reset: Das Rücksetzen des Fifos erfolgt einfach, indem der Leseindex gleich dem Schreibindex gesetzt wird. Allerdings sollte dieser Vorgang nur im Notfall angewendet werden, denn dabei gehen garantiert irgendwelche gespeicherte Informationen verloren.
Fifo Overrun: Ob noch ein Zeichen in den Fifo passt oder dieser voll ist, kann durch die Subtraktion des Schreibindex w vom Leseindex r überprüft werden. Ist das Ergebnis dieser Operation -1, dann kann kein weiteres Zeichen gespeichert werden.