ISR mit Timer1 wird nicht aufgerufen

OP #4894838
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
Gast #4894846
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
#4894875
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
#4894918
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.
OP #4895064
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?
OP #4895068
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.
Gast #4895076
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.
OP #4895709
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 :)
Gast #4895820
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.
Angehängte Dateien:
OP #4895891
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
Gast #4895962
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?
Gast #4895979
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.
#4896063
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
#4896070
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.
OP #4896094
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.
Gast #4896108
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.
#4896112
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.
Gast #4896125
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.
#4896126
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.

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