Hallo!
Ein Interrupt setzt flag=1 => ok.
In der while Schleife wird i hochgezählt und sollte Port B7 toggeln =>
nicht ok.
Habe es testhalber mit einem anderen Interrupt probiert, in beiden
Interrupts toggelt B7 korrekt.
Beim Durchlesen der Forensuche bin ich leider nicht fündig geworden.
Wie kann ich den Fehler weiter eingrenzen?
korrekt.
Will nachher in der while Schleife OCR1A und OCR1B Registerinhalte
ändern und die beiden PWM-Kanäle des Timer1 nutzen.
Es ist ein fehlerfrei kompilierbares Testprogramm für eine Attiny 2313,
um den Fehler nachzuvollziehen.
Aus diesem Grund sind Programmteile enthalten, die ich später ev. noch
nutzen werde.
Hallo Achim,
danke für deine Antwort.
Das Register ICR1 (InputCaptureRegister1) ist TOP im gewählten
PWM-Modus.
In der Interruptliste des Datenblatts habe ich den TIMER1_CAPT_vect
gefunden.
Wenn der Wert ICR1 verändert wird, ändert sich aliquot die Periodendauer
der angezeigten Rechteckspannung am Oszi, PORTB ^= (1 << PB7) natürlich
entkommentiert.
Wenn PORTB ^= (1 << PB7) in der Schleife steht, zeigt das Oszi dieselbe
Rechteckspannung.
Controller ist der Attiny2313.
If an unexpected interrupt occurs (interrupt is enabled and no handler is installed, which usually indicates a bug), then the default action is to reset the device by jumping to the reset vector. You can override this by supplying a function named BADISR_vect which should be defined with ISR() as such. (The name BADISR_vect is actually an alias for __vector_default. The latter must be used inside assembly code in case <avr/interrupt.h> is not included.)
6
7
#include <avr/interrupt.h>
8
9
ISR(BADISR_vect)
10
{
11
// user code here
12
}
an. Wenn ich das richtig interpretiere, bekommst Du Resets für die
Interrupts ohne ISR. Das war wohl auch der Hinweis von Walter.
ggggast schrieb:> korrekt.
Nein.
> Will nachher in der while Schleife OCR1A und OCR1B Registerinhalte> ändern und die beiden PWM-Kanäle des Timer1 nutzen.
Man baut keine Sachen halb ein, die man später nutzen will. Das ist
halbgar.
> Es ist ein fehlerfrei kompilierbares Testprogramm für eine Attiny 2313,> um den Fehler nachzuvollziehen.
Der Compiler ist böse. Der lässt dich mit deinen fehlenden und falschen
ISRs voll auf die Schnauze fliegen. Wahrscheinlich grinst er sogar noch
dabei.
> Aus diesem Grund sind Programmteile enthalten, die ich später ev. noch> nutzen werde.
S.o: halbgar!
> In der Interruptliste des Datenblatts habe ich den TIMER1_CAPT_vect> gefunden.
Schön. Da sind noch mehr drin. Bau die doch auch mit ein.
Wenn du einen Interrupt möchtest, der bei TOP zuschlägt, also wenn
TCNT1==ICR1, dann nimmst du den Overflow:
1
ISR(TIMER0_OVF_vect)
2
{
3
//PORTB ^= (1 << PB7);
4
//b++;
5
6
//PORTB ^= (1 << PB7);
7
flag=1;
8
}
Siehe auch Datenblatt, Table 16-4, Mode 14, rechte Spalte.
Und schalte die Interrupts, für die keine ISR vorhanden ist, ab. Auch
wenn die später noch benutzt werden sollen. Oder benutz den Würgaround
mit BADISR.
mfg.
Eigentlich nutzt er ja Timer 1, da ist TIMER0_OVF_vect u.U. nicht
passend.
In der Doku steht auch bei Fast PWm Mode (Figure 46)
1
OCRnx/TOP Update and
2
TOVn Interrupt Flag Set and
3
OCnA Interrupt Flag Set
4
or ICFn Interrupt Flag Set
5
(Interrupt on TOP)
Könnte also auch mit dem Capture Interrupt tun.
P.S.: Atmel hat neue Dokus gemacht, ohne Kapitelnummern. Daher kann es
sein, dass die "Figure" in den bisherigen Dokus auch anderst heißt.
Achim K. schrieb:> Eigentlich nutzt er ja Timer 1, da ist TIMER0_OVF_vect u.U. nicht> passend.
Autsch. Ist mir beim Kopieren gar nicht aufgefallen.
Dann natürlich so:
1
ISR(TIMER1_OVF_vect)
2
{
3
//PORTB ^= (1 << PB7);
4
flag=1;
5
}
> In der Doku steht auch bei Fast PWm Mode (Figure 46)>>
1
> OCRnx/TOP Update and
2
> TOVn Interrupt Flag Set and
3
> OCnA Interrupt Flag Set
4
> or ICFn Interrupt Flag Set
5
> (Interrupt on TOP)
6
>
>> Könnte also auch mit dem Capture Interrupt tun.
Mag sein. Aber 2 IRQs für dieselbe Sache sind irgendwie unsinnig. Beim
Overflow-Int stürzt der natürlich ohne ISR ab.
mfg.
Danke für die vielen Antworten!
Habe nun die "halbgaren" Programmteile vom Attiny2313 entfernt und es
funktioniert.
Sowohl der Capture Interrupt als auch der Overflow Interrupt des Timer1
führen zum Programmaufruf alle 20ms und die Variable in der while
Schleife wird raufgezählt =>ok.
@ Thomas Eckmann:
Dass der Capture Interrupt ein Fehlgriff ist, kann ich nicht
nachvollziehen. Mit welcher Umgebung hast du den Code getestet?
@all:
Welche Stolpersteine gibt es sonst noch auf die Schnelle, auf die ich
aufpassen sollte?
mfg
Alle Variablen, die in Interrupt Routinen geändert werden und im
Hauptprogram gelesen werden (oder auch umgekehrt) müssen volatile sein.
Das hast Du ja schon richtig gemacht.
> @all:> Welche Stolpersteine gibt es sonst noch auf die Schnelle, auf die ich> aufpassen sollte?
Ich nehme immer die Typen aus "<stdint.h>", dann weiß ich, wie viele
Bytes es sind. Außerdem nehme ich natürlich auch immer den kleinsten
Typ, in den die benötigten Werte passen. Also nicht
1
volatileintflag=0;
sondern
1
volatileint8_tflag=0;
Wenn man die 2 Byte Werte braucht und mit einem Interrupt teilt, dann
reicht "volatile" oft nicht aus, man muss "cli(); .... ; sei();" (oder
analoges) benutzen, sonst sieht man u.U. unerwartete "Geisterwerte". Das
gilt auch für 16 Bit I/O SFRs, wenn man die 16 Bit Register oder einen
Teil davon auch aus dem Interrupt nutzt. Und für "read and modify" gilt
dies natürlich auch.
Bei besonderen I/O Operationen mit "Zeitfenster" (z.B. Watchdog füttern,
System Clock Prescaler ändern) sollte man die entsprechenden Funktionen
verwenden. Wenn man es, aus welchem Grund auch immer, selber
programmieren möchte, muss man inline Assembler nehmen.
Da der CPU Core bei vielen Applikationen nur wartet, versuche ich
möglichst mit "sleep" etwas Energie zu sparen. Man muss natürlich die
Doku beachten, sonst schläft der Core vielleicht länger, als man
wollte :-).