Forum: Compiler & IDEs Interrupt Problem mit ATMega128


von Florian M. (skywalker79)


Lesenswert?

Hallo,

ich habe mal wieder ein Problem mit meinem ATMega128 und den Interrupts.
Ich benutze die Timer0, Timer2 und einen Interrupt für die UART.
Solange nur die ISR für die beiden Timer im Programm waren, liefen diese 
noch.
Seitdem ich den UART-Empfang per Interrupt steuere, laufen die Timer 
scheinbar nicht mehr.

die entsprechenden Programmteile sind hier :

ISR( TIMER0_OVF_vect )
{
  teiler_abtastung++;
  speicher_zaehler ++;

  if( teiler_abtastung >= teiler_abtastrate)
  {
    teiler_abtastung = 0;
    PORTA ^= 0x08;
    speicher_zaehler = 0;
  }
}

ISR( TIMER2_OVF_vect )
{
  teiler_laufzeit++;
  if( teiler_laufzeit >= 3596)
  {
    teiler_laufzeit = 0;
    PORTA ^= 0x10;
  laufzeit_sekunden ++;

  if( laufzeit_sekunden >= 59)
      {
         laufzeit_sekunden = 0;
      laufzeit_minuten ++;
                PORTA ^= 0x20;
    }
  }
}

ISR( SIG_UART1_RECV )
{
  uart();
}

die Initialisierung in der main:

TCCR0 = ( 1 << CS01 );
TCCR2 = ( 1 << CS21 );
TIMSK = ( 1 << TOIE2 )|( 1 << TOIE0 );

und für die UART-Schnittstelle:

void USART_INIT(unsigned int baud)
{
  UBRR1H = (unsigned char)(baud>>8);
  UBRR1L = (unsigned char)baud;
  UCSR1B = (1<<RXCIE1)|(1<<RXEN1)|(1<<TXEN1);
  UCSR1C = (1<<USBS1)|(1<<UCSZ11)|(1<<UCSZ10);
}

Ich hoffe mal, ihr könnt mir helfen.

mit freundlichen Grüßen

von Sepp (Gast)


Lesenswert?

Ich kann nur raten, aber schon mal an den watchdog gedacht? Hatte mal 
was Ähnliches. Bei mir lief der Watchdog in der UART Routine einfach 
über. Ein Deaktivieren der Interrupts in ISR( SIG_UART1_RECV ) könnte 
evtl ne Lösung sein.
Ist aber wirklich nur ne Vermutung...

von Florian M. (skywalker79)


Lesenswert?

Hallo Sepp,
das scheint tatsächlich zu Funktionieren, mit dem deaktivieren und 
aktivieren der Interrupts in der ISR.
Könntest du mir noch kurz verraten, warum das so ist?

von Sepp (Gast)


Lesenswert?

Hmm. Gute Frage. Soweit ich weiß, muss der µC den Watchdog immer wieder 
reseten. Sobald er sich aber in nem Interrupt befindet macht er das 
nicht mehr. Dauert dein Interrupt zu lange, was bei Uart leicht der Fall 
sein kann, läuft der Watchdog über und resetet den Controller.

So oder so ähnlich läuft das wohl ab :)

von Karl H. (kbuchegg)


Lesenswert?

Was passiert in der Funktion Uart() ?

Beim UART Empfangsinterrupt gibt es eine Falle:
Du musst das Zeichen aus dem UDR1 Register auslesen.
Erst dieses Lesen setzt die Interrupt Anforderung zurück.
Wird aus UDR1 nicht gelesen, dann kommt der UART1_RECV
Interrupt gleich wieder und wieder und wieder.

Mit: "Ich häng mich da mal an den Interrupt dran um zu
sehen ob er ausgelöst wird, das Zeichen verarbeiten mach
ich dann später" ist also nichts.

von Florian M. (skywalker79)


Lesenswert?

Guten morgen,

Also hier mal meine uart();
Ist das Auslesen vom UDR1 Register da schon zu spät?

void uart (void)
{
  uint8_t i;
    char c;
    char* s;

   s=befehl;
    i=0;


    do
    {
      c=USART_Receive();
    if( c!='\r')
    {
        *s=c;
        s++;
        i++;
    }
  }
  while( c!='&' );
    *s=0;

  befehlspruefung();

  while (!(UCSR0A & (1<<UDRE0))) {}
}

und hier noch die Funktion für den Empfang:

uint8_t USART_Receive(void)
{
  while ( !(UCSR1A & (1<<RXC1)) );
  return UDR1;
}

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.