mikrocontroller.net

Forum: Compiler & IDEs Problem mit simplem FiFo


Autor: Sven S. (schwerminator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin Moin,
ich versuche zur Zeit einen einfachen FIFO zu implementieren. Dazu habe 
ich einen externen SRAM-Baustein im Einsatz, der 16 Speicherbänke à 32kB 
beherbergt. Eine Testfunktion, die alles mit fortlaufenden Nummern 
beschreibt und später wieder kontrolliert, funktioniert einwandfrei.

Nun versuche ich eine Eingabe über UART zu realisieren, bei der zunächst 
beliebig viele Zeichen in den FIFO geschrieben werden und bei Eingabe 
eines '#' die ersten hundert Zeichen im FIFO ausgegeben werden sollen. 
Leider bleibt die Ausgabe immer bei Zeichen 98 hängen. Nun weiß ich 
nicht, wo der Fehler liegt, bei der FIFO-Routine, die im vorherigen Test 
ja reibungslos funktioniert hat, oder bei der UART-Ausgabe (P. Fleury), 
die ja eigentlich auch erprobt ist... Vielleicht könnt ihr mir ja 
weiterhelfen...
#define UART_BAUD_RATE 9600
#define XMEM_OFFSET 0x2200
#define XMEM_BANK_SIZE 0x8000

struct {
  uint16_t address;
  uint8_t bank;
} fifo_read, fifo_write;

void fifo_init(void){
  XMCRA |= (1<<SRE);
  XMCRB |= (1<<XMM0);

  DDRF |= 0xF0;
  PORTF &= 0x0F;

  fifo_read.address = XMEM_OFFSET;
  fifo_read.bank = 0;

  fifo_write.address = XMEM_OFFSET;
  fifo_write.bank = 0;
}

void fifo_putc(char c){
  PORTF = (fifo_write.bank << 4) | (PORTF & 0x0F);
  *((char*) fifo_write.address) = c;

  if(++fifo_write.address == XMEM_BANK_SIZE+XMEM_OFFSET){
    fifo_write.address = XMEM_OFFSET;
    if(++fifo_write.bank == 0x10)
      fifo_write.bank = 0;
  }
}

char fifo_getc(void){
  PORTF = (fifo_read.bank << 4) | (PORTF & 0x0F);
  uint8_t rtrn = *((char*) fifo_read.address);

  if(++fifo_read.address == XMEM_BANK_SIZE+XMEM_OFFSET){
    fifo_read.address = XMEM_OFFSET;
    if(++fifo_read.bank == 0x10)
      fifo_read.bank = 0;
  }

  return rtrn;
}

int main(void){
  uint16_t c;

  sei();

  uart_init(UART_BAUD_SELECT(UART_BAUD_RATE, F_CPU));
  fifo_init();

  fdevopen(uart_putc, NULL);

  while(1){
    c = uart_getc();
    
    if(!(c & UART_NO_DATA)){
      if((char) c != '#'){
        fifo_putc((char)c);
        uart_putc('X');
      }
      else{
        printf("End-Zeichen erhalten!\n");
        break;
      }
    }
  }
  
  for(uint8_t i=0; i<100; i++){
    printf("Zeichen %d: %c\n", i, fifo_getc());
  }

  return 0;

}

Danke und Gruß
Sven

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Häng entweder deine Ausgabe noch mit in die Endlosschleife mit rein, 
oder mach noch eine Endlosschleife hinter deine Ausgabe.

Dein Programm darf main() nie verlassen!
Tut es dass, dann sorgt die C-Runtime dafür, dass zb Interrupts 
abgeschaltet werden und damit steht dann auch deine Ausgabefunktion, die 
die Zeichen im Hintergrund per Interrupt an den Mann bringt.

Die bessere Lösung ist es, wenn du dich daran gewöhnst, dass sich deine 
Programmlogik immer innerhalb der einzigen
  while( 1 ) {

    ....
  }

Schleife in main abspielt. Und zwar nur dort! Ein µC beendet sein 
Programm nie!
Auch wenn das heißt, dass du deinen jetzigen Code dazu etwas umbauen 
musst.

Autor: Sven S. (schwerminator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hoppla! Ich danke dir :)

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.