Ringpuffer besser programmieren?

Gast #168633
Hallo,
ich habe mir mal zwei Funktionen geschrieben, um Werte in einen
Ringspeicher zu schreiben und zu lesen.
Leider habe ich bei meinem Programm einen Speicherplatz im Ringpuffer
verschwendet, um beim Lesen feststellen zu können dass der Speicher
leer ist.
Mit ein paar zusätzlichen Abfragen und einer zusätzlichen Variablen in
der Funktion zum Ringspeicher auslesen ließe sich das sicher anders
realisieren. Wenn der Ringspeicher jedoch nur 16Bit Integer-Werte
aufnimmt, ist ja abzuwägen was im Speicher weniger Platz wegnimmt.
Vielleich hat ja jemand noch einen eleganteren Code.
Hier meine Funktionen:

void schreibeRS(int wert)
{
   ringspeicher[schreibepointer++] = wert;
   if (schreibepointer >= SPEICHERGROESSE)
      schreibepointer = 0;
   if (schreibepointer >= SPEICHERGROESSE)
      schreibepointer = 0;
   if (schreibepointer == lesepointer)
      lesepointer++;
   if (lesepointer >= SPEICHERGROESSE)
      lesepointer = 0;
}
//-------------------------------------------------
int leseRS(void)
{
   int wert;
   wert = ringspeicher[lesepointer];
   if (lesepointer == schreibepointer)
      wert = LEER;
   else
   {
      lesepointer++;
      if (lesepointer >= SPEICHERGROESSE)
         lesepointer = 0;
   }
   return wert;
}
Gast #168634
Hi, Thomas,

wozu selber erfinden, was andere schon zur Perfektion gebracht und
nicht geschützt haben?
Googele mal unter "UART", "header", "trail", da findest wohl
Dutzende Beispiele. Besonders elegant fand ich die, wo der Ringpuffer
eine Größe von 4, 8, 16, 32 etc. hat, weil Du den Überlauf mit einer
Und-Funktion verhindern kannst.

Ciao
Wolfgang
Gast #168635
>   if (schreibepointer >= SPEICHERGROESSE)
>      schreibepointer = 0;
>   if (schreibepointer >= SPEICHERGROESSE)
>      schreibepointer = 0;

Wozu zweimal? oder nur ein Copy&Paste Fehler ?
Gast #168637
Danke, die Atmel Application Note sieht gut aus. Der Puffer funktioniert
da so wie von Wolfgang oben schon beschrieben.
Allerdings muss man erst zweimal hinschauen um das zu verstehen. Bei
meinem "Prototypen" ist es ja etwas einfacher zu verstehen, aber halt
nicht ganz so sparsam.

@Malte: Ist wohl irgendwie doppelt reingerutscht, die doppelte Abfrage
macht natürlich keinen Sinn.

Thomas
Gast #168638
Ich benutze für solche Puffer Makros:

// increment for ring buffer index (0..n-1), also works with start
value -1
#   define mc_RING_INC(x, n) {++(x); (x) %= (n);}

// next value at incrementing
#   define mc_RING_NEXT(x, n) (((x)+1)%(n))

// decrement for ring buffer index (0..n-1), also works with start
value < 0
#   define mc_RING_DEC(x, n) {if((x) > 0)  --(x); else (x)=(n)-1;}

// value before last increment
#   define mc_RING_LAST(x, n) ( (x) ? ((x)-1) : ((n)-1))

Für einen AD-Wandler in einem ARM9 habe ich damit mal Ringpuffer (für
jeden Kanal einen) programmiert, aus deren 64-Bit-Index man jeweils
sowohl den letzten Ringpufferindex als auch dessen Zeit (seit dem
Treiber-Start) entnehmen kann, damit man die Daten aus den Puffern
lückenlos und ohne Überlappungen auslesen kann.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 21 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.