Forum: Mikrocontroller und Digitale Elektronik Probleme mit Interrupts


von Jo (Gast)


Lesenswert?

Hey Zusammen!
Ich habe Probleme mit dem Timer 0 im Zusammenhang mit AVR Studio. Ich 
hab versucht ein früheres Programm das mal funktioniert hat (nicht auf 
AVR Studio programmiert) mittels AVR Studio zu programmieren, da das 
Alte nicht mehr vorhanden ist.

Der Timer 0 zählt auch hoch, aber es wird nie ein Interrupt ausgelöst.

Bin schon ziemlich am Verzweifeln!

Besten Dank schon mal!

Unten mal der Code:


  #include <avr/io.h>
  #include <avr/interrupt.h>
  #include <avr/wdt.h>

int main (void)
{
  IO_Init ();      //Hardware initialisieren
  wdt_disable()

  TCCR0A = 0;
  TCCR0B |= (0<<WGM02)|(1<<CS02) |(0<<CS01) | (0<<CS00);
  TIMSK0 |= (0<<OCIE0A)|(1<<TOIE0);
  sei();

  while(1)
  {
  }

  return(0);
}

ISR (TIMER0_OVF_vect)
{
  PORTD |= (1<<PD2);
}

von Peter D. (peda)


Lesenswert?

Per default geht ein freigegebener Interrupt aber fehlender 
Interrupthandler zum Resetvector.


Peter

von Dietrich L. (dietrichl)


Lesenswert?

Welcher µC?

von Jo (Gast)


Lesenswert?

Ich benutze den ATMEGA168A

von Jo (Gast)


Lesenswert?

Ich verstehe nicht ganz was du mit Interrupthandler meinst?

von Jo (Gast)


Lesenswert?

besser gesagt, verstehe ich nicht warum der Handler nicht freigegeben 
sein soll?

von MWS (Gast)


Lesenswert?

Jo schrieb:
> besser gesagt, verstehe ich nicht warum der Handler nicht freigegeben
> sein soll?

Jo schrieb:
> (0<<OCIE0A)

Ohne ISR (Interrupthandler) keine Freigabe, da dann der Defaultvektor in 
der Interruptvektortabelle auf den Resetvektor weist.

von Krapao (Gast)


Lesenswert?

>   PORTD |= (1<<PD2);

Du überwachst wahrscheinlich PD2, um festzustellen, ob der Interrupt 
kommt oder nicht?

>   IO_Init ();      //Hardware initialisieren

Wird da auch DDRD für PD2 auf Ausgang gesetzt?

> TCCR0B |= (0<<WGM02)|(1<<CS02) |(0<<CS01) | (0<<CS00);

Prescaler 256
Angenommen du arbeitest mit der Werkseinstellung (1 MHz interner Takt)
1000000/256/256 = 6,6 ms
Hast du ein Messgerät, um das Pintoggeln alle 6,6 ms festzustellen?

von Krapao (Gast)


Lesenswert?

s/6,6 ms 66 ms

von Krapao (Gast)


Lesenswert?

Rechner falsch abgelesen => 66 ms statt 6.6 ms

von Jo (Gast)


Lesenswert?

Genau ich überwache den Interrupt jetzt vorläufit mal mit dem PD2, den 
ich auch als Ausgang konfiguriert habe.
Ich habe auch ein Oszilloskop dran, aber mindestens einmal sollte die 
Lammpe ja angehen, dann weiß ich auch ob der Interrupt gekommen ist oder 
nicht. Bis jetzt geht sie nie an.

von Krapao (Gast)


Lesenswert?

Dann setze den Ausgang mal im Hauptprogramm und warte, bis der Interrupt 
sie ausschaltet. Wenn das Setzen im hauptprogramm nicht funktioniert ist 
der Interrupt unschuldig. Dann ist vielleicht die Schaltung fehlerhaft!

von Krapao (Gast)


Lesenswert?

Achso - was macht das Programm im Einzelschrittmodus im Simulator?

von Jo (Gast)


Lesenswert?

Hab ich schon!
Die LED funktioniert schon, aber der Interrupt kommt halt nie!

von Krapao (Gast)


Lesenswert?

Wenn der Watchdog mal per Fuse WDTON an war (Inhalt der Fuses?), dann 
die Fuse disablen (Schaltung stromlos machen nicht vergessen! 
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Watchdog#WDTON_Fuse_zur.C3.BCcksetzen)

Oder wenn der Watchdog per Software aktiv war das wdt_disable() noch 
früher machen 
(http://www.mikrocontroller.net/articles/AVR-Tutorial:_Watchdog#WDT_nach_einem_Reset).

Was macht das Programm im Simulator?

von Jo (Gast)


Lesenswert?

Der Simulator springt nach dem Abarbeiten des sei() Befehls gleich 
wieder hoch zum Init()-Befehl.

Also bringt er irgendwie RESET?

von Krapao (Gast)


Lesenswert?

Geh im Simulator in den Disassembler, nicht in das C-Fenster und 
kontrolliere im Einzelschritt: Über welchen Vektor macht er den Sprung 
nach Init. Anhand der Vektornummer über den der Sprung passiert findest 
du raus, welche ISR fehlt. Die Zuordnung Vektornummer findest du im 
Datenblatt und in avr/include/avr/iomx8.h.

von Krapao (Gast)


Lesenswert?

Kontrolliere in deiner Toolchain, ob es TIMER0_OVF_vect gibt oder ob es 
in deiner (älteren) Toolchain anders definiert ist.

Die Toolchain wirft zwar ggf. eine Warnung bei unbekanntem Namen, aber 
gelegentlich überliest man die, weil sie in einem anderen Fenster in der 
IDE erscheint.

Hier der "Universal"-Code für neue/alte Toolchain aus dem 
AVR-GCC-Tutorial:
1
#ifndef TIMER0_OVF_vect
2
// Für ältere WinAVR Versionen z.B. WinAVR-20071221 
3
#define TIMER0_OVF_vect TIMER0_OVF0_vect
4
#endif

von Krapao (Gast)


Lesenswert?

Kontrolliere auch, ob du unter Projektoptionen als Target auch den 
ATMEGA168A eingestellt hast. Bei falscher Einstellung liegen die 
Vektoren u.U. woanders und der Reset ist klar!

von Jo (Gast)


Lesenswert?

-Fuses: hab ich geschaut und auch die Stelle von wdt_disable geändert
-Dissambler: hab ich auch versucht und gemerkt, dass er nach sei() in 
Assembler den Aufruf "RJMP      PC-0x0000" bringt. Das heißt der springt 
ins Nirgendwo oder?

von Jo (Gast)


Lesenswert?

Target: passt auch

von Jo (Gast)


Lesenswert?

Toolchain: hilft leider auch nicht

von Karl H. (kbuchegg)


Lesenswert?

Da dein Programm Syntax Error enthält
1
int main (void)
2
{
3
  IO_Init ();      //Hardware initialisieren
4
  wdt_disable()

geh ich davon aus, dass das wieder mal nicht das richtige Programm ist, 
welches auf deinem µC läuft.

Korrigiert man ihn und ersetzt IO_init() durch
DDRD = (1<<PD2);
funktioniert dein Programm im SImulator

von Karl H. (kbuchegg)


Lesenswert?

Jo schrieb:

> Assembler den Aufruf "RJMP      PC-0x0000" bringt. Das heißt der springt
> ins Nirgendwo oder?

Nein. Das implementiert die Endlosschleife
1
  while( 1 ) {
2
  }

von Jo (Gast)


Angehängte Dateien:

Lesenswert?

Nach dem RJMP springt er dann zu 0000001C und dreht da seine Runden und 
geht dann irgendwann wieder zum Start.
Weiß gar nicht ob das wirklich Reset ist

Hab im Anhang mal das Programm als zip.

Bin die nächste halbe Stunde mal kurz weg, aber dann wieder da.

Vielen vielen Dank schon mal für die riesen Hilfe!

von Karl H. (kbuchegg)


Lesenswert?

Jo schrieb:

> Hab im Anhang mal das Programm als zip.

Was wird das?
1
ISR (TIMER0_OVF_vect)
2
{
3
  PORTD |= (0<<PD2);
4
}

--->     PORTD &= ~(1<<PD2);
wenn du das Bit löschen willst, dass du in main gesetzt hast.


Und du bist sicher, dass du einen einzelnen Puls am PD2 Pin im Oszi 
siehst?
Tausch das mal gegen
1
ISR (TIMER0_OVF_vect)
2
{
3
  PORTD ^= (1<<PD2);
4
}
dann toggelt das Teil und du hast alle Zeit der Welt Messungen 
vorzunehmen.



Und das
1
  PCMSK0 |= (1<<PCINT0);
2
3
....
4
5
ISR (PCINT2_vect)

macht dich nicht irgendwie stutzig?

von Jo (Gast)


Lesenswert?

zu ISR (TIMER0_OVF_vect):
Der PD2 soll ausgehen als Zeichen, dass der Interrupt ausgelöst wurde
Kann genauso auch umgedreht werden.


zu ISR (PCINT2_vect):
den hätte ich rauslöschen sollen. Der war als Versuch ob überhaupt 
Interrupts ausgelöst werden können und das hat funktioniertl. Tut aber 
nicht zur Sache

von Karl H. (kbuchegg)


Lesenswert?

Jo schrieb:

> den hätte ich rauslöschen sollen.

Du sollst in erster Linie das Programm posten, mit dem du auch 
tatsächlich testest! Sonst suchen wir Fehler, die nicht in deinem 
eigentlichen Programm enthalten sind.
Wenn du abspeckst, dann teste das abgespeckte, ob es noch die gleichen 
Symptome zeigt.

Mit dem Posten von extra für das Forum hergerichteten Code, der so nie 
getestet wurde, kann man sich hier ganz schnell unbeliebt machen.

von Jo (Gast)


Lesenswert?

PORTD |= (1<<PD2) mach, da dann die Lampe gesetzt bleibt. Sie wird ja 
erst ausgemacht, wenn der Controller neu initialisiert, solange ist sie 
an.

Dann sehe ich ob sie durch den Interrupt mindenstens einmal an bzw. aus 
gemacht wurde

von Jo (Gast)


Angehängte Dateien:

Lesenswert?

Es war nicht meine Absicht euch zu verwirren. Ich hab den Code auch 
vorher getestet, aber es übersehen.
Hab einfach schon viel probiert.
Habs jetzt nochmal bereinigt.

Entschuldigt bitte!

von Jo (Gast)


Lesenswert?

Und mein Programm ist momentan einfach so klein, da ich es selbst aufs 
wesentliche reduziert hab, da ich den Fehler mit den Timerinterrupts 
nicht finde.

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.