Ein kleiner Nachtrag zu Timer1
es muß natürlich heißen
.equ time = 65536 -10000
:oops:
Druckbare Version
Ein kleiner Nachtrag zu Timer1
es muß natürlich heißen
.equ time = 65536 -10000
:oops:
Juhu meine LED blinkt! Mann ist das geil :D :D
Jetzt versuch ich mal das ganze zu verstehen!
Gruß Michi
Da der Michi, das Problem mit Stack angesprochen hat, von wegen ohne seine
Initialisierung wollte ich hier auch mal dazu sagen.
Klar geht es ohne, aber sobald man die Befehle rcall, pop und push benutzt (hat schon Florian angesprochen) gibt es Probleme.
Genauso mit Interrupts, dabei wird auf dem Stack die Rücksprung Adresse abgelegt.
Und wenn wir nicht deklarieren, wo das ende von Sram liegt, bleiben die SPL und SPH adressen leer, also 0x00.
Was passiert dann, wenn man ungewollt(z.B. ein Interrupt) irgendwas auf dem Stack ablegt?
Sram von Adresse 0x00 bis 0x60(Mega8) ist für alle Register R0-R31 und alle anderen Register reserviert (sehe Dattenblatt Seite 16) damit überschreiben wir uns den Inhalt von R0 . Da der Stack aber rückwärts geht also von hinten nach vorne, wird er mit sbiw vom µC
um 1 verringert und wo landen wir wenn 0x000 -1 gerechnet wird?
Ich hoffe, daß hier auch ein Schlaumeier ist, der diese Ausführung bestätigen könnte.
Gruß Sebastian
Hallo hab jetzt ne Frage:
Warum wird TCNT0 mit 255-254 geladen? 255-254 gibt doch 1!?
Gruß Michi
Ich seh gerade das Tutorial ist bei der Statistik auf Rang 2 gestiegen!
[schild=13 fontcolor=000000 shadowcolor=C0C0C0 shieldshadow=1]Glückwunsch[/schild]
an alle die hier so kräftig helfen!
Gruß Michi
Wir hatten doch hier im Thread eine Formel:Zitat:
Zitat von michaelb
1/ 3,6864 Mhz = 271ns
271ns * 1024 (prescaler) = 278µs
278µs * 90 (ausprobierter Wert) = 25ms
Wir wollen ja 1 Sekunde, erreichen, deswegen suche ich einen Wert, der gut mit einer Zahl multipliziert werden kann, sodass dann 1 Sekunde = 1000ms rauskommt.
25ms * 40 = 1 Sekunde oder 1000ms
Also muss du deinen Timer mit 256-90 vorladen (warum 256? --> ein paar Post wurde das nochmal erklärt)
und diesen Timer musst du dann 40x überlaufen lassen, dann hast du 1 Sekunde erreicht.
Gruß
Thomas
Das stimmt auch nicht *glaub*Zitat:
Zitat von izaseba
Denn dann ist es viel länger als 1 Sekunde. Meiner Meinung nach müsste es
.equ time = 65536-1000
heißen, aber dann ist es viel schneller als 1 Sekunde. Ein Teufelskreis ;)
Ich versuch da mal ne Formel zu bekommen.
Hier mal der Code mit Timer1:
Soweit funktioniert er ja. Aber wie man genau die Zeit festlegt ist noch ein Problem.Code:;Programm
;CDurTonleiter rauf und runter spielen
.include "m8def.inc"
.def tmp = r16 ;Mein Universallregister
.def helpSek = r17
.def tonwert = r19 ;aktueller Wert für den Ton
.def lpm_reg = r0 ;Mein lpm-Register
.equ Summer = PB2 ;Summer an B.2
.equ time0 = 256-255 ;Timer0 für die Tonleiter
.equ time1 = 65536-1000 ;Damit wird der Timer1 vorgeladen, für die Sekunde
.equ daten_laenge = 9 ;Anzahl der Werte
.org 0x000
rjmp reset ;Interruptvektor "reset:"
.org OVF1addr
rjmp pruefSek ;Interruptvektor "pruefSek:"
.org OVF0addr
rjmp timerSummer ;Interruptvektor "timerSummer:"
reset:
;Stack einrichten
ldi tmp, HIGH(RAMEND) ;HIGH-Byte der obersten RAM-Adresse
out SPH, tmp
ldi tmp, LOW(RAMEND) ;Low-Byte der obersten RAM-Adresse
out SPL, tmp
;Timer Register für Ton werden belegt, hier Timer 0
ldi tmp, (1<<CS02) ;Prescaler ist 256
out TCCR0, tmp ;Register TCCR0 ist für den Prescaller zuständig
ldi tmp, time0 ;Hier wird der Timer vorgeladen
out TCNT0, tmp
;Timer Register für Sekunde werden belegt, hier Timer 1
ldi tmp, (1<<CS12) | (1<<CS10) ;Prescaler ist 1024
out TCCR1B, tmp
ldi tmp, HIGH(time1) ;Für den Timer1 (16Bit) benötigen
out TCNT1H, tmp ;wir 2 Register, in denen wir den Wert
ldi tmp, LOW(time1) ;für die 1 Sekunde (10000) speichern ->
out TCNT1L, tmp ;"TCNT1H" und TCNT2L"
ldi tmp, (1<<TOIE0) | (1<<TOIE1);Hier werden Interrupts nach Timer0 Überlauf eingeschaltet
out TIMSK, tmp ;Register TIMSK ist dafür zuständig
;Z-Register mit DB "tonleiter1" füllen
ldi ZH, HIGH(tonleiter1 * 2)
ldi ZL, LOW(tonleiter1 * 2)
sbi DDRB, Summer ;B.2 als Ausgang
sbi PORTB, Summer ;B.2 auf HIGH stellen
sei ;Interrupts zulassen
;Hier wird der nächste Ton geladen und in "tonwert" gespeichert
;Z-Zeiger wird um 1 erhöht, damit er beim nächsten mal den nächsten
;Ton lädt. Es wird hier auch verglichen,, ob der letzte Ton erreicht,
;wenn ja, dann springt er zu "endeTon"
tonLaden:
clr helpSek ;helpSek auf 0 setzen
lpm ;Daten von tonleiter1: holen
mov tonwert, lpm_reg ;erstes Byte in tmp verschieben
adiw ZL,1 ;Z um 1 erhöhen, nächstes Byte
ldi tmp, LOW ((tonleiter1 * 2) + daten_laenge) ;vergleiche LOW-Byte
cp ZL, tmp
ldi tmp, HIGH ((tonleiter1 * 2) + daten_laenge) ;vergleiche HIGH-Byte
cpc ZH, tmp
breq endeTon ;springe zu "endeTon:", wenn letztes Byte ausgelesen
rjmp main ;sonst springe zu "main:"
;Hier wird der Timer gestoppt, indem wir den Prescaler auf 0 setzen
endeTon:
ldi tmp, (0<<CS02) ;Timer stoppen
out TCCR0, tmp
;Die Hauptschleife, die sich immer wiederholt
main:
cpi helpSek, 0b11111111 ;Ist helpSek auf 255? (also 1 Sekunde um?)
breq tonLaden ;dann lade den nächsten Ton
rjmp main ;immer wieder zurück zu main springen
;Läuft Timer2 über, so wieder zaehlerSek um 1 erhöht und
;Timer2 neu vorgeladen
pruefSek:
push tmp ;tmp sichern
in tmp, SREG
push tmp ;SREG sichern
ldi helpSek, 0b11111111 ;Hilfsvariable mit 255 belegen
ldi tmp, HIGH(time1) ;Für den Timer1 (16Bit) benötigen
out TCNT1H, tmp ;wir 2 Register, in denen wir den Wert
ldi tmp, LOW(time1) ;für die 1 Sekunde (10000) speichern ->
out TCNT1L, tmp ;"TCNT1H" und TCNT2L"
pop tmp
out SREG, tmp ;SREG wiederholen
pop tmp ;tmp wiederholen
reti ;Spring wieder dahin, wo du hergekommen bist
;Läuft Timer0 über, so wird B.2 umgeschaltet, sodass Ton
;aus dem Summer zu hören ist
timerSummer:
push tmp ;tmp sichern
in tmp, SREG
push tmp ;SREG sichern
sbis PINB, Summer ;ist B.2 = 1?
rjmp timerSummer1 ;NEIN -> spring zu timerSummer1:"
cbi PORTB, Summer ;JA -> setze B.2 auf 0
rjmp timerSummer2 ;zu "timerSummer2:" springen
timerSummer1:
sbi PORTB, Summer ;wenn B.2 = 0 ist, dann auf 1 setzen
;Hier wird Timer0 mit dem aktuellen Tonwert vorgeladen
timerSummer2:
out TCNT0, tonwert ;Timer dementsprechen vorladen
timerSummer3:
pop tmp ;SREG wiederholen
out SREG, tmp
pop tmp ;tmp wiederholen
reti
;Das sind die Werte, womit der Timer0 (Tonleiter-Timer) vorgeladen wird
tonleiter1:
.db 256-55, 256-49, 256-44, 256-41 ;Wert zum Vorladen für den Timer
.db 256-37, 256-33, 256-29, 256-27, 0 ;für die Tonleiter
Achja...die Hilfsvariable brauchte ich, um festzustellen, ob schon eine Sekunde um ist, wusste sonst nicht, wie ich das ohne hätte lösen sollen.
Hallo,
also kann mann statt 255-254 einfach 1 schreiben, oder?
Oder was bringen die schreibweisen mit 256-90 oder 255-254?
Gruß Michi
Klar stimmt das nicht, war nur als Beispiel ! :-)Zitat:
Das stimmt auch nicht *glaub*
Vergiss einfach die 255, schreib immer 256 (Erklärun wie gesagt weiter oben).
Und ja, anstelle von 256-255 könnte man auch 1 schreiben. Aber ich denke, dass 256-255 die bessere Schreibweise, denn dann sieht man gleich, mit wieviel Bit man arbeitet.
Gruß
Thomas