PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Atmega128 - Wieder mal Probleme mit UART Interrupt (Gelöst)



messier
14.04.2009, 14:40
Hallo,

jetzt probier ich schon seit einigen Stunden Daten mittels dem
USART0_RX_vect Interrupt zu empfangen, aber aus irgendeinen Grund wird
die ISR anscheinend nie aufgerufen.
Daten Senden mittels USART0_UDRE_vect funktioniert ohne Probleme. Daten
empfangen mittel Polling ebenfalls.

Hier mal der vereinfachte Code der nur überprüft ob die ISR aufgerufen
wird.
Wenn ja, dann sollten sich 4 LEDs die am PortC hängen einschalten. Nach
spätestens 4 sek sollen sich die LEDs aber auf jedenfall einschalten.
Und da passiert jetzt was seltsames: Wenn ich im Hyperterminal nichts
eingebe werden die LEDs nach 4 sekunden eingeschalten, aber wenn ich
Daten sende, dann scheint das Programm abzustürzen, weil dann garnichts
mehr passiert.



...

void uart_init()
{
uint8_t sreg = SREG;

UBRR0H = UBRR_VAL >> 8;
UBRR0L = UBRR_VAL & 0xFF;

// Interrupts kurz deaktivieren
cli();

// UART Receiver und Transmitter anschalten, Receive Interrupt setzen
// Data mode 8N1, asynchron
UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
UCSR0C = (1<<UCSZ1) | (1<<UCSZ0);


// Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte)
do
{
// UDR auslesen (Wert wird nicht verwendet)
UDR0;
}
while (UCSR0A & (1 << RXC0));

// Rücksetzen von Receive und Transmit Complete-Flags
UCSR0A = (1 << RXC0) | (1 << TXC0);

// Global Interrupt-Flag wieder herstellen
SREG = sreg;
}

ISR(USART0_RX_vect)
{
uint8_t sreg = SREG;
cli();

// LEDS einschalten
DDRC = 0xFF;
PORTC = 0b11110000;

UDR0;

SREG = sreg;
}

int main (void)
{
sei();

uart_init();

// Nach 4 Sekunden sollen die LEDs auf jedenfall eingeschalten werden
for(int i = 0; i< 4000; i++)
_delay_ms(1);

DDRC = 0xFF;
PORTC = 0b11110000;
while(1);

return 0;
}


Sieht hier jemand einen Fehler? Kann das irgendwie mit dem AT103
Kompatibilitätsmodus zusammenhängen? Oder liegts vielleicht sogar am
Bootloader (es handelt sich dabei um den Conrad Bootloader der auf der C-Control Pro arbeitet)?.

Danke schon mal im vorraus,

Thomas

messier
14.04.2009, 18:56
Endlich nach langen verzweifelten Herumprobieren und reichlich Unterstützung vom Nachbarforum ist das Problem gelöst.

Der Conrad Bootloader aktiviert das IVSEL Bit im MCUCR und leitet somit alle Interrupts erstmal zur Bootloadersektion um. Manche Interrupts wie z.B USART0_UDRE_vect werden dann wieder an die ursprüngliche Adresse zurückgeleitet.

Wenn man das IVSEL bit wieder zurücksetzt funktioniert aber alles so wie es soll. Also braucht man nur folgende 2 Zeilen vor dem eigentlichen Program einfügen:

MCUCR = (1<<IVCE);
MCUCR = 0;

mfg Thomas

avion23
15.04.2009, 10:44
Hallo THomas,
die erste Zeit hat keinen Effekt.

messier
15.04.2009, 11:19
Hallo,

sieht zwar komisch aus, aber steht so im Datenblatt. Das IVCE Bit muss zuerst gesetzt werden, dann kann innerhalb von 4 Taktzyklen das Register angepasst werden.