mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Buffer wechseln die zweite


Autor: Michael Hegener (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe gestern von Karl Heinz Buchegger folgenden Code Vorschlag bekommen
um unterschiedliche buffer zum speichern von Daten zu Nutzen.
Ich habe noch folgendes Problem:
Ich möchte vier Interrupt nutzen um Zeiten zu messen! Mit der funktion
store (siehe unten) kann ich auch im Interrupt den Wert des ICU
abspeichern.
Wie ist das jetzt zu realisieren das von jeder Zeit nur fünf Werte in
den Buffer geschrieben werden und der dann automatisch wechselt in den
nächsten.
Zur Auswertung soll dann immer der Buffer genutzt werden der zuletzt
aktiv war.
Bitte kann mir jemand helfen wie soetwas zu realisieren ist?



struct Buffer {
  int Werte[100];
  int NrWerte;
};

struct Buffer Messung1;    // der erste Buffer
struct Buffer Messung2;    // der zweite Buffer
struct Buffer Messung3;    // der dritte Buffer
struct Buffer* Active;     // Zeiger auf den aktiven Buffer
                           // in den aktiven Buffer werden Werte
                           // geschrieben

void Store( int Wert )
{
  // Speicher den Wert im aktiven Buffer
  Active->Werte[ Active->NrWerte ] = Wert;
  Active->NrWerte++;
}

int main()
{
  // den ersten Buffer aktivieren
  Messung1.NrWerte = 0;
  Active = &Messung1;

  // speichere ein paar Werte im aktiven Buffer
  Store( 100 );
  Store( 50 );
  Store( 150 );

  // Es ist Zeit den 2. Buffer zu aktivieren ...
  Messung2.NrWerte = 0;
  Active = &Messung2;

  // .. denn wir wollen mit der ersten Messreihe was machen
  Compute( &Messung1 );
}

void Compute( struct Buffer& Buff )
{
  int i;

  for( i = 0; i < Buff->NrWerte; ++i )
    printf( Buff->Werte[i] );
}

Autor: tauscher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
//Initialisiere
struct Buffer* temp;
struct Buffer* Active;
struct Buffer* Last_active;
struct Buffer* Next_active;

//Definiere vor der main Loop
Active = &Messung1;
Next_active = &Messung2;
Last_active = &Messung3;

//In der main Loop
temp = Last_active;
Last_active = Active;
Active = Next_active;
Next_active= temp;

/*
und nun hast du die Buffer bei jeder main Loop durchgetauscht, kannst
den Alten bearbeiten und den Neuen beschreiben.

Compute( &Last_active );
 Store( 100 );
 Store( 50 );
 Store( 150 );

Warum sind eigentlich deine Buffer so groß, wenn du blos je 3 Werte
speichern möchtest?
Gruß
*/

Autor: tauscher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ups,

muss natürlich heißen:

Compute( Last_active );

Autor: Michael Hegener (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das war nur das Codebeispiel! Hatte im ersten Beitrag keine Angabe zur
größe des Buffers gemacht.
Habe in der main allerdings wenig stehen meine application wird durch
reload timer interrupts zyklisch aufgerufen!

Autor: Michael Hegener (michih)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann das auch in einer switch case erfolgen mit dem Buffer umschalten?

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> struct Buffer Messung1;    // der erste Buffer
> struct Buffer Messung2;    // der zweite Buffer
> struct Buffer Messung3;    // der dritte Buffer

Durchnummerierte Variablen sind ein sicherer Hinweis darauf dass man
eigentlich ein Array verwenden möchte. Dann kann man sich auch sowas
sparen:

temp = Last_active;
Last_active = Active;
Active = Next_active;
Next_active= temp;

...und stattdessen einfach einen Index inkrementieren.

Autor: tauscher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
natürlich, warum nicht?

Ich hab das Gefühl, du solltest dir über die Struktur und den Aufbau
deines Programms mal ein paar Gedanken machen und über das was du
eigentlich wie realisieren möchtest.

Grüße

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und vor allen Dingen:

Hinsetzen und mal auf dem Papier ein paar Skizzen machen:
Welche variablen gibt es, wie verhalten sie sich zueinander,
was ist wo gespeichert, was muss wann passieren.

Dann löst sich so manches Problem von alleine in Luft auf.

Autor: Michael Hegener (michih)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
to Andreas! Das ist ja alles richtig mein problem bei der ganzen sache
ist doch das ich mir bei einem Array nicht sicher bin wenn ich in der
Berechnung bin ob da nun schon neue oder die eigentlich zu verwendeden
alten werte stehen. Aufgrund dessen soll für einen Messwert ein Array
für fünf werte zur verfühgung stehen. Von diesem Array brauche ich fünf
damit die Berechnung in ruhe und ohne sorge das die werte überschrieben
werden durchgeführt werden kann.

Grundsätzlicher Aufbau
main initialisiert die ICU, ADC, Eingänge, Ausgänge usw. geht dann in
eine Endlosschleife die durch Interrupts unterbrochen wird. Z.B. um ADC
Messwerte abzuholen.
Ein reload Timer steuert diese ganze Geschichte.
Jetzt habe ich Input Capture mit Interrupt programmiert in welchem der
Zeitwert in einem Buffer geschrieben werden soll. Dieses habe ich für
vier Input Capture gemacht. Die Interrupts sind gegeneinander gesperrt
so das sie nur in der richtigen reihenfolge auftreten können.
Meine Application wird zyklisch aufgerufen um jetzt zu verhindern das
soetwas wie oben beschrieben passiert d.h. das alte Werte mit in die
Berechnung einfließen suche ich nach einer Kompforttablen lösung die
mir aber leider nicht einfällt.

Also Interrupt kommt > Wert wird gespeichert > wenn 5 Werte im
buffer(bei allen Messungen) soll der nächste buffer genommen werde >
hinweis für die App Note buffer"1" voll berechnung kann starten >
nach  füllen des letzten buffers switchen auf den ersten.

Und ich kriegs nicht hin und brauche eure Hilfe!!

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie Andreas schon sagte:
Anstatt 3 einzelnen struct Buffer Variablen macht man halt
ein Array aus diesen. Anstatt dem komplizierten Pointer-häck-mäck
tritt dann eine ganz einfache Indexvariable.

struct Buffer Messungen[10];   // 10 mögliche Buffer
int ActiveBuffer;              // der Index des aktiven Buffers

wenn du einen Buffer weiterschalten willst, machst du einfach
ActiveBuffer++;
Natürlich musst du aufpassen, dass das ganze auch immer schön im
Kreis rumgeht, d.h. wenn ActiveBuffer den Wert 10 erreicht hat,
gehts wieder bei 0 los:

  ActiveBuffer++;
  if( ActiveBuffer == 10 )
    ActiveBuffer = 0;

Der vorhergehende Buffer ist dann auch leicht zu bestimmen, das
ist einfach der mit dem Index um 1 kleiner als ActiveBuffer. Auch
hier wieder aufpassen: das geht im Kreis herum, der vorhergehende
Buffer zum Index 0 ist der Buffer Nr. 9 und nicht -1.

Der Zugriff auf die Werte gestaltet sich dann:

  Messungen[ActiveBuffer].Werte[5] = ...

Über die Nummer in ActiveBuffer wird ein Buffer aus dem Array
aller Buffer ausgewählt. In diesem einen Buffer gibt es dann
wieder ein Array in dem alle Werte sind und mit dem zweiten
Index wird einer davon ausgewählt.

Wie ich schon sagte: mal eine Zeichnung machen:


  Mesungen
  +-----------------------------------------------+
  | Werte                                         |
  | +---+---+---+---+---+- ... -+---+---+---+---+ |
  | |   |   |   |   |   |       |   |   |   |   | |
  | +---+---+---+---+---+- ... -+---+---+---+---+ |
  |                                               |
  | NrWerte                                       |
  | +------+                                      |
  | |      |                                      |
  | +------+                                      |
  +-----------------------------------------------+
  | Werte                                         |
  | +---+---+---+---+---+- ... -+---+---+---+---+ |
  | |   |   |   |   |   |       |   |   |   |   | |
  | +---+---+---+---+---+- ... -+---+---+---+---+ |
  |                                               |
  | NrWerte                                       |
  | +------+                                      |
  | |      |                                      |
  | +------+                                      |
  +-----------------------------------------------+
  .                                               .
  .                                               .
  .                                               .
  +-----------------------------------------------+
  | Werte                                         |
  | +---+---+---+---+---+- ... -+---+---+---+---+ |
  | |   |   |   |   |   |       |   |   |   |   | |
  | +---+---+---+---+---+- ... -+---+---+---+---+ |
  |                                               |
  | NrWerte                                       |
  | +------+                                      |
  | |      |                                      |
  | +------+                                      |
  +-----------------------------------------------+

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich auch mal meinen Senf dazugebend:

unsigned char messungen[10][10];
unsigned char zeile,spalte;


adc_int
messungen[zeile][spalte] = adc;
if (zeile < 9)
{
  zeile++;
}
else
 zeile = 0;
 if (spalte < 9)
 {
   spalte++;
 }
 else
 {
  spalte = 0;
 }
}
...


und zum berechnen:

if (spalte == 0)
{
 brechne spalte 9;
}
else
{
 berechne spalte - 1;
}

müsste doch gehen oder?

MW

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klar geht das genauso.

Die eigentliche Frage sollte aber sein. Warum diese
künstliche Unterteilung in x Messwerte? Wenn es keinen
wirklichen Grund dafür gibt, jeweils x Messwerte zu
einer Gruppe zusammenzufassen ist ein stink normaler
Ringbuffer doch viel einfacher als ein 2D Array. Egal
wie es realisiert wird (meine Lösung ist auch nur ein
glorifiziertes 2D Array, wobei jede Zeile seinen eigenen
Füllstandsmesser hat).

Ringbuffer:

    +---+---+---+---+---+---+---+---+
    |   |   |   |   |   |   |   |   |
    +---+---+---+---+---+---+---+---+
                  ^       ^
                  |       |
     ReadIndex    |       |
    +----+        |       |
    | o-----------+       |
    +----+                |
                          |
    WriteIndex            |
    +----+                |
    | o-------------------+
    +----+

Der WriteIndex sagt immer wo als nächstes geschrieben werden darf
und wird bei einem Schreibvorgang um ein Feld weitergesetzt (und
natürlich an den Anfang zurück, wenn das Ende des Arrays erreicht
ist). Read ReadIndex sagt aus von wo der nächste Wert zur Verarbeitung
gelesen werden kann (und wird nach dem Lesevorgang weitergesetzt).
Ist der ReadIndex identisch mit dem WriteIndex, so ist der Buffer
leer. Ist der WriteIndex um 1 kleiner als der ReadIndex, so ist der
Buffer voll und es passt nichts mehr rein.

Aber das kann ich nicht beurteilen. Ich kenne die Aufgabenstellung
nicht und weiss dahere nicht ob es einen speziellen Grund dafür
gibt jeweils x Einträge zusammenzufassen (was man im übrigen
auch mit dem Ringbuffer erreichen könnte).

Abgesehen davon ist das bisher Vorgeschlagene eine gute Übung im
Arbeiten mit Strukturen und Arrays.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.