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_ttestIndex=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
intmain(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
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
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
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.
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.
>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().
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?
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.
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
volatileint8_tcounter;
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.
@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 :)
> 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.
@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
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
> 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?
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?
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.
@ 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.
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
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
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.
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?
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.
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.
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.
> 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.
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.
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.
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.
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
;)