Ok,
Eine ISR habe ich nicht.
es wird aber auch nicht vom
https://www.roboternetz.de/wissen/in...RT_mit_avr-gcc
explizit erwähnt, oder ich habe es überlesen....
Habe ja auch fast alles von dort kopiert...
Hier der Gesamte Kode:
Main.c
Code:
#include <avr/interrupt.h> /* Wird nur gebraucht bei der Interrupt-Version */
#include "uart.h"
/*==================[macros]=================================================*/
/* Ein Zeilenumbruch, abhängig davon, was die Gegenstelle haben will */
/* Windows: "rn" */
/* Linux : "n" */
/* MacOS : "r" */
#define CR "\r\n"
/*==================[type definitions]=======================================*/
/*==================[internal function declarations]=========================*/
/*==================[external constants]=====================================*/
/*==================[internal constants]=====================================*/
/*==================[internal data]==========================================*/
/*==================[external function definitions]==========================*/
/*==================[internal function definitions]==========================*/
int main()
{
uart_init();
sei(); // Wird nur gebraucht bei der Interrupt-Version
uart_putc ('f');
/*uart_puts ("Hallo Welt!" CR);*/
while (1);
return 0;
}
/** @} doxygen end group definition */
/*==================[end of file]============================================*/
uart.h:
Code:
#include <avr/io.h>
/*==================[macros]=================================================*/
/*==================[type definitions]=======================================*/
/*==================[external function declarations]=========================*/
extern void uart_init();
extern int uart_putc(const uint8_t);
extern uint8_t uart_getc_wait();
extern int uart_getc_nowait();
extern void uart_puts (char *string_data);
/* Wartet, bis die Übertragung fertig ist. */
static inline void uart_flush()
{
while (UCSRB & (1 << UDRIE));
}
/*==================[external constants]=====================================*/
/*==================[external data]==========================================*/
/** @} doxygen end group definition */
#endif /* _UART_H_ */
/*==================[end of file]============================================*/
uart.c:
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include "uart.h"
#include "fifo.h"
/*==================[macros]=================================================*/
#ifndef F_CPU
/* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
F_CPU im Makefile definiert werden, eine nochmalige Definition
hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
#ifndef/#endif
Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio
verwendet wird und dort eine andere, nicht zur Hardware passende
Taktrate eingestellt ist: Dann wird die folgende Definition
nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?)
von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
noch nicht definiert: */
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 8000000"
#define F_CPU 8000000L // Systemtakt in Hz, das L am Ende ist wichtig, NICHT UL verwenden!
#endif
#define BAUD 9600L // Baudrate, das L am Ende ist wichtig, NICHT UL verwenden!
// Berechnungen
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) /* clever runden */
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) /* Reale Baudrate */
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) /* Fehler in Promille */
/*
#if (((BAUD_ERROR) > (10)) || ((BAUD_ERROR) < (-10)))
#error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
#endif
*/
#define BUF_SIZE_IN 0x40 /* FIFO-Buffergröße */
uint8_t in_buffer[BUF_SIZE_IN];
fifo_t in_fifo;
#define BUF_SIZE_OUT 0x40 /* FIFO-Buffergröße */
uint8_t out_buffer[BUF_SIZE_OUT];
fifo_t out_fifo;
/********* FUNKTIONEN ***********/
void uart_init()
{
uint8_t sreg = SREG;
UBRRH = UBRR_VAL >> 8;
UBRRL = UBRR_VAL & 0xFF;
cli(); /* Interrupts kurz deaktivieren */
UCSRB |= (1<<TXCIE) | (1<<TXEN); /* TXCompleteInterrupt u. TX einschalten */
UCSRC |= (1<<URSEL)| (1<<UCSZ1) | (1<<UCSZ0); /* Asynchron 8N1 */
/* Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte) */
do
{
/* UDR auslesen (Wert wird nicht verwendet) */
UDR;
}while (UCSRA & (1 << RXC));
/* Rücksetzen von Receive und Transmit Complete-Flags */
UCSRA = (1 << RXC) | (1 << TXC);
/* Global Interrupt-Flag wieder herstellen */
SREG = sreg;
/* FIFOs für Ein- und Ausgabe initialisieren */
fifo_init (&in_fifo, in_buffer, BUF_SIZE_IN);
fifo_init (&out_fifo, out_buffer, BUF_SIZE_OUT);
}
/* Senden eines Chars */
int uart_putc (const uint8_t data)
{
int ret = fifo_put (&out_fifo, data);
UCSRB |= (1 << UDRIE);
return ret;
}
/**/
int uart_getc_nowait ()
{
return fifo_get_nowait (&in_fifo);
}
/**/
uint8_t uart_getc_wait ()
{
return fifo_get_wait (&in_fifo);
}
/* Senden eines Strings */
void uart_puts (char *string_data)
{
while (*string_data) /* Wiederhole bis im String '\0' erreicht wurde (*s != '\0') */
{
uart_putc (*string_data); /* Gebe ein Zeichen aus*/
string_data++; /* Erhöhe den String um ein Character */
}
}
/*********************** INTERRUPTS ****************************************/
// Empfangene Zeichen werden in die Eingabgs-FIFO gespeichert und warten dort
SIGNAL (SIG_UART_RECV)
{
_inline_fifo_put (&in_fifo, UDR);
}
// Ein Zeichen aus der Ausgabe-FIFO lesen und ausgeben
// Ist das Zeichen fertig ausgegeben, wird ein neuer SIG_UART_DATA-IRQ getriggert
// Ist die FIFO leer, deaktiviert die ISR ihren eigenen IRQ.
SIGNAL (SIG_UART_DATA)
{
if (out_fifo.count > 0)
UDR = _inline_fifo_get (&out_fifo);
else
UCSRB &= ~(1 << UDRIE);
}
/*********************** ENDE INTERRUPTS ***********************************/
/** @} doxygen end group definition */
/*==================[end of file]============================================*/
fifo.h
Code:
#ifndef FIFO_H_
#define FIFO_H_
#include <avr/io.h>
#include <avr/interrupt.h>
typedef struct
{
uint8_t volatile count; // # Zeichen im Puffer
uint8_t size; // Puffer-Größe
uint8_t *pread; // Lesezeiger
uint8_t *pwrite; // Schreibzeiger
uint8_t read2end, write2end; // # Zeichen bis zum Überlauf Lese-/Schreibzeiger
} fifo_t;
extern void fifo_init (fifo_t*, uint8_t* buf, const uint8_t size);
extern uint8_t fifo_put (fifo_t*, const uint8_t data);
extern uint8_t fifo_get_wait (fifo_t*);
extern int fifo_get_nowait (fifo_t*);
/* Schreibt das nächste Byte "data" in die FIFO.
* Liefer 1 bei Erfolg und 0, falls die FIFO voll ist. */
static inline uint8_t _inline_fifo_put (fifo_t *f, const uint8_t data)
{
if (f->count >= f->size)
return 0;
uint8_t * pwrite = f->pwrite;
*(pwrite++) = data;
uint8_t write2end = f->write2end;
if (--write2end == 0)
{
write2end = f->size;
pwrite -= write2end;
}
f->write2end = write2end;
f->pwrite = pwrite;
uint8_t sreg = SREG;
cli();
f->count++;
SREG = sreg;
return 1;
}
/* Liefert das nächste Zeichen aus der FIFO. Ob überhaubt ein Zeichen in der FIFO
* ist, muss vorher extra abgeprüft werden */
static inline uint8_t _inline_fifo_get (fifo_t *f)
{
uint8_t *pread = f->pread;
uint8_t data = *(pread++);
uint8_t read2end = f->read2end;
if (--read2end == 0)
{
read2end = f->size;
pread -= read2end;
}
f->pread = pread;
f->read2end = read2end;
uint8_t sreg = SREG;
cli();
f->count--;
SREG = sreg;
return data;
}
#endif /*FIFO_H_*/
fifo.c:
Code:
#include "fifo.h"
/* Initialisiert die FIFO, setzt Lese- und Schreibzeiger, etc.
* Die FIFO verwendet den Puffer "buffer", der "size" Bytes sein muss. */
void fifo_init (fifo_t *f, uint8_t *buffer, const uint8_t size)
{
f->count = 0;
f->pread = f->pwrite = buffer;
f->read2end = f->write2end = f->size = size;
}
/* Schreibt das nächste Byte "data" in die FIFO.
* Liefer 1 bei Erfolg und 0, falls die FIFO voll ist. */
uint8_t fifo_put (fifo_t *f, const uint8_t data)
{
return _inline_fifo_put (f, data);
}
/* Liefert das nächste Byte aus der FIFO, bei leerer FIFO wird gewartet,
* bis das nächste Zeichen eintrift. */
uint8_t fifo_get_wait (fifo_t *f)
{
while (!f->count);
return _inline_fifo_get (f);
}
/* Liefert das nächste Byte aus der FIFO als "int" bzw. -1,
* falls die FIFO leer ist. */
int fifo_get_nowait (fifo_t *f)
{
if (!f->count) return -1;
return (int) _inline_fifo_get (f);
}
Lesezeichen