Forum: Mikrocontroller und Digitale Elektronik Attiny45 Interrupt in c


von basti (Gast)


Lesenswert?

Hi,
ich kämpfe gerade mit dem folgenden Code in c für den Attiny45.
Beim Betätigen eines Pull-up-Tasters soll die Led für zwei Sekunden 
leuchten.
Sie leuchtet auch, sowohl beim Drücken als auch bei stark verzögertem 
Loslassen (durch fehlendes Debouncing), aber sie lässt sich zwischen 
Drücken und leuchten gut 1/2 Sekunde Zeit...
Könnt ihr mir meinen Fehler zeigen?
1
#define F_CPU 8000000UL
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <util/delay.h>
6
7
8
9
10
int warten = 1;
11
12
13
int main(void)
14
{
15
  DDRB = (1 << PORTB1) | (0 << PORTB2);
16
  MCUCR = (1 << ISC01) | (1 << ISC00);
17
  GIMSK = (1 << INT0);
18
  
19
    while (1) 
20
    {
21
    sei();
22
    if (warten == 0)
23
    {
24
      cli();
25
      _delay_ms(2000);
26
      PORTB &= ~(1 << PORTB1);
27
    }
28
    }
29
}
30
31
ISR(INT0_vect)
32
{
33
  PORTB |= (1 << PORTB1);
34
  warten = 0;
35
}

von Trumpeltier (Gast)


Lesenswert?

Wo fragst Du den Taster ab?

von basti (Gast)


Lesenswert?

Am PINB2.

von Stefan F. (Gast)


Lesenswert?

Mach die Abfrage mal ohne Interrupt, so kannst du relativ leicht einen 
Hardwarefehler ausschließen.

von basti (Gast)


Lesenswert?

Das habe ich bereits gemacht, es funktioniert problemlos.

von Uwe D. (monkye)


Lesenswert?

Ich bin jetzt kein C Spezi, aber wenn Du während des
1
 _delay_ms(2000);
 drückst, dann wird nach der ISR doch weiter gewartet, oder??

von Trumpeltier (Gast)


Lesenswert?

Dein Taster prellt vermutlich so stark, daß Dein Programm sofort wieder 
in den Interrupt spring.

von Frank (Gast)


Lesenswert?

Hallo
ich glaube du musst deine Variable als volatile kennzeichnen.
Ansonsten fällt die Werteänderung der "Optimierung" zum Opfer
und dein Hauptprogramm bekommt von der Änderung nichts mit.
1
volatile int warten = 1;

von basti (Gast)


Lesenswert?

Hm, ich weiß nicht genau was du meinst. Während des _delay_ms sind ja 
alle Interrupts ausgeschaltet, da tut sich also nichts. Wenn ich 
gedrückt halte bis die 2s vorbei sind, bleibt die LED aus, da nur eine 
steigende Flanke erkannt wird.

von basti (Gast)


Lesenswert?

Probiere ich mal, ohne das vollständig verstanden zu haben :)

von Mattias (Gast)


Lesenswert?

Habe mal im Code ein paar Kommentare in den Code gemacht. Schau es dir 
mal an und überleg dir mal wie du die Variable wann setzt.
basti schrieb:
> int warten = 1; //1. hier wird auf 1 initialisiert, diese variable wird im 
interrupt verändert. Dann muss noch ein volatile davor
>
> int main(void)
> {
>   // initialisieren
>     while (1)
>     {
>     sei(); // interrupts einschalten
>     if (warten == 0)
>     {
>       cli(); // interrupts aus..
>       _delay_ms(2000);//2sek warten .. ok
>       PORTB &= ~(1 << PORTB1); // pin low.. ok
>     }
>     }
> }
>
> ISR(INT0_vect)
> {
>   PORTB |= (1 << PORTB1); // pin high.. ok
>   warten = 0; // auf null setzen.. wann wird diese wieder 1??
> }

Viele Grüße
Mattias

von basti (Gast)


Lesenswert?

Danke Mattias, die Kommentare habe ich vergessen.
Ich habe bereits die Variable in "volatile int" geändert, das hat noch 
nicht geholfen. "warten" muss natürlich am Ende der if-Schleife auf 0 
gesetzt werden, das probiere ich mal.

von basti (Gast)


Lesenswert?

Ich meine natürlich dass "warten" auf eins gesetzt wird.

von Mattias (Gast)


Lesenswert?

basti schrieb:
> Ich meine natürlich dass "warten" auf eins gesetzt wird.

Darauf wollte ich hinaus.

Viele Grüße
Mattias

von basti (Gast)


Lesenswert?

Jetzt klappt alles perfekt, klasse :D
Danke für eure Hilfe, ich werd' mich dann mal zum Thema "volatile" 
Variablen schlau machen.

von Trumpeltier (Gast)


Lesenswert?

Oops, die LED sollte auch dann sofort leuchten. Ich glaube, die Grippe 
vernebelt mich komplett.
Setze mal Matthias diffizielen Hinweis um, und nenne eine If-Bedingung 
nicht Schleife.

von Peter II (Gast)


Lesenswert?

basti schrieb:
> Während des _delay_ms sind ja
> alle Interrupts ausgeschaltet, da tut sich also nichts.

dein ganz bestimmt nicht.

von basti (Gast)


Lesenswert?

Kommt nicht wieder vor, und gute Besserung!

von Mattias (Gast)


Lesenswert?

Das volatile sagt dem Compiler, dass die CPU die Variable jedes mal vom 
RAM lesen muss bevor er was damit anstellt. Und nicht einen 'alten' Wert 
aus dem Register zum Vergleich nutzt.

Viele Grüße
Mattias

von basti (Gast)


Lesenswert?

Ok, das ergibt Sinn, wenn vom Interrupt aus darauf zugegriffen wird.

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.