www.mikrocontroller.net

Forum: Compiler & IDEs ringpuffer code beispiel


Autor: gizmo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute

Hätte mir jemand ein kurzes Code Beispiel wie man in c einen Ringpuffer 
realisiert ?

Gruß

Gizmo

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beispiel aus UART-Code:
#include "uart.h"
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>

#define SEND_BUF_BITS 4
#define SEND_BUF_SIZE (1<<SEND_BUF_BITS)
#define SEND_BUF_MASK (SEND_BUF_SIZE-1)
#define RECV_BUF_BITS 2
#define RECV_BUF_SIZE (1<<RECV_BUF_BITS)
#define RECV_BUF_MASK (RECV_BUF_SIZE-1)


static volatile uint8_t send_buf_start;
static uint8_t send_buf_end;
static char send_buf[SEND_BUF_SIZE];

static uint8_t recv_buf_start;
static volatile uint8_t recv_buf_end;
static char recv_buf[RECV_BUF_SIZE];


void uart_init(uint16_t baud) {
// ifdef ATTINY...
  UCSRA = _BV(U2X);
  UCSRB = _BV(TXEN) | _BV(RXEN) | _BV(RXCIE);   //UART TX+RX einschalten
  UCSRC |= _BV(UCSZ0)|_BV(UCSZ1);       //Asynchron 8N1
  UBRRH=(uint8_t)((baud)>>8);
  UBRRL=(uint8_t)(baud);

  send_buf_start=0;
  send_buf_end=0;
  recv_buf_start=0;
  recv_buf_end=0;
}
void uart_putc(char c)
{
  uint8_t next_pos=(send_buf_end+1)&SEND_BUF_MASK;

  // wait till we got space in buffer
  while ((SREG & _BV(SREG_I)) && (next_pos == send_buf_start));

  if (next_pos == send_buf_start) {
    // Interrupts are disabled and buffer is full. we loose this char.
    return;
  }

  send_buf[send_buf_end]=c;

  send_buf_end=next_pos;

  // Enable UDR interrupt. will immediatly call ISR if UDRE is set.
  UCSRB = _BV(TXEN) | _BV(RXEN) | _BV(UDRIE) | _BV(RXCIE);
}

void uart_write(const char * c) {
  while (*c) {
    uart_putc(*c++);
  }
}
void uart_write_P(const char * c) {
  char ch;
  do {
   ch=pgm_read_byte(c++);
   if (!ch) return;
   uart_putc(ch);
  } while(1);
}
char uart_getc(void) {
  // Wait till byte in buffer
  while(recv_buf_start == recv_buf_end);
  char x=recv_buf[recv_buf_start++];
  recv_buf_start &=RECV_BUF_MASK;
  return x;
}

 uint8_t uart_recv_buf_size(void) {
  if (recv_buf_end >= recv_buf_start) {
    return recv_buf_end - recv_buf_start;
  }
  return recv_buf_end + RECV_BUF_SIZE - recv_buf_start;
}

 uint8_t uart_send_buf_size(void) {
  if (send_buf_end >= send_buf_start) {
    return send_buf_end - send_buf_start;
  }
  return send_buf_end + SEND_BUF_SIZE - send_buf_start;
}
ISR(USART_RX_vect) {
  recv_buf[recv_buf_end]=UDR;

  recv_buf_end=(recv_buf_end+1)&RECV_BUF_MASK;

  if (recv_buf_end == recv_buf_start) {
    // Overflow! drop the first byte of the recv_buf.
    recv_buf_start=(recv_buf_start+1)&RECV_BUF_MASK;
  }
}

ISR(USART_UDRE_vect) {
  if (send_buf_end == send_buf_start) {
    // No data to send, disable ISR.
    UCSRB = _BV(TXEN) | _BV(RXEN) | _BV(RXCIE);
  } else {
    UDR=send_buf[send_buf_start++];
    send_buf_start &=SEND_BUF_MASK;
  }
}



Benutzung auf eigene Gefahr ;)

Autor: J. M. (Firma: OCL) (lorcan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: gizmo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Leute für die schnellen Antworten hat mir sehr geholfen.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier meine Version: http://www.lothar-miller.de/s9y/categories/51-Fifo
Das ist in etwa das selbe wie bei Ernst B*, aber es gibt garantiert 
keine Zugriffe ausserhalb des Arrays, auch wenn die Schreib-Lese-Pointer 
fälschlicherweise ausserhalb geändert werden.

Bei Ernsts Version gäbe es Probleme, wenn irgendwer irgendwo sowas in 
den Code schreiben würde:
recv_buf_end = 123;
Beim nächsten Eintrag in den Fifo hätten wir einen amoklaufenden 
Pointer:
ISR(USART_RX_vect) {
  recv_buf[recv_buf_end]=UDR;  // Holla, jetzt gehts rund.

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.