Hallo Leute Hätte mir jemand ein kurzes Code Beispiel wie man in c einen Ringpuffer realisiert ? Gruß Gizmo
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 ;)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.