Hallöchen, ich versuche mir grad ein Gerät zu basteln welches Klarträume
induzieren soll d.h. nach ca. 4-5 Stunden für eine kurze weile LED's zum
Blinken bringen soll. Dafür muss ich nun also lange Timer durch
kaskadierung von Registern hinbekommen. Da ich aber schwer jedes mal so
lange warten kann (bzw. auch mit kürzer Eingestellter Zeit finde ich den
Fehler nicht) bleibt mir nichts anderes übrig als hier zu fragen. Das
ganze läuft auf einem Attiny15 mit 1,6 MHz.
Hi, danke für die Antwort! Könntest du etwas genauer erklären wie du das
mit der Flag meinst weil ich nicht verstehe wie ich damit auf so einen
hohen wert komme.
Martin Z. schrieb:
> Hi, danke für die Antwort! Könntest du etwas genauer erklären wie du das> mit der Flag meinst weil ich nicht verstehe wie ich damit auf so einen> hohen wert komme.
Gar nicht.
Die Flagge (einfach ein Register) zeigt nur an, dass die Zeit abgelaufen
ist.
Am Anfang wird die Flagge (=such dir ein Register dafür aus) auf 0
gesetzt.
Wenn 60 mal 1 Sekunde abgelaufen ist, ist 1 Minute vergangen
Sind 60 Minuten vergangen, dann ist 1 Stunde vergangen.
Sind bsp. 4 Stunden vergangen, dann setzt du ein spezielles Register (=
die Flagge) auf 1
Das Hochzählen der Sekunden, Minuten, Stunden und entscheiden ob die
Flagge auf 1 gesetzt werden muss, kann alles in der Interrupt Routine
passieren.
In der Hauptschleife wartest du nur noch darauf, dass dieses Register 1
wird. Da dies, so wie die Interrupt Routine aufgebaut ist, erst nach 4
Stunden passieren wird, hat deine Hauptschleife effektiv 4 Stunden
gewartet.
Das sieht ja höllisch kompliziert aus, warum benutzt Du nicht die
Möglichkeit, Bytes zu kaskadieren?
Der AVR kann ganz einfach 32 Bit (und mehr) Increment und Test auf 0:
@Peter
Ich kenne mich zwar mit AVR-Asm nicht aus, aber
wenn in deinem Beispiel z.B. R16, R17, byte1 <> 0 sind,
R18,R19,byte2..byte4 aber =0, dann
setzt sbci r19, byte4(1) das Zero-flag und der anschliessende Zero-Test
verzweigt fälschlicherweise nach Timer_abgelaufen.
Oder sehe ich das falsch ?
APW schrieb:
> Ich kenne mich zwar mit AVR-Asm nicht aus, aber> wenn in deinem Beispiel z.B. R16, R17, byte1 <> 0 sind,> R18,R19,byte2..byte4 aber =0, dann> setzt sbci r19, byte4(1) das Zero-flag und der anschliessende Zero-Test> verzweigt fälschlicherweise nach Timer_abgelaufen.> Oder sehe ich das falsch ?
Ja.
Das Zero-Flag wird mit dem vorherigen verundet.
Nennt sich "zero-flag propagation".
Peter
Vielen Dank für die Antworten. In Asm bin ich leider nicht so bewandert
und C für den Tiny15 "einzurichten" ist mir für so ein Mini-Projekt zu
aufwendig. Ausserdem lern ich so ja was.
@Peter: ret geht mit dem Tiny15 leider nicht aber das ist nicht das
Problem. Ich versteh nicht ganz was du in deinem Code machst. du zählst
ja quasi runter wenn ich das richtig seh aber was bedeutet byteN(1) ?
Martin Z. schrieb:
> ret geht mit dem Tiny15 leider nicht
Klar geht das.
> Ich versteh nicht ganz was du in deinem Code machst. du zählst> ja quasi runter wenn ich das richtig seh aber was bedeutet byteN(1) ?
Das sind die jeweiligen Bytes, wenn man die 1 als 32-Bit-Wert (also 4
Bytes) interpretiert. Er hätte auch beim subi direkt 1 und bei den sbci
jeweils 0 schreiben können.
Achso ich dachte das Byte steht für irgendwas. also man zieht einfach
nur 1 ab und gibt das carry weiter. Jetzt hab ichs verstanden, DANKE :-)
!
wegen ret: Als ich es mit dem AVR Simulator auspropiert hab hatte ich
einen Stack underflow. Es will glaube ich nur mit rcall funktionieren
und nicht mit branches (weil bei branches nichts in den Z-Pointer
schreiben glaub ich) aber wissen tu ich das nicht :-[ . Aber du merkst
ja viel glauben und nichts wissen (klappt bei den Christen aber auch
irgendwie)
Martin Z. schrieb:
> wegen ret: Als ich es mit dem AVR Simulator auspropiert hab hatte ich> einen Stack underflow. Es will glaube ich nur mit rcall funktionieren> und nicht mit branches (weil bei branches nichts in den Z-Pointer> schreiben glaub ich) aber wissen tu ich das nicht :-[
Natürlich geht es nicht mit Branches, die haben mit ret rein gar
nichts zu tun. Branches sind "Sprünge" keine "Aufrufe".
(und mit dem Z-Pointer hat das Ganze auch nichts zu tun)
Also der Code funktioniert soweit recht gut. Allerdings hab ich das
Problem das die Zeit extrem ungenau ist. Wenn ich z.B. bei 1600000Hz den
Timer mit dem Prescaler 1024 betreibe hab ich eine Zählfrequenz von
1600000/1024/256 = 6,1 Hz. Das heißt wenn ich als Zählvariable 265 nehme
komme ich auf eine Zeit von ~41 Sekunden bis das Blinken losgeht. Ich
kriege allerdings eine Zeit von 60 Sekunden wenn ich stoppe. Kann das
interne Quarz wirklich SO ungenau sein oder könnte der Fehler woanders
liegen?
Der gekürzte Code:
Es gibt keinen "internen Quarz" nur einen "internen RC-Oszillator". Der
ist leider ungenau.
Man kann ihn kalibrieren, aber für Laufzeiten von mehreren Stunden
müsste man öfter kalibrieren. Also am besten einen Quarz verwenden bzw.
Quarzoszillator. Wie genau muss es denn effektiv sein?
Ich kalibrier den Controller jetzt mit dem Wert den ich mit dem STK500
ausgelesen hab. Ist zwar immernoch ein bisschen ungenau aber immerhin
sind es keine 50% mehr :D
vorher hatte ich bei einer 40 Sekunden Zählungen in echt 60 Sekunden
jetzt sind es 42(vielleicht ist das die Antwort?) oder 43. Wenn ich
jetzt noch an dem Kalibrierungswert feile ist es ausreichend genug.
Danke für die Hilfe!