Atmega328P Interrupt löst dauerhaft aus

Gast #4849443
Lesenswert?

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
}
Moderator Persönliche Seite #4849548
Lesenswert?

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.
#4849629
Lesenswert?

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 #4849676
Lesenswert?

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

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