Forum: Mikrocontroller und Digitale Elektronik Ringpuffer besser programmieren?


von Thomas (Gast)


Lesenswert?

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;
}

von Wolfgang Horn (Gast)


Lesenswert?

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

von Malte (Gast)


Lesenswert?

>   if (schreibepointer >= SPEICHERGROESSE)
>      schreibepointer = 0;
>   if (schreibepointer >= SPEICHERGROESSE)
>      schreibepointer = 0;

Wozu zweimal? oder nur ein Copy&Paste Fehler ?

von jozi (Gast)


Lesenswert?

Hallo

schau mal bei den AVR Application Notes nach AVR306 (bitte pdf und
Source ansehen).

http://www.atmel.com

von Thomas (Gast)


Lesenswert?

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

von Rolf F. (Gast)


Lesenswert?

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.

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.