Erstes C Programm UART - Warum wird zweimal "Hallo World" gesendet?
Moin,
also das Problem ist der ISP. Wenn ich den Abziehe, dann macht das Programmw was es soll...
Gruß
Holger
Moin,
ich möchte von Assembler auf C umsteigen und habe mein erstes Projekt mit ATMEL-Studio 6.1 angelegt. Ich möchte ganz einfach nur einen Text "Hallo Welt" via UART übertragen.
Als Anfänger habe ich mir dazu einiges von rn-wissen.de zusammengeklickt. Ich habe fifo.h und uart.h erstellt und mein .c-Datei mit dem Namen _20140117_UART_ATMEGA32.c.
Nach dem Build übertrage ich das fertige hex mit meinem AVR-ISP MKII in den ATMEGA32. Sowei alles gut. Aber wenn ich den Controller einschalte wird zweimal mit einer etwa 0,5 Sekunden Pause Hallo Welt übertragen.
Warum?
Gruß
Holger
Code:
/*
* _20140117_UART_ATMEGA32.c
*
* Created: 17.01.2014 13:18:31
* Author: DL9HDA
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include "uart.h"
#include "fifo.h"
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#ifndef BAUDRATE
#define BAUDRATE 9600UL
#endif
// FIFO-Objekte und Puffer für die Ein- und Ausgabe
#define BUFSIZE_IN 0x40
uint8_t inbuf[BUFSIZE_IN];
fifo_t infifo;
#define BUFSIZE_OUT 0x40
uint8_t outbuf[BUFSIZE_OUT];
fifo_t outfifo;
#define CR "\r\n"
char text[] = "Hallo Welt." CR;
void uart_puts (const char *s)
{
do
{
uart_putc (*s);
}
while (*s++);
}
int main(void)
{
sei();
uart_init();
uart_puts (text);
while(1)
{
//TODO:: Please write your application code
}
}
void uart_init (void)
{
uint8_t sreg = SREG;
uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16UL*BAUDRATE) - 1);
UBRRH = (uint8_t) (ubrr>>8);
UBRRL = (uint8_t) (ubrr);
// Interrupts kurz deaktivieren
cli();
// UART Receiver und Transmitter anschalten, Receive-Interrupt aktivieren
// Data mode 8N1, asynchron
UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
// 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 (&infifo, inbuf, BUFSIZE_IN);
fifo_init (&outfifo, outbuf, BUFSIZE_OUT);
}
ISR (USART_RXC_vect)
{
_inline_fifo_put (&infifo, 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.
ISR (USART_UDRE_vect)
{
if (outfifo.count > 0)
UDR = _inline_fifo_get (&outfifo);
else
UCSRB &= ~(1 << UDRIE);
}
int uart_putc (const uint8_t c)
{
int ret = fifo_put (&outfifo, c);
UCSRB |= (1 << UDRIE);
return ret;
}
int uart_getc_nowait (void)
{
return fifo_get_nowait (&infifo);
}
uint8_t uart_getc_wait (void)
{
return fifo_get_wait (&infifo);
}
Code:
#ifndef UART_H
#define UART_H
#include <avr/io.h>
extern void uart_init (void);
extern int uart_putc (const uint8_t);
extern uint8_t uart_getc_wait (void);
extern int uart_getc_nowait (void);
static inline void uart_flush (void)
{
while (UCSRB & (1 << UDRIE));
}
#endif /* UART_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*);
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;
}
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 */
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;
}
uint8_t fifo_put (fifo_t *f, const uint8_t data)
{
return _inline_fifo_put (f, data);
}
uint8_t fifo_get_wait (fifo_t *f)
{
while (!f->count);
return _inline_fifo_get (f);
}
int fifo_get_nowait (fifo_t *f)
{
if (!f->count) return -1;
return (int) _inline_fifo_get (f);
}