Atmega328P Interrupt löst dauerhaft aus

Gast #4849443
Moin,

Ich bin gerade dabei meinen Controller für eine Rotierende Uhr(ähnlich 
einer Propeller-Clock) zu Programmieren. Zur ermittlung der Drehzahl 
nutze ich einen Hallsensor vom Typ A3144 und einen kleinen Magneten. Nun 
habe ich folgendes Problem: Der Interrupt löst solange aus, wie der 
Magnet über dem Sensor ist, obwohl ich eigentlich deklariert habe, dass 
er nur bei steigender Flanke auslösen soll. Anbei schicke ich mal die 
entsprechenden Passagen, vielleicht hat ja jemand von euch eine Idee.

Danke im voraus, Waldkauz

1
 #define F_CPU   16000000UL
2

3
#include <asf.h>
4
#include <avr/sfr_defs.h>
5
#include <avr/io.h>
6
#include <stdio.h>
7
#include <stdlib.h>
8
#include <inttypes.h>
9
#include <util/delay.h>
10
#include <avr/interrupt.h>
11

12
#define setbit(P,BIT)  ((P) |= (1<<(BIT)))    
13
#define clearbit(P,BIT)  ((P) &= ~(1<<(BIT)))  
14

15
int main (void)
16
{  
17
        MCUCR = 1<<ISC01 | 1<<ISC00;
18
  EIMSK |= (1 << INT0);
19

20
        while(testvariable == 1)
21
        {
22
        }
23
}
24

25

26
ISR(INT0_vect)
27
{
28
  setbit(PORTD, 7);
29
  _delay_ms(50);
30
  clearbit(PORTD, 7);
31
  _delay_ms(50);
32
}
Gast
Ich hänge den echten code mal eben mit an, habe das jetzt mit der 
Testvariable so geschrieben, da die Hauotschleife funktioniert und nur 
der Interrupt probleme macht. Der Code ist auch nooch nicht wirklich 
aufgeräumt ^^
Angehängte Dateien:
Moderator Persönliche Seite
Waldkauz schrieb:
> setbit(PORTD, 7);
>   _delay_ms(50);
>   clearbit(PORTD, 7);
>   _delay_ms(50);

Du kannst nicht ganze 100ms (eine ganze zehntel Sekunde) in der ISR() 
mit Nichtstun vertrödeln. Bis dahin tritt ja schon wieder der nächste 
Interrupt auf. Oder drehst Du den Propeller in Ultra-Zeitlupe? Delays in 
ISRs gehen zu 99% in die Hose.

Setze lediglich ein Flag in der ISR, toggle das Bit PD7 in der 
Hauptschleife. Am besten letzteres über einen Timer, denn auch das 
Warten einer ganzen zehntel Sekunde in der Hauptschleife hat meist 
weitere unerwünschte Nebeneffekte.

Merke:

Vermeide Delays. delay_ms() kann man ja mal für kleine Tests verwenden, 
wenn man weiß, was man tut. Praxistauglich ist es meistens nicht. 
delay_us() kann man in seltenen Fällen durchgehen lassen, wenn es sich 
um sehr kleine Zeitspannen handelt, wo man sowieso nichts zwischendurch 
zu tun hat. Aber sonst sind Flags und Timer die richtige Wahl. Dafür 
sind sie da.
Waldkauz schrieb:
> MCUCR = 1<<ISC01 | 1<<ISC00;
Warum versuchst du die Interruptvektoren zu verbiegen? Klappt aber 
nicht, da es sich um eine "Timed Sequence" handelt. Stattdessen steht 
der Eingang auf Low Level und produziert solange Interrupts, bis der Pin 
auf High geht. Alles richtig also. Oder ein typischer Fall von 
Copy&Paste-Programmierung, ohne weiteres Nachdenken und Nichtbenutzung 
des Datenblattes.

Daß der Atmega328 kein GIMSK hat, hast du ja mittels Fehlermeldung des 
Compilers noch rausgefunden. Nur liefert das vorhandene MCUCR natürlich 
keine Fehlermeldung. Leider hat es eine vollkommen andere Bedeutung.

Guck ins Datenblatt unter Register Description bei den Externen 
Interrupts.

Kleiner Tip: Dein Freund heißt EICRA.
Gast
Danke Thomas, das war der Fehler!
Hatte den Teil aus einem anderen Code von mir übernommen, wo ich aber 
einen anderen Controller damals verwendet hatte. Jetzt klappt es.
Gast
Frank M. schrieb:
> Du kannst nicht ganze 100ms (eine ganze zehntel Sekunde) in der ISR()
> mit Nichtstun vertrödeln. Bis dahin tritt ja schon wieder der nächste
> Interrupt auf. Oder drehst Du den Propeller in Ultra-Zeitlupe? Delays in
> ISRs gehen zu 99% in die Hose.

Moin Frank!
Die Delays kommen da wieder raus, die hatte ich nur testweise drin um zu 
gucken ob und wie der Interrupt auslöst. Der Propeller lief dabei 
wirklich in Zeitlupe, da ich ihn nur mit dem Finger gedreht hatte.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.