"Programm bleibt in der TIMER ISR hängen"

OP #3363275
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;
      }
    }

  }
}
OP #3363335
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.
Gast #3363347
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
Persönliche Seite #3363356
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.
OP #3363362
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?
Gast #3363370
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?
OP #3363391
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...)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren