USART-Ringbuffer
/*
* Ringbuffer
* Einfacher Code, der den UART initialisiert und die
* empfangenen Bytes in einen Rinpuffer schiebt
* Sind Bytes im Ringpuffer, werden diese zurueckgeschickt
* Als Baudrate wird 9600Bd eingestellt
* https://www.eHaJo.de
* (C) Hannes Jochriem, 2013
*/
#define F_CPU 8000000UL /* 8MHz */
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
// Prototypen
void long_delay(uint16_t);
// Defines:
#define LED1 (1<<PD6)
#define PUFFERSIZE 8
// globale Variablen
// volatile ist noetig, da die Variablen in der ISR veraendert werden
volatile uint8_t ringpuffer[PUFFERSIZE];
volatile uint8_t ring_schreibe = 0;
volatile uint8_t ring_lese = 0;
// Interrupt Serviceroutine für "Byte am USART empfangen"
ISR(USART_RXC_vect)
{
uint8_t temp;
// Empfangenes Byte in den Speicher schreiben
temp = UDR;
// Schreibposition inkrementieren
ring_schreibe++;
//Schreibposition auf Puffergroesse beschraenken
ring_schreibe %= PUFFERSIZE;
if(ring_schreibe != ring_lese)
{ // Puffer ist nicht voll, Byte schreiben
// LED aus
PORTD &= ~LED1;
ringpuffer[ring_schreibe] = temp;
}
else
{ // Puffer ist voll, Schreibposition wieder dekrementieren
// LED an zeigt vollen Buffer an
PORTD |= LED1;
ring_schreibe--;
}
}
int main()
{
// LED-Pin als Ausgang definieren
DDRD |= LED1;
// Receive-Interrupt einschalten, RX und TX einschalten
UCSRB |= (1<<RXCIE) | (1<<RXEN) | (1<<TXEN);
// 8 Bit Daten:
UCSRC |= (1<<UCSZ0) | (1<<UCSZ1);
// Baudrate auf 9600Bd einstellen:
UBRRH = 0;
UBRRL = 51;
// Globales Interruptflag einschalten:
sei();
while(1)
{
if(ring_lese != ring_schreibe)
{ // He, es ist was im Ringpuffer!!!
// Leseposition inkrementieren
ring_lese++;
// Leseposition auf Puffergroesse beschraenken
ring_lese %= PUFFERSIZE;
// Byte im Puffer zurücksenden
UDR = ringpuffer[ring_lese];
// Eine Sekunden warten damit man Versuchsweise den
// Rinpuffer volllaufen lassen kann
long_delay(1000);
}
}
return 0;
}
void long_delay(uint16_t ms)
{
for(; ms>0; ms--)
_delay_ms(1);
}
Keine Kommentare