- LiTime Speicher und Akkus         
Ergebnis 1 bis 3 von 3

Thema: Ringpuffer für UART-Kommunikation

  1. #1

    Ringpuffer für UART-Kommunikation

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Guten Morgen,

    auf dem XMC4700 Mikrocontroller von Infineon wird eine UART eingesetzt. Es sollen die ankommenden Daten von UDP über die UART an ein anderes Device gesendet werden.
    Es kann nun passieren, dass die ankommenden UDP Daten schneller ankommen als die UART die Daten verarbeiten kann. Deshalb sollen Die Daten (Frames) in einen Ringpuffer abgelegt werden. Auf folgender Seite habe ich eine Implementierung gefunden https://www.google.de/url?sa=t&rct=j&q=&esrc=s&sou... die mein Problem eventuell lösen könnte.

    Der folgende Quellcode habe ich auf dem PC mit Visual Studio erfolgreich getestet. Auf dem Mikrocontroller läuft dieser Quellcode nicht. Der Mikrocontroller bleibt hängen.
    Wo könnte hier das Problem liegen?


    Code:
    #define BUFFER_SIZE      512
    #define NUMBER_OF_FRAMES  10
    
    //Struktur fuer die Daten
    typedef struct
    {
      int length;
      char data[BUFFER_SIZE];
    } userdata_t;
    
    //Struktur fuer einen Ringbuffer-Handler
    //wird benoetigt, um mehrere Listen zu verwalten
    typedef struct
    {
      //Index zum Lesen
      int readIndex;
      //Index zum Schreiben
      int writeIndex;
      //Platz fuer Speicherelemente, eigentlicher Buffer
      userdata_t fifo[NUMBER_OF_FRAMES];
      //Groesse des Buffers, d.h. Anzahl der Elemente
      int size;
    } ringbuffer_handler_t;
    
    
    /*-------------------------------------------------------------------------*/
    
    //eine Funktion, um einen Ringbuffer anzulegen
    //Parameter size: Groesse des Buffers (Anzahl der Elemente)
    //Rückgabewert: Zeiger auf Ringbuffer-Handler
    ringbuffer_handler_t * createFIFO(int size)
    {
      static char Memory[6000];
      ringbuffer_handler_t *buffer = (ringbuffer_handler_t *)Memory;
    
      //Werte des Handler belegen
      //readIndex und WriteIndex zu Anfang 0
      //fuer fifo muss genuegend Speicher reserviert werden,
      //um size Datenelemente aufnehmen zu koennen
      //size gibt Anzahl der Elemente im Ringbuffer an (aus Parameter)
      buffer->readIndex = 0;
      buffer->writeIndex = 0;
      buffer->size = size;
    
      return buffer;
    }
    
    /*-------------------------------------------------------------------------*/
    
    //eine Funktion, um Elemente anzuhaengen, d.h. in den Buffer zu schreiben
    //Parameter data: Daten, die in den Buffer geschrieben werden sollen
    //Parameter *buffer: Zeiger auf Ringbuffer-Handler
    //kein Rueckgabewert
    void appendFIFO(userdata_t data, ringbuffer_handler_t *buffer)
    {
      //Daten in den entsprechenden Platz im Buffer schreiben
      //dafuer ist writeIndex da
      buffer->fifo[buffer->writeIndex] = data;
      //writeIndex wird fuer das naechste Schreiben auf den neuen Wert
      //gesetzt
      //Achtung: wenn der Buffer voll ist, wird wieder vorne hineinge-
      //schrieben (deshalb RINGbuffer), Daten koennen verloren gehen,
      //wenn nicht zwischendurch gelesen wird
      buffer->writeIndex = buffer->writeIndex++ % (buffer->size + 1);
      //an dieser Stelle ist es deshalb sinnvoll, den readIndex auf den
      //letzen wahren Wert zu setzen, wenn NICHT zwischendurch gelesen
      //wurde
      if (buffer->readIndex == buffer->writeIndex)
        buffer->readIndex = buffer->readIndex++ % (buffer->size + 1);
    }
    
    //eine Funktion, um Elemente aus dem Buffer zu lesen
    //Parameter *data: Zeiger auf ein Datenelement, das die gelesenen Daten
    //aufnehmen soll
    //Parameter *buffer: Zeiger auf Ringbuffer-Handler
    //Rueckgabewert -1, wenn nicht gelesen werden konnte
    //Rueckgabewert 1, wenn gelesen werden konnte
    int readFIFO(userdata_t *data, ringbuffer_handler_t *buffer)
    {
      //der writeIndex zeigt immer auf das naechste zu beschreibende Element,
      //d.h. dieses Element ist noch nicht beschrieben worden und enthaelt
      //deshalb keine gueltigen Daten
      //wenn readIndex also gleich writeIndex, darf nicht gelesen werden
      if (buffer->readIndex != buffer->writeIndex)
      {
        //Daten kopieren
        *data = buffer->fifo[buffer->readIndex];
        //readIndex fuer das naechste Lesen hochsetzen
        buffer->readIndex = buffer->readIndex++ % (buffer->size + 1);
        //Rueckgabewert 1, da gelesen wurde
        return 1;
      }
      else
        //es konnten keine Daten gelesen werden, da keine gueltigen Daten
        //Rueckgabewert also -1
        return -1;
    }
    
    void main (void)
    {
      ringbuffer_handler_t *local_buffer;
      userdata_t write_data;
      userdata_t read_data;
      int ergebnis;
    
      local_buffer = createFIFO(NUMBER_OF_FRAMES);
    
      char DummyData[500];
      memset(DummyData, 0x33, 500);
    
      write_data.length = 101;
      memcpy(write_data.data, DummyData, 101);
      appendFIFO(write_data, local_buffer);
    
      readFIFO(&read_data, local_buffer);
    }

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von vohopri
    Registriert seit
    11.09.2004
    Ort
    südlich der Alpen
    Beiträge
    1.708
    Jetzt deinen Quälcode zu analysieren, hab ich nicht die Zeit zur Verfügung.

    Nur so als Tip, was bei mir optimal funktioniert:

    Debugbefehle einbauen und anzeigen lassen, wie der Programmablauf vorangeht und wie die Daten im Speicher verarbeitet werden. Da sieht man sehr schnell, was Sache ist. Die Debugstrategie überlegt man sich am Besten noch bevor die erste Codezeile geschrieben wird. Aber besser spät, als nie.

    Du hast einen UART zur Verfügung, wenn du den zum debuggen nutzt, brauchst du nicht einmal Zusatzhardware und -software.

  3. #3
    Erfahrener Benutzer Roboter Genie Avatar von White_Fox
    Registriert seit
    04.10.2011
    Beiträge
    1.473
    Ich hab auf den Abend auch keine Lust mehr mich durch Code kämpfen zu müssen. Aber einen alternativen Lösungsansatz hätte ich vielleicht, sowas könnte ich demnächst vielleicht auch gebrauchen. Also:

    Code:
    //globaler Zugriff:
    *TBuffercell FirstBuffercell;
    *TBuffercell LastBuffercell;
    
    typedef struct{
        char[128] buffer;    //Kleines Array, das deine Daten aufnimmt, kann natürlich auch eine andere Größe haben, die Größe sollte aber als Konstante hinterlegt werden
        int queueStart;      //Gibt den Anfang des beschriebenen Bereichs an, bei "vollem" buffer also 0, so findest du den Anfang wieder wenn du das Array nicht auf einen Schlag auslesen willst
        int queueEnd;        //Gibt das Ende des beschriebenen Bereichs an, bei "vollem" buffer also 127, so findest du das Ende wieder wenn du das Array nicht auf einen Schlag beschreiben willst
        *nextTBuffercell;    //Pointer auf das nächste Speicherelement, bei Null ist das vordere Ende der Queue erreicht
    }TBuffercell
    Das wars dann auch fast schon, noch eine Funktion die deine Daten auf lauter TBuffercells quer durch den Speicher verteilt () und eine, die mit dem Pointer FirstBuffercell hinterherkriecht und die Daten wieder zurückgibt, aber das kriegst du selber hin. Nicht vergessen, LastBuffercell und queueEnd bzw. FirstBuffercell und queueStart zu inkrementieren.

    Jetzt war ich doch mal neugierig und hab mir mal deinen Code nochmal angesehen, viel Arbeit ist so ein Ringpuffer nun doch nicht. Warum der nicht funktioniert kann ich dir auf die Rasche nicht sagen, allerdings belegt der den Speicher in einem einzigen Stück, ist fest begrenzt und belegt den Platz auch wenn du ihn nicht brauchst.
    Das Konzept mit der struct-Kette ist da weitaus flexibler, kann gerne fragmentieren, kann ausgedehnt werden solange noch Speicher da ist (du kannst ja ohne weiteres ein neues struct erstellen und dem jetzt struct das nun an zweiter Stelle steht den Pointer umsetzen), eine Größenbeschränkung kannst du auch einbauen (vom ersten struct bis zum letzten durchzählen). Dafür hast du etwas mehr Überbau an Speicherbedarf für die Pointer.

    Edit:
    Zumindest denk ich mir das so einfach, seit ich mich mal etwas ernsthaft mit OOP befaßt habe fällt mir prozedurale Programmierung echt schwer und C geht mir sehr auf die Nerven...ich bin auf die Probleme gespannt die dieses Konzept aufwirft.

Ähnliche Themen

  1. Syntax für UART Kommunikation
    Von spelli2001 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 5
    Letzter Beitrag: 24.06.2012, 15:51
  2. Probleme mit UART Kommunikation
    Von curzon161 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 28.08.2011, 18:17
  3. Problem mit UART Kommunikation
    Von Testus2K im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 11
    Letzter Beitrag: 30.05.2011, 14:41
  4. UART Ringpuffer löschen ?
    Von Jürgen75 im Forum C - Programmierung (GCC u.a.)
    Antworten: 3
    Letzter Beitrag: 02.05.2008, 13:15
  5. µC Kommunikation via UART?
    Von Killer im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 24.12.2007, 03:22

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiTime Speicher und Akkus