Forum: Mikrocontroller und Digitale Elektronik "Programm bleibt in der TIMER ISR hängen"


von Anon A. (marinco)


Lesenswert?

Mein Programm soll eine Reaktionszeitmessung durchführen
Ablauf:
Eine LED leuchtet auf.
Der Timer fängt an zu zählen ISR(Timer0)
bis ein externer Interrupt(Taster) ausgelöst wird
Anschließend soll der Wert des Zählers in eine Variable gespeichert 
werden
Dies soll 5-Mal geschehen und der Mittelwert gebildet werden.

Problem: nach dem cli im externen Interrupt sollte das Programm wieder 
in der main weiterlaufen, stattdessen springt es wieder zurück in die 
Timer-ISR und bleibt dort hängen

auch eingefügter cli-Befehl hat keine Auswirkung
Programm bleibt weiterhin in der TIMER_ISR




Programm:


/*
 * Reaktion.c
 *
 * Created: 15.10.2013 09:01:04
 *  Author: E.C
 */


#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include "lcd.h"

ISR(INT0_vect);
ISR(TIMER0_OVF_vect);
int main(void);

struct
{
unsigned char bNeuerWert_1:1; // 1 Bit für bNeuerWert_1
} bNeuerWert;

volatile uint16_t msek, gesamt = 0;  // Timer
volatile uint8_t gedrueckt = 0; // TastCounter

ISR(INT0_vect)
{
  // Taste wurde gedrückt
  // angeschlossen an (INT0) PD2 Pin 4

  cli();  // alle IRQ sperren



  bNeuerWert.bNeuerWert_1 = 1;

  // Led aus

  PORTC = 0x01;

}

ISR(TIMER0_OVF_vect)
{
  // Einsprung alle ms

  msek++;
  TCNT0 = 209;  // Nachladung


}



int main(void)
{
  /* PC0 als Ausgang -> LED Anschluss */

  DDRC = 0x01;  // PC0 als Ausgang definieren

  // Ext0init:

    PORTD |= 0x04;      // Activate pullupressistor of PD2
    MCUCR |= (1 << ISC01);  // INT0 is executed on falling edge
    GICR |= (1 << INT0);  // Enable INT0

  // Timer0init:

  TCCR0 |= (1<<CS02);    // Vorteiler
  TCNT0 = 209;      // Nachladung
  TIMSK= (1<<TOIE0);      // Enable Timer 0 overflow interrupt

  sei();    // globale ISR Freigabe

    while(1)
    {
    if(bNeuerWert.bNeuerWert_1)
    {
     if(gedrueckt == 5)
      {
      gedrueckt = 0;
      gesamt = gesamt/5;

      // itoa integer to ASCII
      // Ausgabe LCD muss noch gemacht werden


      bNeuerWert.bNeuerWert_1 = 0;
      msek = 0;
      gesamt = 0;

      sei();

      // Led ein
      PORTC = 0xFE;

      }
      else
      {
       gedrueckt++;
       gesamt = gesamt + msek;
       msek = 0;
       bNeuerWert.bNeuerWert_1 = 0;

       // Led ein
      PORTC = 0xFE;
      }
    }

  }
}

: Bearbeitet durch User
von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

Das cli im Interrupt ist unnötig. Interrupts sind gesperrt während ein 
Interrupt ausgeführt wird

EDIT: Das sei in deiner if(gedrueckt == 5) Abfrage auch... aus o.g. 
Grund

Ist dein Taster Hardwareseitig entprellt?

: Bearbeitet durch User
von Anon A. (marinco)


Lesenswert?

Christopher B. schrieb:
> Das cli im Interrupt ist unnötig. Interrupts sind gesperrt während ein
> Interrupt ausgeführt wird
>
Könnte ich da mit einem reti wieder in die main kommen?
oder wäre die Rücksprungadresse wieder im timer?

Und wenn ich die Interrupts nicht disable komme ich dann, wenn ich im 
main bin wegen dem sei bei jedem OVF in die OVF-ISR oder nicht?

PS.: mit dem cli(); wollte ich eigentlich bewirken, dass die Interrupts 
auch nach dem verlassen der ISR gesperrt bleiben...

> EDIT: Das sei in deiner if(gedrueckt == 5) Abfrage auch... aus o.g.
> Grund

> Ist dein Taster Hardwareseitig entprellt?
 Nein der Externe-Interrupt wird mit der fallenden Flanke ausgelöst.

von spess53 (Gast)


Lesenswert?

Hi

>Könnte ich da mit einem reti wieder in die main kommen?
>oder wäre die Rücksprungadresse wieder im timer?

Ein Interrupt springt immer wieder an den Punkt im Programm zurück, an 
dem es unterbrochen wurde.

>PS.: mit dem cli(); wollte ich eigentlich bewirken, dass die Interrupts
>auch nach dem verlassen der ISR gesperrt bleiben...

Das RETI, das am Ende jeder Interruptroutine steht, setzt das globale 
Interrupt-Enable-Flag wieder.

MfG Spess

von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

>>PS.: mit dem cli(); wollte ich eigentlich bewirken, dass die Interrupts
>>auch nach dem verlassen der ISR gesperrt bleiben...

>Das RETI, das am Ende jeder Interruptroutine steht, setzt das globale
>Interrupt-Enable-Flag wieder.
Richtig, dazu müsstest du die einzelnen Interrupts abschalten

>> Ist dein Taster Hardwareseitig entprellt?
> Nein der Externe-Interrupt wird mit der fallenden Flanke ausgelöst.
aber wenn dein Taster prellt, dann landest du öfter in dem Interrupt als 
dir lieb ist.

von Anon A. (marinco)


Lesenswert?

spess53 schrieb:
> Das RETI, das am Ende jeder Interruptroutine steht, setzt das globale
> Interrupt-Enable-Flag wieder.

Ja aber wenn ich das bei der Timer-ISR mache komme ich wegen dem 
internen Overflow (zählt in dem Fall von 209 bis 256) immer wieder in 
die ISR rein
--> im main wird nichts gemacht...:/
Gibt es keinen anderen Weg die ISR zu beenden?

von spess53 (Gast)


Lesenswert?

Hi

>Gibt es keinen anderen Weg die ISR zu beenden?

Siehe Post von Christopher B. (chrimbo).

MfG Spess

von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

>ISR(INT0_vect);
>ISR(TIMER0_OVF_vect);
liegt es vielleicht daran?
Du brauchst keine Deklaration für ISRs.

von Vabi (Gast)


Lesenswert?

Im else-Teil fehlt ein sei() - so wie es dasteht, drückst du den Knopf 
und dein Programm läuft einmal durch das else. Dann sind Interrupts aber 
immer noch aus und es passiert nie mehr irgendetwas.

Woraus schließt du, dass dein Programm in der Timer-ISR hängenbleibt?

von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

Vabi schrieb:
> Im else-Teil fehlt ein sei() - so wie es dasteht, drückst du den Knopf
> und dein Programm läuft einmal durch das else. Dann sind Interrupts aber
> immer noch aus und es passiert nie mehr irgendetwas.
nö, guck mal über while(1) da ist das sei()

von Anon A. (marinco)


Lesenswert?

Vabi schrieb:
> Im else-Teil fehlt ein sei() - so wie es dasteht, drückst du den Knopf
> und dein Programm läuft einmal durch das else. Dann sind Interrupts aber
> immer noch aus und es passiert nie mehr irgendetwas.
>
> Woraus schließt du, dass dein Programm in der Timer-ISR hängenbleibt?

Ich benutzte dir "Entwicklungsumgebung" AVR Studio 4....Dort kann man ja 
die Programme Simulieren.

Bei der Simulation:
Fängt in Main an, führt alles aus bis zum sei()
-->Timer-ISR: dort wird gezählt bis die taste "gedrückt" wird in diesem 
Fall wenn das Bit auf Pin2 gesetzt wird
--> ExtInt wird ausgeführt
-->Timer-ISR: bleibt hängen (zählt weiter und kommt nicht mehr ins 
main...)

von Anon A. (marinco)


Lesenswert?

Danke an alle für die schnellen Antworten,
ich habe für das Problem eine andere Lösung gefunden,
indem ich das Hängenbleiben in der Timer-ISR ausnutze :)
lg

von spess53 (Gast)


Lesenswert?

Hi

>ich habe für das Problem eine andere Lösung gefunden,
>indem ich das Hängenbleiben in der Timer-ISR ausnutze :)

Was denn nur für ein 'Hängenbleiben in der Timer-ISR'?

MfG Spess

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.