Interrupt mit atmega8

OP #2569095
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
}
Gast #2569154
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
Gast #2569170
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
OP #2569247
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
}

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