Forum: Compiler & IDEs ringpuffer code beispiel


von gizmo (Gast)


Lesenswert?

Hallo Leute

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

Gruß

Gizmo

von Εrnst B. (ernst)


Lesenswert?

Beispiel aus UART-Code:
1
#include "uart.h"
2
#include <avr/io.h>
3
#include <avr/pgmspace.h>
4
#include <avr/interrupt.h>
5
6
#define SEND_BUF_BITS 4
7
#define SEND_BUF_SIZE (1<<SEND_BUF_BITS)
8
#define SEND_BUF_MASK (SEND_BUF_SIZE-1)
9
#define RECV_BUF_BITS 2
10
#define RECV_BUF_SIZE (1<<RECV_BUF_BITS)
11
#define RECV_BUF_MASK (RECV_BUF_SIZE-1)
12
13
14
static volatile uint8_t send_buf_start;
15
static uint8_t send_buf_end;
16
static char send_buf[SEND_BUF_SIZE];
17
18
static uint8_t recv_buf_start;
19
static volatile uint8_t recv_buf_end;
20
static char recv_buf[RECV_BUF_SIZE];
21
22
23
void uart_init(uint16_t baud) {
24
// ifdef ATTINY...
25
  UCSRA = _BV(U2X);
26
  UCSRB = _BV(TXEN) | _BV(RXEN) | _BV(RXCIE);   //UART TX+RX einschalten
27
  UCSRC |= _BV(UCSZ0)|_BV(UCSZ1);       //Asynchron 8N1
28
  UBRRH=(uint8_t)((baud)>>8);
29
  UBRRL=(uint8_t)(baud);
30
31
  send_buf_start=0;
32
  send_buf_end=0;
33
  recv_buf_start=0;
34
  recv_buf_end=0;
35
}
36
void uart_putc(char c)
37
{
38
  uint8_t next_pos=(send_buf_end+1)&SEND_BUF_MASK;
39
40
  // wait till we got space in buffer
41
  while ((SREG & _BV(SREG_I)) && (next_pos == send_buf_start));
42
43
  if (next_pos == send_buf_start) {
44
    // Interrupts are disabled and buffer is full. we loose this char.
45
    return;
46
  }
47
48
  send_buf[send_buf_end]=c;
49
50
  send_buf_end=next_pos;
51
52
  // Enable UDR interrupt. will immediatly call ISR if UDRE is set.
53
  UCSRB = _BV(TXEN) | _BV(RXEN) | _BV(UDRIE) | _BV(RXCIE);
54
}
55
56
void uart_write(const char * c) {
57
  while (*c) {
58
    uart_putc(*c++);
59
  }
60
}
61
void uart_write_P(const char * c) {
62
  char ch;
63
  do {
64
   ch=pgm_read_byte(c++);
65
   if (!ch) return;
66
   uart_putc(ch);
67
  } while(1);
68
}
69
char uart_getc(void) {
70
  // Wait till byte in buffer
71
  while(recv_buf_start == recv_buf_end);
72
  char x=recv_buf[recv_buf_start++];
73
  recv_buf_start &=RECV_BUF_MASK;
74
  return x;
75
}
76
77
 uint8_t uart_recv_buf_size(void) {
78
  if (recv_buf_end >= recv_buf_start) {
79
    return recv_buf_end - recv_buf_start;
80
  }
81
  return recv_buf_end + RECV_BUF_SIZE - recv_buf_start;
82
}
83
84
 uint8_t uart_send_buf_size(void) {
85
  if (send_buf_end >= send_buf_start) {
86
    return send_buf_end - send_buf_start;
87
  }
88
  return send_buf_end + SEND_BUF_SIZE - send_buf_start;
89
}
90
ISR(USART_RX_vect) {
91
  recv_buf[recv_buf_end]=UDR;
92
93
  recv_buf_end=(recv_buf_end+1)&RECV_BUF_MASK;
94
95
  if (recv_buf_end == recv_buf_start) {
96
    // Overflow! drop the first byte of the recv_buf.
97
    recv_buf_start=(recv_buf_start+1)&RECV_BUF_MASK;
98
  }
99
}
100
101
ISR(USART_UDRE_vect) {
102
  if (send_buf_end == send_buf_start) {
103
    // No data to send, disable ISR.
104
    UCSRB = _BV(TXEN) | _BV(RXEN) | _BV(RXCIE);
105
  } else {
106
    UDR=send_buf[send_buf_start++];
107
    send_buf_start &=SEND_BUF_MASK;
108
  }
109
}

Benutzung auf eigene Gefahr ;)

von J. M. (Firma: OCL) (lorcan)


Lesenswert?


von gizmo (Gast)


Lesenswert?

Danke Leute für die schnellen Antworten hat mir sehr geholfen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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:
1
recv_buf_end = 123;
Beim nächsten Eintrag in den Fifo hätten wir einen amoklaufenden 
Pointer:
1
ISR(USART_RX_vect) {
2
  recv_buf[recv_buf_end]=UDR;  // Holla, jetzt gehts rund.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.