Forum: Mikrocontroller und Digitale Elektronik ISR mit Timer1 wird nicht aufgerufen


von Johannes (menschenskind)


Lesenswert?

Hallo,

Die ISR in meinem Programm wird weder für den Overflowinterrupt noch für 
den OCRA-Interrupt ausgeführt.

Der Prescaler ist auf 4096 gesetzt und demnach sollte der µC bei 8MHz 
nach ca 130ms den Interrupt auslösen, was er anscheinend nicht tut.

LED_EVENT() macht die LED kurz an und wieder aus.

Hier der Code:
1
#include <util/delay.h>
2
#include <avr/interrupt.h>
3
#include <avr/io.h>
4
#include <avr/sleep.h>
5
6
#include "includes/config.h"
7
#include "includes/debounce.h"
8
#include "includes/light_ws2812.h"
9
10
uint8_t testIndex = 0;
11
12
ISR( TIMER1_OVF_vect ){
13
  LED_EVENT(1);
14
  
15
  if(testIndex == 7)  
16
    testIndex = 0;
17
  if(testIndex == 0)
18
    testIndex = 7;
19
}
20
21
int main(void){
22
  
23
  /**** Set Timer1 for delay functionality ****/
24
  TCCR1 = /*(1<<CTC1)|*/(1<<CS13)|(1<<CS12)/*|(1<<CS11)*/|(1<<CS10);            // set clock prescaler to 4096 --> 512µs per clock cycle
25
  TIMSK = (1<<TOIE1);//(1<<OCIE1A);                    //enable Timer interrupt
26
  //OCR1A = 200;                          // interrupt set after 10ms
27
28
  sei();                // Enable global Interrupts  
29
30
  LED_EVENT(1);
31
  _delay_ms(100);
32
  while(1){
33
    ws2812_setleds(&COLOR[testIndex],1);
34
  }
35
}

Entdeckt ihr meinen Denkfehler?

Danke
Hannes

von Chris L. (kingkernel)


Lesenswert?

1
  if(testIndex == 7)  
2
    testIndex = 0;
3
  if(testIndex == 0)
4
    testIndex = 7;

testIndex wird immer 7 sein, da du testIndex erst auf 0 setzt und in der 
nächsten anweisung direkt wieder auf 7

von holger (Gast)


Lesenswert?

if(testIndex == 7)
    testIndex = 0;
  if(testIndex == 0)
    testIndex = 7;

Schönes Ding;)

Gleich nachdem testIndex = 0 wurde wird er wieder 7;)

von Michael (Gast)


Lesenswert?

Ich habe zwar nicht genau nachgerechnet aber könnte es damit zu tun 
haben?

http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__util__delay_1gad22e7a36b80e2f917324dc43a425e9d3.html

"The maximal possible delay is 262.14 ms / F_CPU in MHz.

When the user request delay which exceed the maximum possible one, 
_delay_ms() provides a decreased resolution functionality. In this mode 
_delay_ms() will work with a resolution of 1/10 ms, providing delays up 
to 6.5535 seconds (independent from CPU frequency). The user will not be 
informed about decreased resolution."

Grüße

von Rainer B. (katastrophenheinz)


Lesenswert?

Neben dem Fehler hier
1
if(testIndex == 7)  
2
    testIndex = 0;
3
  if(testIndex == 0)
4
    testIndex = 7;

muss testIndex auch noch volatile deklariert werden.

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

Johannes H. schrieb:
> ISR( TIMER1_OVF_vect ){
>   LED_EVENT(1);
>
>   if(testIndex == 7)
>     testIndex = 0;
>   elseif(testIndex == 0)
>     testIndex = 7;
> }

Mir ist nicht bekannt, ob 'elseif' in der Sprache bekannt ist, würde die 
Doppelzuweisung aber vermeiden.
Sonst ginge auch ein Case-Block.

Du kannst auch einfach nur +1/-1 zählen und die 8 auf 0 setzen bzw. die 
-1 auf 7.

MfG

von S. Landolt (Gast)


Lesenswert?

Offenbar bin ich der Einzige, der es nicht erkennt, aber ich frage 
trotzdem: um welchen Controller handelt es sich?

von Peter D. (peda)


Lesenswert?

S. Landolt schrieb:
> um welchen Controller handelt es sich?

Ja, Atmel hat die Interrupts oft umbenannt. Es sollte aber eine Warnung 
geben, wenn der unbekannte AVR den Interruptvector nicht kennt.

von Thomas E. (thomase)


Lesenswert?

Peter D. schrieb:
> Ja, Atmel hat die Interrupts oft umbenannt. Es sollte aber eine Warnung
> geben, wenn der unbekannte AVR den Interruptvector nicht kennt.

Wer beachtet denn Warnungen? Das sind doch nur Warnungen.

S. Landolt schrieb:
> Offenbar bin ich der Einzige, der es nicht erkennt, aber ich frage
> trotzdem: um welchen Controller handelt es sich?

Ein Prescaler von 4096 lässt auf den Tiny25..85 schliessen.
Damit passte der Interrupt.

von neuer PIC Freund (Gast)


Lesenswert?

>Entdeckt ihr meinen Denkfehler?

Du lieferst zu wenig Informationen.

Unter simulavr läuft es. Der Interrupt triggert mit 7.62936 Hz.

Also liegt es an dem ci(); innerhalb LED_EVENT().

von Johannes (menschenskind)


Lesenswert?

holger schrieb:
> if(testIndex == 7)
>     testIndex = 0;
>   if(testIndex == 0)
>     testIndex = 7;
>
> Schönes Ding;)
>
> Gleich nachdem testIndex = 0 wurde wird er wieder 7;)

Ohje... hüstel hüstel, das war richtig gedacht aber falsch umgesetzt. 
Mit else if in der Tat lösbar.

Aber das hätte ich ja irgendwann rausgefunden, aber "LED_EVENT" wird ja 
gar nicht ausgeführt. Das Erreichen der ISR schlägt also schon mal fehl.
LED_EVENT funktioniert ja für sich allein.

Es ist ein ATTiny85.

Eine Debounceroutine nutzt den Timer0. Kann es da wegen der Parallelität 
Probleme geben?

: Bearbeitet durch User
von Johannes (menschenskind)


Lesenswert?

neuer PIC Freund schrieb im Beitrag #4894966:
>>Entdeckt ihr meinen Denkfehler?
>
> Du lieferst zu wenig Informationen.
>
> Unter simulavr läuft es. Der Interrupt triggert mit 7.62936 Hz.
>
> Also liegt es an dem ci(); innerhalb LED_EVENT().

Was ist ci();?
Der Interrupt würde viel zu langsam triggern. Bei der angegebenen 
Frequenz samt Prescaler und 256 Zyklen lande ich bei ~130ms.

von Codix (Gast)


Lesenswert?

Mach doch einmal den einfachsten Test den es überhaupt gibt:
Schliesse eine LED mit Vorwiderstand an einen freien Portpin an und
toggle diesen Port (als Ausgang initialisiert) in der Interruptroutine.
Ein Scope an die LED und die kannst am Scope sehen, ob sich dort 
überhaupt
etwas tut.
Oder zu zählt eine volatile definierte Variable im ISR hoch und prüfst 
den
Wert in der main. Bspw. so:
1
volatile int8_t counter;
2
3
main()
4
{
5
    do {
6
7
        
8
        if ( counter > 100){
9
        cli();
10
        PORTx ^= ~(1 << PINx);
11
        counter = 0;
12
        sei();
13
        }
14
        
15
   while(1);
16
}
Dann sollte die LED ca. im Sekundentakt blinken.
So sollte man an das Problem herangehen.

von Johannes (menschenskind)


Lesenswert?

@Codix
Wenn ich meine LED-Routine in die die ISR vom Timer0 packe(die wird 
aller 10ms aufgerufen), dann wird die ja auch ausgeführt.
Also muss ja was an meinen Timer1-Einstellungen falsch sein.

Overflow Interrupt aktiviert -> Check!
Prescaler gesetzt -> Check!
Globale Interrupts gesetzt -> Check!
Richtiger ISR-Vektor -> Check!

Ein Scope habe ich leider nicht zu Hause.


@ PIC Freund
Bitte noch die Fragen beantworten :)

von neuer PIC Freund (Gast)


Angehängte Dateien:

Lesenswert?

> Bitte noch die Fragen beantworten :)

Mit dem typo l gäbe es ein cli().


Ansonsten zeigt es sich hier sehr schön, warum man mit 
IDE/Debugger/Simulator viel schneller vorankommt. Das Studio sollte noch 
viel besser simulieren als simulavr. Aber auch damit klappt es bei dem 
Minimalbeispiel. Insofern liegt der Fehler wohl in dem Codeteil, der 
noch in der Glaskugel gefangen ist.

Und 7.62936 Hz entsprechen einer Periodendauer von ca. 131 ms. Das 
klingt mit 8MHz  4096  256 sehr plausibel.

von Johannes (menschenskind)


Lesenswert?

@PIC Freund
Hm klar, 7 Hz und 130ms korrelieren natürlich.

Also cli() gibt's keins in LED_EVENT. Da drin sieht's so aus:
1
  ws2812_setleds(&COLOR[i],1);  
2
  _delay_ms(200);
3
4
  ws2812_setleds(&COLOR[0],1);  
5
  _delay_ms(100);

Außerdem, wie schon geschrieben, wird das ja in einer ISR vom Timer0 
ganz korrekt ausgeführt.

Ich hab Atmel Studio, aber da springt er nur korrekt in die Timer0-ISR, 
jedoch nicht in die um die's geht :(

Ich hab's auch schon mit ner 2. identischen meiner Platinen probiert: 
ebenso Fehlanzeige. Also ist irgendwo in der Software was "corrupted" :D

von Walter S. (avatar)


Lesenswert?

Johannes H. schrieb:
> Da drin sieht's so aus:  ws2812_setleds(&COLOR[i],1);
>   _delay_ms(200);
>
>   ws2812_setleds(&COLOR[0],1);
>   _delay_ms(100);

also wird der Interrupt für 300ms blockiert

von Johannes (menschenskind)


Lesenswert?

Walter S. schrieb:
> also wird der Interrupt für 300ms blockiert

Ja, aber das hat leider nichts mit dem Problem zu tun...

von Dieter F. (Gast)


Lesenswert?

Johannes H. schrieb:
> Hier der Code:

Nicht vollständig ...

von S. Landolt (Gast)


Lesenswert?

> Nicht vollständig ...

In der Tat. Hier ist von aktiver Timer0-ISR die Rede, wo und wie bitte 
wird diese denn freigegeben, wenn es nur
> TIMSK = (1<<TOIE1);//(1<<OCIE1A);
gibt, und wo ist die Routine selbst?

von Johannes (menschenskind)


Lesenswert?

Dieter F. schrieb:
> Nicht vollständig ...

Ja, die relevanten Zeilen sind aber da bzw. was fehlt Dir?


@all
Das TIFR muss ich ja nicht konfigurieren, korrekt?

von M. K. (sylaina)


Lesenswert?

Thomas E. schrieb:
> Wer beachtet denn Warnungen? Das sind doch nur Warnungen.

Wer arbeitet denn ohne -Wall -Werror?

von Theor (Gast)


Lesenswert?

Johannes H. schrieb:
> Dieter F. schrieb:
>> Nicht vollständig ...
>
> Ja, die relevanten Zeilen sind aber da bzw. was fehlt Dir?

Es liegt ein logischer Widerspruch darin, zum einen den Fehler nicht 
finden zu können, zum anderen aber zu behaupten man wisse was relevant 
ist.

Unter einer gewissen Menge oder Qualität oder Abdeckung von Information 
ist es sogar unmöglich, auch nur annähernd zu sagen, welche Information 
ein Problem aufdecken wird.

von S. Landolt (Gast)


Lesenswert?

> bzw. was fehlt?

Vielleicht etwas in der Art:
  TIMSK = (1<<TOIE0);

von Johannes (menschenskind)


Lesenswert?

@ Landolt:
Das hab ich auskommentiert und dementsprechend nicht mit hier gepostet.
Ich habe den Timer0 erwähnt, weil es da eben funktioniert, aber nicht 
bei Timer1.

von M. K. (sylaina)


Lesenswert?

Johannes H. schrieb:
> Ohje... hüstel hüstel, das war richtig gedacht aber falsch umgesetzt.
> Mit else if in der Tat lösbar.
 Ich würde wohl ein Switch nehmen
1
switch(testIndex){
2
  case 0:
3
    testIndex = 7;
4
    break;
5
  case 7:
6
    testIndex = 0;
7
    break;
8
  default:
9
    break;
10
}

Ist lesbarer, finde ich, und macht das Gleiche.

von Johannes (menschenskind)


Lesenswert?

@Köhler
Stimme zu, das Problem ist aber, dass die ISR überhaupt nicht 
angesprungen wird...

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

TOIE1 dachte ich - geht doch um Timer1, Der nicht will.

Kleine Nebenfrage :)
Wird ggf. das Register TIMSK bei der Zuweisung für den Timer0 
überschrieben und die davor gesetzten Werte (unter Anderem Überlauf 
Timer 1) wird gelöscht?

Hmm, TOIE1 sehe ich im Code, aber für Timer 0 sehe ich Nix - könnte also 
irgendwie passen.

MfG

von Thomas E. (thomase)


Lesenswert?

Patrick J. schrieb:
> Wird ggf. das Register TIMSK bei der Zuweisung für den Timer0
> überschrieben und die davor gesetzten Werte (unter Anderem Überlauf
> Timer 1) wird gelöscht?

Völlig ausgeschlossen. Er hat den Check gemacht:

Johannes H. schrieb:
> Overflow Interrupt aktiviert -> Check!
> Prescaler gesetzt -> Check!
> Globale Interrupts gesetzt -> Check!
> Richtiger ISR-Vektor -> Check!

Wetten würde ich allerdings nicht darauf.

von M. K. (sylaina)


Lesenswert?

Johannes H. schrieb:
> Stimme zu, das Problem ist aber, dass die ISR überhaupt nicht
> angesprungen wird...

Ach, ich dachte das Problem ist jetzt gelöst. Welchen AVR hast du denn 
und mit welcher ClockSource arbeitest du?

von Johannes (menschenskind)


Lesenswert?

Die Timer0-Initialisierungen habe ich ja auskommentiert.

Es geht um den ATTiny85 mit internen 8MHz.

Aber der Fehler sitzt natürlich 30cm vorm Bildschirm...
Weil ich in einer ersten Version nur Timer0 verwendet habe und die 
Schaltung batteriebetrieben ist hatte ich folgende Zeile eingefügt:
1
/**** Power Reduction ****/
2
  PRR = (1<<PRUSI) | (1<<PRADC) | (1<<PRTIM1);

...hüstelhüstel Die hatte ich schon gar nicht mehr wahrgenommen.
Da war Dieter F.s Anmerkung natürlich vollkommen korrekt.

: Bearbeitet durch User
von M. K. (sylaina)


Lesenswert?

Wo hast du denn das drin? Hab ich oben ja gar nicht erkannt. Aber OK, du 
hast es ja jetzt gefunden, Problem also gelöst ;)

von Johannes (menschenskind)


Lesenswert?

Ja, ich hatte mich so auf die Timerkonfiguration fixiert, dass ich diese 
eine Zeile gar nicht mehr "gesehen" habe und nur die vermeintlich 
relevanten Zeilen hier gepostet habe.

von Thomas E. (thomase)


Lesenswert?

M. K. schrieb:
> Wo hast du denn das drin?

In dem Teil des Codes, in dem der Fehler garantiert nicht lag.

Hätte er den ganzen Code von Anfang an gezeigt, wäre das Problem gestern 
um spätestens 20.30h gelöst gewesen.

Johannes H. schrieb:
> und nur die vermeintlich
> relevanten Zeilen hier gepostet habe.

Kopf-Tisch, mein Lieber.

: Bearbeitet durch User
von neuer PIC Freund (Gast)


Lesenswert?

> und nur die vermeintlich relevanten Zeilen

Und warum hast du dein einfaches Beispiel von oben nicht mal selbst 
ausprobiert?

Ansonsten klassischer Anfängerfehler: Peripherie will Takt und Strom.

von M. K. (sylaina)


Lesenswert?

Johannes H. schrieb:
> Ja, ich hatte mich so auf die Timerkonfiguration fixiert, dass ich
> diese
> eine Zeile gar nicht mehr "gesehen" habe und nur die vermeintlich
> relevanten Zeilen hier gepostet habe.

Am besten immer an die Foren-Regel halten: Ein komplettes Beispiel 
posten, dass den Fehler enthält/zeigt. Oft findet man beim Erstellen des 
Beispiels dann den eigenen Fehler und es kommt erst gar nicht zum Thread 
;)
Übrigens: Benutze bei ca. 130 ms doch den Watchdog im ISR-Mode. Vorteil: 
Der kann dir den AVR auch aus dem PWR-DOWN heraus aufwecken und weniger 
Strom kann man praktisch nicht verbraten beim AVR.
Brauchst du denn unbedingt die 8 MHz? Gff. kann man auch hier den 
Watchdog als Taktquelle (also den internen 128 kHz Oszillator) benutzen. 
Grade für Batteriebetrieb ist das eine Überlegung wert. Der Strombedarf 
kann so locker deutlich unter 100 uA fallen für den AVR.

von Theor (Gast)


Lesenswert?

Johannes H. schrieb:
> Ja, ich hatte mich so auf die Timerkonfiguration fixiert, dass ich diese
> eine Zeile gar nicht mehr "gesehen" habe und nur die vermeintlich
> relevanten Zeilen hier gepostet habe.

Na schön. So was passiert einfach.
Aber spätestens meine folgende Bemerkung hätte Dich eigentlich aufmerken 
lassen sollen.

Theor schrieb:
> Johannes H. schrieb:
>> Dieter F. schrieb:
>>> Nicht vollständig ...
>>
>> Ja, die relevanten Zeilen sind aber da bzw. was fehlt Dir?
>
> Es liegt ein logischer Widerspruch darin, zum einen den Fehler nicht
> finden zu können, zum anderen aber zu behaupten man wisse was relevant
> ist.

Ist schon frustrierend, wenn die Fragesteller einfach nicht hören 
wollen, was man ihnen rät.

von Thomas E. (thomase)


Lesenswert?

M. K. schrieb:
> Übrigens: Benutze bei ca. 130 ms doch den Watchdog im ISR-Mode. Vorteil:
> Der kann dir den AVR auch aus dem PWR-DOWN heraus aufwecken und weniger
> Strom kann man praktisch nicht verbraten beim AVR.

Den niedrigsten Stromverbrauch mit Selbstaufweckmechanismus erreicht man 
mit Uhrenquarz an Timer 2 im Asynchronmodus.

M. K. schrieb:
> Brauchst du denn unbedingt die 8 MHz? Gff. kann man auch hier den
> Watchdog als Taktquelle (also den internen 128 kHz Oszillator) benutzen.
> Grade für Batteriebetrieb ist das eine Überlegung wert. Der Strombedarf
> kann so locker deutlich unter 100 uA fallen für den AVR.

Das Runtertakten macht nur wirklich Sinn, wenn der Controller die ganze 
Zeit laufen muß. Ansonsten sind Sleep und normaler Takt günstiger und 
100µA eher ein lächerliches Ziel. Da geht noch wesentlich weniger.

von M. K. (sylaina)


Lesenswert?

Thomas E. schrieb:
> 100µA eher ein lächerliches Ziel. Da geht noch wesentlich weniger.

Deswegen schrieb ich ja:

M. K. schrieb:
> Der Strombedarf
> kann so locker deutlich unter 100 uA fallen

;)

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.