Forum: Mikrocontroller und Digitale Elektronik fifo oder nicht fifo ist die Frage


von fifi (Gast)


Lesenswert?

Guten Tag,
Habe mir den Artikel 
https://www.mikrocontroller.net/articles/FIFO#FIFO_als_Bibliothek 
durchgelesen.
Dabei ist mir aber noch einiges nicht ganz klar.
Ich benötige so eine Fifo um ständig 64 Messwerte zu haben.
Wenn ein Fehler auftretet möchte ich die neusten 64 Messwerte speichern.
 Im Artikel steht
1
Für die Behandlung des Pufferüberlaufs gibt es zwei Methoden, nichts tun und Fehler zurück geben oder ältesten Puffer-Inhalt verwerfen (read+1).

Das wäre ja genau das was ich haben  will oder?
Verstehe aber nicht was es mit read+1 gemeint ist?
Kann mir das Bitte jemand erklären?
Dnake

von c-hater (Gast)


Lesenswert?

fifi schrieb:

> Dabei ist mir aber noch einiges nicht ganz klar.

Hmm, naja...

> Ich benötige so eine Fifo um ständig 64 Messwerte zu haben.
> Wenn ein Fehler auftretet möchte ich die neusten 64 Messwerte speichern.

Kein Problem, einfach den gesamten FIFO abspeichern. Das Einzige, was 
zusätzlich nützlich sein könnte: Zusätztlich den aktuellen 
Schreibzeiger/-index zu speichern.

Wenn du das Konzept eines Ringpuffers wirklich verstanden hättest, wäre 
dir das automatisch klar gewesen...

von Eine Antwort (Gast)


Lesenswert?

read+1 ?

Der Pointer zum lesen markiert gleichzeitig das Ende des freien 
Bereiches.

Also - du überschreibst die Daten, die als nächstes gelesen werden und 
setzt den Lesepointer auf die zweitältesten Daten.

read+1 bedeutet einfach den Lesepointer auf das nächste Element setzen, 
obwohl die Daten nicht gelesen wurden.

von fifi (Gast)


Lesenswert?

Eine Antwort schrieb:
> read+1 bedeutet einfach den Lesepointer auf das nächste Element setzen,
> obwohl die Daten nicht gelesen wurden.

Also meim füllen des Fifo wenn er voll ist read+1?
Sorry ich bin etwas verwirrt mit dieser Geschichte.

Danke für die Hilfe

von fifi (Gast)


Lesenswert?

Also ich möchte ständig aufzeichnen und nicht nur einmal die 64 Mal.
Danke für die Hilfe

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

c-hater schrieb:
> Wenn du das Konzept eines Ringpuffers wirklich verstanden hättest
Der Groschen ist noch immer nicht gefallen.

fifi schrieb:
> Also ich möchte
Du möchtest eigentlich nur einen Puffer, der die 64 neuesten Werte 
enthält. Du brauchst den Leseteil des Fifos gar nicht.
Du verwendest nur den Teil, der in das Ringpuffer-Array schreibt.
Und wenn Du alle Daten auslesen willst, dann ist das ein memcpy() für 64 
Elemente.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

c-hater schrieb:
> Wenn du das Konzept eines Ringpuffers wirklich verstanden hättest
Der Groschen ist noch immer nicht gefallen.

fifi schrieb:
> Also ich möchte
Du möchtest eigentlich nur einen Puffer, der die 64 neuesten Werte 
enthält. Du brauchst den Leseteil des Fifos gar nicht.
Du verwendest nur den Teil, der in das Ringpuffer-Array schreibt.
Und wenn Du alle Daten auslesen willst, dann ist das ein memcpy() für 64 
Elemente.

Falls ich das nicht richtig verstanden habe, wären noch ein paar Worte 
sinnvoll: woher kommen die Daten, was soll mit ihnen geschehen und wohin 
gehen die dann?

von Tilo R. (joey5337) Benutzerseite


Lesenswert?

Die verlinkte Implementierung erlaubt ggf. nicht, dass der Puffer 
überläuft bzw. älteste Werte automatisch überschrieben werden. Wenn der 
Puffer voll ist, werden keine neuen Werte gespeichert, du willst aber 
die ältesten verwerfen.

Grundsätzlich empfehle ich zum Ringpuffer, das mal auf einem Papier 
aufzuzeichnen.
Ein Array, mit z.B. 5 Elementen, dazu dann ein Schreib und ein 
Lesezeiger (ruhig mit 2 Farben direkt auf die Zelle zeigen, oder 
oberhalb der Arrayzeile den Schreibzeiger, unterhalb den Lesezeiger.

Und dann empfehle ich, von Hand alle notwendigen Operationen 
durchzuspielen. Auch so Mini-Funktionen wie die Abfrage, ob der Puffer 
voll oder leer ist, wie viele Elemente gespeichert sind etc. Die kann 
man später inline oder als Makro programmieren. Dabei wirklich auf dem 
Papier was ins Array schreiben und neue Zeiger malen, wenn sie geändert 
wurden.

Und dann kann man mehrere Varianten ausprobieren: zeigt z.B. der 
Schreibzeiger auf das Feld, das zuletzt geschrieben wurde oder auf das, 
das als nächstes beschrieben wird? Auch Fälle probieren, wo ein Zeiger 
den Wraparound schon gemacht hat, der andere noch nicht.

Wenn man es mal verstanden hat ist ein Ringpuffer einfach. Aber die 
Off-By-One-Fehlermöglichkeiten sind trickreich, vom-Hirn-ins-Terminal 
ohne den Papier-Zwischenschritt geht oft schief.

von fifi (Gast)


Lesenswert?

Tilo R. schrieb:
> Die verlinkte Implementierung erlaubt ggf. nicht, dass der Puffer
> überläuft bzw. älteste Werte automatisch überschrieben werden. Wenn der
> Puffer voll ist, werden keine neuen Werte gespeichert, du willst aber
> die ältesten verwerfen.

Guten Morgen.
Ja genau das möchte ich. Und ich möchte die Daten in der richtigen 
Reihenfolge bekommen. Also benötige ich die Auslese Funktion schon.

Werde mir nachher deinen Tipp mit dem Aufzeichnen zu Herzen nehmen.
Obwohl ich das schon gemacht habe. Aber wer weiß und der Groschen fällt 
dann.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

fifi schrieb:
> Ja genau das möchte ich.
Wie gesagt: interessant ist eigentlich nicht, was du möchtest, sondern 
was für die Lösung der Aufgabe nötig ist.

Denn mir ist z.B. nicht klar, was passieren soll, wenn du nur 57 neue 
Werte im Puffer hast, aus dem dann aber 64 Werte auslesen willst...


fifi schrieb:
> Und ich möchte die Daten in der richtigen Reihenfolge bekommen. Also
> benötige ich die Auslese Funktion schon.
Also brauchst du nur den Puffer und den Schreibindex. Der Schreibindex 
zeigt immer auf das nächste zu schreibende Element und damit automatisch 
auch auf das älteste Element im Array. Und beim Auslesen musst du genau 
dort anfangen und dann 64 Werte abholen.

Meine Implementation des Puffers nach deiner aktuellen Beschreibung sähe 
dann so aus:
1
#include <stdio.h>
2
3
int mem[64];
4
int idx;
5
6
void write (int d) {
7
   mem[idx&0x3f] = d;  // die Maskierung mit 0x3f erledigt den Wrap-Around
8
   idx++;              
9
}
10
11
void read(int* d) { 
12
   int p = idx;               // der idx zeigt auf das älteste Element, 
13
   for (int i=0; i<64; i++) { // ab dort 64 Zeichen auslesen
14
      *d = mem[p&0x3f];
15
      d++;
16
      p++;
17
   }
18
}
19
20
int main () {
21
   int buf[64];
22
23
   for (int i=0; i<321; i++) // Buffer mit 320 Werten "überfüllen"
24
      write(i);
25
  
26
   read((int*)buf);  
27
28
   for (int i = 0; i<64; i++) 
29
      printf("%d  ",buf[i]);
30
31
    return 0;
32
}

Dort kannst du selber damit herumspielen: 
https://onlinegdb.com/nHteb6zUZ

: Bearbeitet durch Moderator
von fifi (Gast)


Lesenswert?

Lothar M. schrieb:
> Dort kannst du selber damit herumspielen:
> https://onlinegdb.com/nHteb6zUZ

Das ist ja cool.
Werde den Code jetzt testen gebe Feedback
Danke

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.