Forum: Mikrocontroller und Digitale Elektronik UART Interrupt mit Mega8


von Torsten K. (nobby)


Lesenswert?

Hallo,

ich versuche den UART Interrupt des Mega 8 zu aktivieren,
aber ich bekommen es nicht auf die Reihe.

Gesetzt habe ich:

UCSRB = (1<<RXCIE);
sei(); // Globaler Interrupt aktiviert.

Sobald nun in UCSRA das RXC gesetzt wird, sollte er doch in die
Interrupt Routine springen:

ISR(USART_RXC_vect)  // Daten Empfangen, Rx Complete
{

}

Das macht er aber nicht, habe ich was übersehen ??
Das Datenblatt habe ich schon rauf und runter gelesen....

Danke
Torsten

von Matthias L. (Gast)


Lesenswert?

Receiver aktiviert? (1<<RXEN) ?
globale Interrupts aktiv? sei();

WIe wäre es mit dem kompletten code?

von Torsten K. (nobby)


Lesenswert?

Naja, also die Interrupts sind aktiev, habe ja geschrieben sei().
Den (1<<RXEN) hatte ich auch gesetzt, aber das hat auch nichts geholfen.
Was meinst Du mit dem kompletten Code, ich habe im Interrupt eine LED 
aktiviert, aber die tut es eben nicht.

Hier nochmal alle Register, wenns denn hilft..

DDRC |=  _BV(PC0) |_BV(PC1) | _BV(PC2)| _BV(PC3) | _BV(PC4);   // Teile 
von PortC als Ausgang
  DDRC &=~ _BV(PC5);                   // Teile von PortC als Eingang



  DDRD |=  _BV(PD2) | _BV(PD5) | _BV(PD6) | _BV(PD7);  // Teile von 
PortD als Ausgang
  DDRD &=~ _BV(PD3) | _BV(PD4);               // Teile von PortD als 
Eingang
  PORTD |= _BV(PD3) | _BV(PD4);               // Teile von PortD PullUp


  DDRB |= _BV(PB0) | _BV(PB1) |  _BV(PB2) | _BV(PB3) | _BV(PB4) | 
_BV(PB5);    // Teile von PortB als Ausgang
  DDRB &=~  _BV(PB6) | _BV(PB7);              // Teile von PortB als 
Eingang
  PORTB |=  _BV(PB6) | _BV(PB7);              // Teile von PortB PullUp


  OSCCAL = eeprom_read_byte((uint8_t*)0xFF);



  TIFR = (1<<TOV0)|(1<<TOV1);
  TCCR0 = (1<<CS00)|(1<<CS01);
  TCCR1B = (1<<CS12)|(1<<CS10);


  UCSRB = (1<<RXCIE) | (1<<RXEN);



  TIMSK = (1<<TOIE0)|(1<<TOIE1);

von Martin F. (martin-f)


Lesenswert?

wirklich vollständig ist der code wohl immernoch nicht. Hier fehlt mir 
z.B. die Baudratenintitialisierung. (stichwort UBRR)
Sonst schau Dir diesen Teil des tutorials noch mal an:
in C: 
https://www.mikrocontroller.net/articles/AVR-Tutorial:UART:GCC#Der_UART
in ASM:  https://www.mikrocontroller.net/articles/AVR-Tutorial:_UART

von Torsten K. (nobby)


Lesenswert?

naja, der USART funktioniert ja, denn wenn ich den  (UCSRA & (1<<RXC))
polle, bekomme ich Daten rein, kein Problem.

Aber gerne hier meine Init, genau nach Datasheet:

void USART_Init(void)
{
   UBRRH = (F_CPU/(UART_BAUD_RATE1*16l)-1) >> 8;
   UBRRL = (F_CPU/(UART_BAUD_RATE1*16l)-1);

// Enable Receiver and transmitter
   UCSRB = (1<<RXEN)|(1<<TXEN);
// Set frame format: 8data, 2stop bit
   UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}

Ich habe auch gefunden woran es liegt, denn nur

UCSRB = _BV(RXCIE) |_BV(RXEN);

reicht nicht, es muß noch

 _BV(UDRIE)  mit dazu, und wenn ich das Datenblatt richtig verstehe muß 
auch noch in UCSRA einer gesetzt werden. Insgesamt sieht es dann so aus:

UCSRA = _BV(UDRE);
UCSRB = _BV(RXCIE) | _BV(UDRIE) | _BV(RXEN);

Dann springt er auch prima in den Interrupt.
Leider wird nun der Timer0 irgendwie beeinflusst, auch wenn der nicht in 
den Interrupt der Seriellen springt, scheint der Timer0 langsamer zu 
werden.

Mal sehen, ob ich das noch finde.

Gruß
Torsten

von Chrisi (Gast)


Lesenswert?

Solange Du das Zeichen nicht aus dem Empfangspuffer liest, wird der 
Interrupt nicht gelöscht. Dann ist Deine CPU quasi dauerbusy :-) Nur ne 
Idee.

von Johannes M. (johnny-m)


Lesenswert?

Richtig. Es muss im RXC-Interrupt-Handler das UDR gelesen werden. Erst 
der Lesezugriff löscht das Interrupt-Flag. Wenn nicht gelesen wird, 
springt er nach dem Ende der ISR sofort wieder rein.

von Torsten K. (nobby)


Lesenswert?

Ich habe den Eindruck das da irgendetwas mit dem Compiler nicht stimmt !

Wenn ich den
ISR(USART_RXC_vect)
benutze, springt er nur in den Interrupt wenn auch UDRIE gesetzt ist.
Aber er durchläuft dann nicht mehr das Hauptprogramm und verhält sich 
auch sonst "merkwürdig", als ob er überlastet ist.

Benutze ich hingegen den alten Ausdruck,
SIGNAL(SIG_UART_RECV)
dann scheint alles normal zu funktionieren und es muß auch nicht der 
UDRIE gesetzt sein.

Hat denn schonmal jemand den RX Interrupt mit dem Mega 8 benutzt ?

Gruß
Torsten

von Chrisi (Gast)


Lesenswert?

Ja, hier z.B.:

// Setup USART
UBRRH = (byte)(BAUDVAL >> 8);
UBRRL = (byte)(BAUDVAL & 0xFF);
UCSRC = (1<<URSEL) | (3<<UCSZ0);
UCSRA = (1<<U2X);
UCSRB = (1<<RXEN) | (1<<RXCIE);

// Interrupt
SIGNAL(SIG_UART_RECV)
{
    // Read UDR and put it into the revceive buffer
    BUF_PUT(HostRX,UDR)
}

Was moderneres benutze ich auch nicht.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.