Forum: Mikrocontroller und Digitale Elektronik Probleme mit dem isr(int0_vect)


von Tuji de Assis M. (tujideassis_m)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich steh hier leider vor einem Problem.

ISR (INT0_vect)
{

  setLedMode(15,true);

}

Ich wollte eigentlich das bei einem Interrupt eine Led immer 
eingeschaltet wird.

Mein Problem ist gerade, dass der Interrupt immer ausgelöst wird, sobald 
mein µC geflasht worden ist mit meinem neuen Programm.

Es liegt immer 5 V an und bei einem Interrupt fällt die Flanke auf 0 V.
(ich denke daran liegt der fehler).

Hier ist die Doku für die Lichtschranke:
http://www.produktinfo.conrad.com/datenblaetter/125000-149999/140268-da-01-en-IR_SENSOR_APDS_9102_L22.pdf

und es handelt sich um ein ATMEGA88.


Danke im Vorraus!

von Gerald G. (gerald_g)


Lesenswert?

Zeige mal die Initialisierung deines Programms

von Tuji de Assis M. (tujideassis_m)


Lesenswert?

1
//TIMSK0 |= (1 << TOIE0);
2
  //TCCR0B |= (1<<CS00 | 0<<CS01 | 0<<CS02);
3
  // Port B auf Ausgang setzen
4
  DDRB = 0xff;
5
  // Port C auf Ausgang setzen
6
  DDRC  = 0xff;
7
  // Port D auf Ausgang setzen
8
  DDRD = 0xff;
9
  // Lichtschranke PD2 auf Eingang
10
  DDRD = DDRD & ~(1<<PD2);
11
12
  // LEDs auf den Ports ausschalten
13
  PORTB = 0xff;
14
  PORTC = 0xff;
15
  PORTD = 0xff;
16
  
17
  EIMSK |= _BV(INT0);    // PD2 = INT0 enablen
18
  EICRA |= _BV(ISC01);  // Triggern auf fallende Flanke des INT0
19
20
  //Timer1 fuer die Umlaeufe konfigurieren
21
  TCCR1B = (1 << CS10) | (1 << CS21) ;  //kein Prescaler
22
  TIMSK1 = (1 << TOIE1) | (1 << OCIE1A) ;
23
  
24
  TIMSK2 |= (1 << TOIE2);
25
  TCCR2B |= (1<<CS20 | 0<<CS21 | 0<<CS22);
26
27
  // Timer0 fuer die Stundenanzahl konfigurieren
28
  // CompareMatchInterupt ausloesen
29
  // Timer0 fuer die Uhrzeiten-Logik und Overflow fuer Timer0
30
  TIMSK0 = _BV(OCIE0A) | _BV(TOIE0);  // Enable Interrupt TimerCounter0 Compare Match A (SIG_OUTPUT_COMPARE0A)
31
  TCCR0A = _BV(WGM01);        // Mode = CTC
32
  TCCR0B = _BV(CS02) | _BV(CS00);    // Clock/1024, 0.001024 seconds per tick
33
  OCR0A = 244;            // 0.001024*244 ~= .25 SIG_OUTPUT_COMPARE0A will be triggered 4 times per second.
34
  
35
  // Das Makro sei() schaltet alle Interrupts ein.
36
  sei();

: Bearbeitet durch User
von Thomas K. (thomas_k39)


Lesenswert?

Tuji de Assis Moreira schrieb:
> // Port D auf Ausgang setzen
>   DDRD = 0xff;
>   // Lichtschranke PD2 auf Eingang
>   DDRD = DDRD & ~(1<<PD2);

Diese Initialisierung produziert einen kurzen Low-Impuls auf PD2 und 
triggert damit den INT0!

Wieso den Port D nicht gleich richtig initalisieren?
1
  DDRD = 0xff & ~(1<<PD2);

von Thorsten S. (thosch)


Lesenswert?

Unabhängig von dem ISR-Problem: Mach mal Deine Schaltung heil!

AVCC muß an VCC angeschlossen werden (und mit 100nF gegen GND 
geblockt), auch dann, wenn der A/D-Wandler nicht benutzt wird.
Der Pin versorgt nämlich nicht nur den A/D-Wandler,
sondern auch PORT C (PC0..PC3).

(siehe Datenblatt, Seite 6)

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Es ist auch eine gute Idee, vor der Freigabe des Interruptes etwaige 
anstehende Anforderungen zu löschen:
1
EIFR = (1<<INTF0);

von Tuji de Assis M. (tujideassis_m)


Lesenswert?

Port C wird für die RGB LED´s verwendet.(Charlie-Plexing)

Hat das was mit der Lichtschranke zu tun?

von Tuji de Assis M. (tujideassis_m)


Lesenswert?

Matthias Sch. schrieb:
> Es ist auch eine gute Idee, vor der Freigabe des Interruptes
> etwaige
> anstehende Anforderungen zu löschen:EIFR = (1<<INTF0);


Habe es versucht und trotzdem, funktioniert es nicht.

von Tuji de Assis M. (tujideassis_m)


Lesenswert?

Hat niemand eine Ahnung ?
oder überhaupt, an was es liegen könnte, warum der interrupt immer 
ausgelöst wird?

von Karl H. (kbuchegg)


Lesenswert?

Tuji de Assis Moreira schrieb:
> Hat niemand eine Ahnung ?
> oder überhaupt, an was es liegen könnte, warum der interrupt immer
> ausgelöst wird?

Weil die Erkennungslogik nicht riechen kann, ob die Bedingung zur 
Registreierung eines Interrupts jetzt deswegen eingetreten ist, weil 
sich am Eingang tatsächlich eine Flanke ereignet hat, oder ob diese 
Flanke 'pseudo-mässig' dadurch enstanden ist, dass du die 
Auswertebedingungen während der Intialisierungsphase des Programms 
geändert hast.

Nachdem alles fertig konfiguriert ist, lösche eventuell aufgelaufene 
'falsche und unerwünschte' Interrupt Anforderungen ehe du mit sei() 
alles für den tatsächlichen Betrieb freigibst und gut ists.
Das ist weder anrüchig noch schlechte Praxis.

Hinweis: derartige Interrupt-Registrierungsflags werden durch 
Einschreiben eines 1-Bits an der entsprechenden Bitposition ins 
entsprechende Register gelöscht.

: Bearbeitet durch User
von Tuji de Assis M. (tujideassis_m)


Lesenswert?

Karl Heinz schrieb:
> Weil die Erkennungslogik nicht riechen kann, ob die Bedingung zur
> Registreierung eines Interrupts jetzt deswegen eingetreten ist, weil
> sich am Eingang tatsächlich eine Flanke ereignet hat, oder ob diese
> Flanke 'pseudo-mässig' dadurch enstanden ist, dass du die
> Auswertebedingungen während der Intialisierungsphase des Programms
> geändert hast.

Ich hab versucht es zurückzusetzen.
Iwie funktioniert es aber nicht, vllt habe ich es nur falsch gemacht:
GIFR = (1<<INF1);
EIFR = (1<<INTF0);


Habe ich das was falsches gemacht?
Wie heißt den der Code zum zurück setzen?

von spess53 (Gast)


Lesenswert?

Hi

>und es handelt sich um ein ATMEGA88.

>GIFR = (1<<INF1);

Wo hat der ATMEga88 ein GIF-Register?

MfG Spess

von Stefan P. (form)


Lesenswert?

Was macht denn setLedMode(15,true); ?

von Tuji de Assis M. (tujideassis_m)


Lesenswert?

Stefan P. schrieb:
> Was macht denn setLedMode(15,true); ?

Ich hab auf meiner Platine 16 LED´s.
Wenn diese methode aufgerufen wird, wird die LED eingeschalten.
Das Problem bei der ganzen Sache ist, dass der immer anbleibt(ist ja 
auch richtig).

Aber wenn ich in meiner Main dann sage, schalte die LED wieder aus, 
leuchtet die LED auf und wieder zu, die ganze zeit.

Darum denke ich, dass diese ISR(INT0_vect) immer wieder aufgerufen wird, 
obwohl kein externer Interrupt geschieht.

von Tuji de Assis M. (tujideassis_m)


Lesenswert?

spess53 schrieb:
> Wo hat der ATMEga88 ein GIF-Register?
>
> MfG Spess

Muss ehrlich zugeben, dass ich noch ein newbie bin.
Ich kenne mich halt nicht perfekt aus, suche mir gerade alles ausm 
Internet zusammen.
Versuche aber auf über den µController zu lernen.
Aber es tut sich einfach nicht.

von Tuji de Assis M. (tujideassis_m)


Lesenswert?

Kann es vielleicht sein, dass ich diese Register setzen muss:

GICR|=0x40;
MCUCR=0x02;

Ich bin mir halt nicht sicher.

von Karl H. (kbuchegg)


Lesenswert?

Tuji de Assis Moreira schrieb:

> Darum denke ich, dass diese ISR(INT0_vect) immer wieder aufgerufen wird,
> obwohl kein externer Interrupt geschieht.

Zeig doch mal dein ganzes Programm.
Immer diese Ratespielchen von wegen: ich denke, das das und das 
passiert.


Unabhängig davon: wenn man den Verdacht hat, dass eine bestimmte 
Komponente ein Problem verursacht, dann ist es auch kein Beinbruch sich 
erst mal ein Testprogramm zu machen, welches nur und ausschliesslich 
diese Komponente testet.
In deinem Fall willst du wissen, ob der externe Interrupt korrekt 
funktioniert. Dazu braucht es keinen Timer oder sonstiges Zeugs. Einfach 
nur dir Lichtschranke und die LED um das Ansprechen der Lichtschranke 
anzuzeigen. Mehr braucht es dazu nicht. Dann läuft man auch nicht 
Gefahr, dass man sich mit all den anderen Zusatzteilen im Programm 
irgendwo einen Bock geschossen hat, den man selbst nicht mehr findet. 
Bei der Fehlersuche bzw. wenn man erst mal ratlos ist, ist die 
Konzentration aufs Wesentliche der erste wichtige Punkt. Alles was 
nichts mit diesem Wesentlichen zu tun hat, fliegt erst mal raus.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Tuji de Assis Moreira schrieb:
> Kann es vielleicht sein, dass ich diese Register setzen muss:
>
> GICR|=0x40;
> MCUCR=0x02;
>
> Ich bin mir halt nicht sicher.


Das weiß ich nicht, weil ich eine Abneigung dagegen habe, einzelne BIts 
(die eine Bedeutung haben, die sich in ihrem Namen wiederspiegelt) per 
Hex-Zahl zu setzen.

Die Bits haben Namen. Atmel hat dir diese Namen zur Verfügung gestellt. 
Benutzte sie auch!
Immer dieses Hex-Zahl mit dem Datenblatt auseinanderpfriemeln. Da 
scrollt man sich doch regelmässig einen Tennisarm beim Nachverfolgen im 
PDF.

von Tuji de Assis M. (tujideassis_m)


Angehängte Dateien:

Lesenswert?

Am besten  wäre es wenn sie das komplette Projekt mit Atmel Studio 
öffnen.

von Karl H. (kbuchegg)


Lesenswert?

Tuji de Assis Moreira schrieb:

> Darum denke ich, dass diese ISR(INT0_vect) immer wieder aufgerufen wird,
> obwohl kein externer Interrupt geschieht.


IN deinem Eröffnungsposting klingt das alles aber nocht ganz anders

> Mein Problem ist gerade, dass der Interrupt immer ausgelöst wird,
> sobald mein µC geflasht worden ist mit meinem neuen Programm.

da ist vom Einspielen eines neuen Programms die Rede.

Was denn nun?

von Karl H. (kbuchegg)


Lesenswert?

Tuji de Assis Moreira schrieb:
> Am besten  wäre es wenn sie das komplette Projekt mit Atmel Studio
> öffnen.

Nö. Sorry. Aber das tu ich mir nicht an.

Entweder du reduzierst dein Programm auf einen einfachen Fall
* lichtschranke + 1 LED
oder du musst dir den Fehler selbst suchen

von Tuji de Assis M. (tujideassis_m)


Lesenswert?

Das ist immer noch das alte Programm. Mit kleinen Veränderungen die mir 
hier vorgeschlagen worden ist.

von Karl H. (kbuchegg)


Lesenswert?

Tuji de Assis Moreira schrieb:
> Das ist immer noch das alte Programm. Mit kleinen Veränderungen die mir
> hier vorgeschlagen worden ist.

Ja. Aber ich analysiere jetzt nicht 30 Minuten lang, was da im Programm 
alles abgeht und welche Querverflechtungen für welchen Effekt 
verantwortlich sein könnten, wenn ein simples
1
#include <avr/io.>
2
#include <util/delay.h>
3
4
int main()
5
{
6
  DDRC = 0xFF;
7
8
  EIMSK |= _BV(INT0);    // PD2 = INT0 enablen
9
  EICRA |= _BV(ISC01);   // Triggern auf fallende Flanke des INT0
10
  PORTD |= _BV(PD2);
11
12
  while( 1 ) {
13
    PORTC |= _BV( PC0 );
14
    _delay_ms( 1000 );
15
  }
16
}
17
18
ISR (INT0_vect)
19
{
20
  PORTC &= ~ _BV( PC0 );
21
}

... auch ausreichend ist, um die Funktion des externen Interrupts für 
sich alleine zu testen.


Und bei sowas
1
ISR (INT0_vect)
2
{
3
  turnOffLeds();
4
  _delay_ms(5000);
5
....
fangen bei mir sowieso alle Alarmglocken zu klingeln an.

: Bearbeitet durch User
von Tuji de Assis M. (tujideassis_m)


Lesenswert?

Karl Heinz schrieb:
> Nö. Sorry. Aber das tu ich mir nicht an.
>
> Entweder du reduzierst dein Programm auf einen einfachen Fall
> * lichtschranke + 1 LED
> oder du musst dir den Fehler selbst suchen
1
int main (void)
2
{
3
  init();
4
  
5
  
6
  
7
}
8
9
/************************************************************************/
10
/* Initialisierungsmethode                                              */
11
/************************************************************************/
12
void init() {
13
  board_init();
14
  resetRegisters();  
15
  // Port D auf Ausgang setzen
16
  DDRD = 0xff;
17
  // Lichtschranke PD2 auf Eingang
18
  DDRD = DDRD & ~(1<<PD2);
19
20
  // LEDs auf den Ports ausschalten
21
22
  PORTD = 0xff;
23
  
24
  EIMSK |= _BV(INT0);    // PD2 = INT0 enablen
25
  EICRA |= _BV(ISC01);  // Triggern auf fallende Flanke des INT0
26
27
28
29
30
  // Das Makro sei() schaltet die Interrupts ein.
31
  sei();
32
}
33
34
void resetRegisters() {
35
  // Port D auf Ausgang setzen
36
  DDRD = 0b11100111;
37
  // Lichtschranke PD2 auf Eingang
38
  DDRD = DDRD & ~(1<<PD2);
39
  
40
  DDRC = 0x00;
41
  PORTC = 0x00;
42
  PORTD = 0x00;
43
}
44
/************************************************************************/
45
/*  Lichtschranken-Interrupt                                            */
46
/*  Hier Timer starten für Counter der Umläufe und der Geschwindigkeit. */
47
/************************************************************************/
48
ISR (INT0_vect)
49
{
50
  turnOffLeds();
51
  _delay_ms(5000);
52
}

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>Kann es vielleicht sein, dass ich diese Register setzen muss:
>GICR|=0x40;
>MCUCR=0x02;

>Ich bin mir halt nicht sicher.

Welchen Controller setzt du nun wirklich ein?

MCUCR/GICR/GIFR gehören zum ATMega8. Beim ATMega88 heißen die 
richtigen Register EICRA, EIMSK und EIFR.

Könnte es sein, das du dein Programm für einen ATMega8 compilierst?

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

Tuji de Assis Moreira schrieb:

>
1
> int main (void)
2
> {
3
>   init();
4
> 
5
> 
6
> 
7
> }
8
>


schon besser.
Aber da fehlt die obligate Hauptschleife.
Ohne Hauptschleife läuft das Programm aus main() raus zurück in die 
C-Runtime. Und die hat als erstes nichts besseres zu tun, als alle 
Interrupts mittels eines cli() abzuschalten.
Daher braucht JEDES Programm eine Hauptschleife. Selbst wenn die leer 
ist. Du willst das Programm aus main() nie wieder rauslassen.
1
int main (void)
2
{
3
  init();
4
5
  while( 1 )
6
    ;
7
}

: Bearbeitet durch User
von Tuji de Assis M. (tujideassis_m)


Lesenswert?

Ich verwende einen ATMEGA 88 und kompelieren tu ich das auch für einen 
ATMEGA 88.

von Tuji de Assis M. (tujideassis_m)


Lesenswert?

Karl Heinz schrieb:
> #include <avr/io.>
> #include <util/delay.h>
>
> int main()
> {
>   DDRC = 0xFF;
>
>   EIMSK |= _BV(INT0);    // PD2 = INT0 enablen
>   EICRA |= _BV(ISC01);   // Triggern auf fallende Flanke des INT0
>   PORTD |= _BV(PD2);
>
>   while( 1 ) {
>     PORTC |= _BV( PC0 );
>     _delay_ms( 1000 );
>   }
> }
>
> ISR (INT0_vect)
> {
>   PORTC &= ~ _BV( PC0 );
> }


Was machen Sie da im Interrupt ?
Weil bei mir 2 Led´s aufleuchten.

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.