Forum: Mikrocontroller und Digitale Elektronik Interrupt mit atmega8


von Artur G. (artur_g)


Lesenswert?

Hallo,
beschäftige mich seit kurzem mit µC Programmierung. Und natürlich 
versucht man zuerst irgendwelche LED's zum leuchten zu bringen. Ein 
kleines Lauflicht habe ich schon hinbekommen. Jetzt wollte ich, dass am 
PortC erst eine LED leuchtet und dann bei Tastendruck ein 
Interrupt(Int0) ausgelöst wird welcher das Bit um eins verschiebt.

Mein Problem ist jetzt aber, dass ich immer nur bis zur zweiten LED 
komme und der wieder zur ersten springt. Im Simulator kann man sehen, 
dass er nicht in der while- Schleife bleibt sondern zur main() springt 
und dort in PORTC wieder eine 1 schreibt. So kann natürlich es nicht 
funktionieren. Aber warum bleibt er nicht in der schleife solange bis 
ein Interrupt kommt und springt dann wieder dort zurück? Mir ist 
aufgefallen, wenn ich GICR nicht beschreibe  bleibt er in der Schleife. 
Nur dann ist Int0 nicht aktiv.

Ich benutze das AVR Studio 5 mit einem ATMega8.

Gruß
Artur
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
5
6
int main (void)
7
{
8
  DDRC  = 0b00111111;       //Port C Ausgang
9
  DDRD  = 0b00000000;        //Port D Eingang
10
  PORTC = 0b00000001;       //PortC.0=1 setzten
11
  MCUCR = 0b00000011;  //Int0 wird bei steigender Flanke ausgelöst
12
  GICR  = 0b01000000;        //Int0 aktivieren
13
  sei();
14
while(1)
15
{
16
  
17
 }
18
19
20
21
}
22
ISR(INT0_vect)        
23
{
24
25
  PORTC = PORTC << 1; 
26
}

von STK500-Besitzer (Gast)


Lesenswert?

Nein! Tastenabfragen macht man nicht per Interrupt!

von Artur G. (artur_g)


Lesenswert?

Danke für die Antwort, leider bringt sie mich nicht viel weiter. Meinen 
Sie, dass ich es nicht über ein Iterrupt machen muss oder, dass es nicht 
geht? Mein Ziel war es ja ein Interrupt auszulösen und dabei halt eine 
LED zum leuchten zum bringen bzw immer zu schiften.

von da1l6 (Gast)


Lesenswert?

Was er meint, ist das Taster prellen, also ein Druck mehere Pegelwechel 
in kurzer Zeit auslöst. Dadurch wird der AVR mit interrupts überhäuft.
Siehe Entprellung

von alarm (Gast)


Lesenswert?

Artur G. schrieb:
>   DDRC  = 0b00111111;       //Port C Ausgang
>   DDRD  = 0b00000000;        //Port D Eingang
>   PORTC = 0b00000001;       //PortC.0=1 setzten
>   MCUCR = 0b00000011;  //Int0 wird bei steigender Flanke ausgelöst
>   GICR  = 0b01000000;        //Int0 aktivieren
Das ist übrigens ganz schlecht, man hat sich schnell mal verzählt und 
sucht dann ewig den Fehler. Besser so:
1
DDRC=(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0);
2
...

s. auch Bitmanipulation

von da1l6 (Gast)


Lesenswert?

Hallo nochmal

Habe mir mal den Code angesehen und mit fällt auf:

1. Du solltest Konstanten statt bitmuster nehmen, das erhöht die 
lesbarkeit.
2. Du solltest nur die Bits ändern die du wirklich ändern möchtest, 
statt das ganze Register neu zu setzen. Dabei veränderst du sonst 
womöglich ungewollt andere Funktionen. Dazu in C am einfachsten die |= 
und &= Operatonen verwenden.
Also:
1
  GICR  |= (1 << INT0);        //Int0 aktivieren
statt
1
  GICR  = 0b01000000;

3. Wenn du einen Taster anschließt brauchst du einen definierten Pegel 
wenn der Taster geöffnet ist. Dazu am einfachsten den AVR internen 
Pullup Widerstand aktivieren:
1
PORTD |= (1 << 2)
Dies Aktiviert den Pullup an PD2

da1l6

von Artur G. (artur_g)


Lesenswert?

Alarm und da116 keine Einwände! Ist nicht ganz optimal, muss ich 
zugeben. Aber klärt immernoch nicht, warum er auch im Simulator in 
main() springt.

von Artur G. (artur_g)


Lesenswert?

Hallo,
habe den Code nach den Einwänden bisschen aufgefrischt und siehe da, der 
Code funktioniert wie gewünscht. Ich weiß zwar jetzt nicht was da anders 
sein soll als die Optik, aber naja es läuft.

Danke für die Tipp's.

Das Bit wird übrigends sauber "geshiftet", kein Prellen. Ich weiß muss 
nicht immer so sein. :)
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
5
6
int main (void)
7
{
8
  DDRC  |= (1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0);       //Port C Ausgang
9
  DDRD  |= (0<<2);        //Port D Eingang
10
  PORTC |= (1<<0);       //PortC.0=1 setzten
11
  MCUCR |= (1 << ISC00) | (1 << ISC01);             //Int0 wird bei  steigender Flanke ausgelöst
12
  GICR  |= (1 << INT0);         //Int0 aktivieren
13
  sei();
14
while(1)
15
{
16
  
17
 }
18
19
20
21
}
22
ISR(INT0_vect)        
23
{
24
25
  PORTC = PORTC << 1; 
26
27
}

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.