Hi,
versuch mal folgendes:
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/pgmspace.h>
#define SYSCLK 16000000
#define BAUD 9600UL
#define UBRR_BAUD ((SYSCLK/(16*BAUD))-1)
#define TRUE 1
#define FALSE 0
/* USART initialisieren */
void uart_init(void);
volatile const prog_char *p_string;
/* Zeichenkette im Flashspeicher */
prog_char daten[] = "Hello World!\n";
int main(void)
{
// USART initialisieren
uart_init();
sei();
// Pointer zeigt auf die Daten im Flashspeicher
p_string = daten;
// erstes Byte senden
UDR = pgm_read_byte( p_string++ );
// Interrupt aktivieren
UCSRB |= (1<<UDRIE);
for(;;);
}
void uart_init(void)
{
/* Baudrate einstellen ( Normaler Modus ) */
UBRRH = (unsigned char) (UBRR_BAUD>>8);
UBRRL = (unsigned char) (UBRR_BAUD & 0x00FF);
/* Aktivieren des Empfängers, des Senders und des "Daten empfangen"-Interrupts */
UCSRB = (1<<TXEN);
/* Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit */
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}
/* Interrupt wird ausgelöst sobald der Sendepuffer leer ist */
SIGNAL(SIG_UART_DATA)
{
char buffer = pgm_read_byte( p_string++ );
/* Wenn nicht das Ende der Zeichenkette erreicht wurde, weiteres Zeichen senden */
if ( buffer != '\0' ) {
UDR = buffer;
} else {
// Interrupt deaktivieren
UCSRB &= ~(1<<UDRIE);
}
}
Warum das andere Beispiel nicht funktioniert weiß ich im Moment auch noch nicht so genau.
Wenn man sich das Assemblerlisting anschaut, dann sieht man, dass er den Pointer p_string nicht neu lädt. Es wird also nach und nach der gesamte Inhalt des Flashspeichers ausgegeben.
Fügt man aber irgendeine Delayroutine hinter die Abfrage ein, so funktioniert auf einmal alles, auch der Pointer wird wieder richtig initialisiert.
Mit Delay:
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/pgmspace.h>
#define SYSCLK 7372800
#define BAUD 9600UL
#define UBRR_BAUD ((SYSCLK/(16*BAUD))-1)
#define TRUE 1
#define FALSE 0
/* USART initialisieren */
void uart_init(void);
void delay_ms(uint16_t ms);
volatile unsigned char daten_gesendet = TRUE;
volatile const prog_char *p_string;
/* Zeichenkette im Flashspeicher */
prog_char daten[] = "Hello World!\n";
int main(void)
{
// USART initialisieren
uart_init();
sei();
while (1)
{
if (daten_gesendet)
{
// Flag zurücksetzen
daten_gesendet = FALSE;
// Pointer zeigt auf die Daten im Flashspeicher
p_string = daten;
// erstes Byte senden
UDR = pgm_read_byte( p_string++ );
// Interrupt aktivieren
UCSRB |= (1<<UDRIE);
}
delay_ms(1);
}
}
void uart_init(void)
{
/* Baudrate einstellen ( Normaler Modus ) */
UBRRH = (unsigned char) (UBRR_BAUD>>8);
UBRRL = (unsigned char) (UBRR_BAUD & 0x00FF);
/* Aktivieren des Empfängers, des Senders und des "Daten empfangen"-Interrupts */
UCSRB = (1<<RXEN)|(1<<TXEN);
/* Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit */
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}
/* Interrupt wird ausgelöst sobald der Sendepuffer leer ist */
SIGNAL(SIG_UART_DATA)
{
char buffer = pgm_read_byte( p_string++ );
/* Wenn nicht das Ende der Zeichenkette erreicht wurde, weiteres Zeichen senden */
if ( buffer != '\0' ) {
UDR = buffer;
} else {
// Flag setzen, das der String gesendet wurde
daten_gesendet = TRUE;
// Interrupt deaktivieren
UCSRB &= ~(1<<UDRIE);
}
}
/*
* eine kleine Warteschleife ( fürs debugging )
*/
void delay_ms(uint16_t ms)
{
uint16_t zaehler;
while (ms)
{
zaehler = F_CPU / 5000;
while (zaehler)
{
asm volatile ("nop"::);
zaehler--;
}
ms--;
}
}
MfG Kjion
Lesezeichen