brauche Hilfe bei Erweiterungen von Fifo-Funktionalitäten

Gast #4019238
Lesenswert?

Hi,

ich bin hier auf einen megacoolen Fifo gestossen:

Quelle: 
http://www.mikrocontroller.net/articles/FIFO#FIFO_mit_C-Pr.C3.A4prozessor
1
#define BUFFER_SIZE 16 // muss 2^n betragen (8, 16, 32, 64 ...)
2
#define BUFFER_MASK (BUFFER_SIZE-1) // Klammern auf keinen Fall vergessen
3
 
4
struct Buffer {
5
  uint8_t data[BUFFER_SIZE];
6
  uint8_t read; // zeigt auf das Feld mit dem ältesten Inhalt
7
  uint8_t write; // zeigt immer auf leeres Feld
8
} buffer = {{}, 0, 0};
9
 
10
uint8_t BufferIn(uint8_t byte)
11
{
12
  uint8_t next = ((buffer.write + 1) & BUFFER_MASK);
13
  if (buffer.read == next)
14
    return FAIL;
15
  buffer.data[buffer.write] = byte;
16
  // buffer.data[buffer.write & BUFFER_MASK] = byte; // absolut Sicher
17
  buffer.write = next;
18
  return SUCCESS;
19
}
20
 
21
uint8_t BufferOut(uint8_t *pByte)
22
{
23
  if (buffer.read == buffer.write)
24
    return FAIL;
25
  *pByte = buffer.data[buffer.read];
26
  buffer.read = (buffer.read+1) & BUFFER_MASK;
27
  return SUCCESS;
28
}

Ich möchte gerne noch zwei Funktionalitäten dazu haben - Fifo leeren und 
Anzahl Elemente im Fifo ausrechnen.

Dazu habe ich mir folgendes ausgedacht:
1
void BufferClear()
2
{
3
    buffer.read = buffer.write = 0;
4
}
5

6
uint8_t BufferAnzahl()
7
{
8
    int16_t hilf;
9
    hilf = buffer.write-buffer.read;
10
    
11
    // keine Werte vorhanden:
12
    if (hilf=0) {
13
        return (0);
14
     }
15
    
16
    // hilf > 0
17
    if (hilf>0) {
18
       return (hilf);
19
    }
20
    
21
    if (hilf<0) {
22
        return (BUFFER_SIZE-hilf);
23
    }
24
}

Bei der clear-Funktion braucht man glaub ich nicht weiter diskutieren - 
so ist sie auf alle Fälle leer. Aber bei der Ermittlung der Anzahl der 
Elemente in dem Fifo bin ich mir unsicher. Ist die Lösung so brauchbar 
mit den drei if-Abfragen - oder gibt es eine einfachere Variante? Ich 
habe die Hilfsvariable extra als int-Variable genommen, die doppelt so 
groß ist, wie die uint8_t-Variable, damit beim Subtrahieren auch ein 
negativer Wert funktioniert. Meint ihr, das das so funktioniert, was ich 
mir ausgedacht hab?
#4019252
Lesenswert?

Anfänger schrieb:
> oder gibt es eine einfachere Variante?
1
uint8_t BufferAnzahl()
2
{
3
  return (buffer.write - buffer.read) & (BUFFER_SIZE - 1);
4
}
BUFFER_SIZE muss eine Zweierpotenz mit ganzzahlige Exponenten sein.

gonso schrieb:
> Nach jedem return fehlt noch ein break, damit die Funktion vorzeitig
> beendet wird.
Die Funktion wird durch das return beendet.
Gast #4019276
Lesenswert?

Max H. schrieb:
> Das get auch schief: Wenn hilf negativ ist, dann ist BUFFER_SIZE-hilf
> größer als BUFFER_SIZE, z.B. 128 - -6 = 134.

uupps :-), naja, darum bin ich ja noch ein Anfänger und kein 
Fortgeschrittener bzw. Profi, so wie Du. Mir wäre das wahrscheinlich nie 
aufgefallen und ich hätte mich gewundert, warum ich Blödsinn rausbekomme 
:-)
Gast #4019645
Lesenswert?

Guten Morgen!

Aus dem Quellcode würde ich gerne noch die letzte Zeile hier aus dem 
Abschnitt verstehen:
1
struct Buffer {
2
  uint8_t data[BUFFER_SIZE];
3
  uint8_t read; // zeigt auf das Feld mit dem ältesten Inhalt
4
  uint8_t write; // zeigt immer auf leeres Feld
5
} buffer = {{}, 0, 0};

buffer = {{}, 0, 0}

Ich bin mir über die Verwendung der geschweiften Klammern noch im 
Unklaren. Die beiden Nullen dort sind sicherlich als Initialwerte für 
read und write zu verstehen. Mit {} - ist damit gemeint, dass das Array 
data[BUFFER_SIZE] leer sein soll?

Warum kann ich dort überhaupt geschweifte Klammern benutzen? Sorry, wenn 
meine Frage vielleicht trivial ist - aber ich habe in meinem 
C-Anfängerbuch nachgeschaut und noch nicht herausgefunden, warum man 
sagen kann buffer={...}. Ich hab bisher immer gedacht, dass die 
geschweiften Klammern dazu da sind, Funktionsblöcke einzugrenzen.
#4019657
Lesenswert?

Anfänger schrieb:
> Mit {} - ist damit gemeint, dass das Array
> data[BUFFER_SIZE] leer sein soll?
Es wird mit 0 initialisiert.

> warum man sagen kann buffer={...}.
Das ist laut C-Standard einfach so.
> Ich hab bisher immer gedacht, dass die geschweiften Klammern
> dazu da sind, Funktionsblöcke einzugrenzen.
Wie du gesehen hast nicht ausschließlich.
Gast #4019696
Lesenswert?

cool, danke für Eure Hilfe.

Ich hab jetzt mal versucht, das C-Programm in eine Klassenstruktur 
umzuwandeln (Headerdatei und cpp-Datei sind jetzt hier in dem 
Codeschnippsel zusammen):

1
// Headerdatei
2

3
class Buffer {
4
 public:
5
    uint8_t BufferIn  (uint16_t element);
6
    uint8_t BufferOut (* element);
7
    void BufferClear ();
8
    uint32_t BufferAnzahl ();
9
 
10
 private:
11
    uint16_t data[];
12
    uint16_t read;
13
    uint16_t write;
14
};
15

16
// cpp-Datei
17

18
uint8_t Buffer::Buffer(uint16_t size) {
19
    if (size%2 != 0) { 
20
         return ERROR;
21
    }
22
    else {
23
         read = 0;
24
         write = 0;
25
         data = date[size];
26
         return !ERROR;
27
    }
28
}
29
 
30
uint8_t Buffer::BufferIn(uint8_t byte) {
31
  uint8_t next = ((buffer.write + 1) & BUFFER_MASK);
32
  if (buffer.read == next)
33
    return FAIL;
34
  buffer.data[buffer.write] = byte;
35
  // buffer.data[buffer.write & BUFFER_MASK] = byte; // absolut Sicher
36
  buffer.write = next;
37
  return SUCCESS;
38
  int a= ERROR;
39
}
40
 
41
uint8_t Buffer::BufferOut(uint8_t *pByte) {
42
  if (buffer.read == buffer.write)
43
    return FAIL;
44
  *pByte = buffer.data[buffer.read];
45
  buffer.read = (buffer.read+1) & BUFFER_MASK;
46
  return SUCCESS;
47
}
48

49
void Buffer::BufferClear()
50
{
51
    buffer.read = buffer.write = 0;
52
}
53

54
uint8_t Buffer::BufferAnzahl()
55
{
56
    return (buffer.write - buffer.read) & (BUFFER_SIZE - 1);
57
}

Später würde ich in meinem Programm das so aufrufen:
1
 if ( (Buffer meinbuffer(1024)) != SUCCESS) 
2
    { ... Fehler beim Initialisieren des Buffers ...}
Ich bin mir aber nicht sicher, ob im Konstruktor die Zuweisung der 
Arraygröße funktioniert:
1
 data = date[size];

Könnt ihr mir da vielleicht nochmal ein paar Tipps geben? Kann ich 
überhaupt im Konstruktor eine return-Anweisung machen?
Gast #4019746
Lesenswert?

Max H. schrieb:
> Nein, die Präprozessor Anweisungen funktionieren nur mit Konstanten.
> Dann müsstest du 'size' mit einem #define machen

ok, danke. Ich brauche in meinem Programm zwei Buffers mit 
unterschiedlichen Größen und wollte gerne die Größe variabel erzeugen 
können - auch für später mal, wenn ich wieder mal nen Buffer brauche.

Aber das hier würde gehen?
1
uint8_t Buffer::Buffer(uint16_t size) {
2
    if (size%2 != 0) { 
3
         return ERROR;
4
    }
5
    else {
6
         read = 0;
7
         write = 0;
8
         data = date[size];
9
         return !ERROR;
10
    }
11
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren