Guten Abend
Bei folgendem Codeschnipsel versuche ich mich bereits seit ein paar
Stündchen, die Formel zur berechnung der Laufzeit zu bestimmen:
1
; Zeile
2
warte: ; 1
3
warte_500ms: ; 2
4
ldi counter0, CNT0 ; 1T 3
5
ldi counter1, CNT1 ; 1T 4
6
ldi counter2, CNT2 ; 1T 5
7
8
cnt: ;7
9
dec counter0 ; 1T 8
10
brne cnt ; 2T .. bei counter = 0 1T (einmal) 9
11
12
ldi counter0, CNT0 ; 1T 11
13
dec counter1 ; 1T 12
14
brne cnt ; 2T .. bei counter = 0 1T (einmal) 13
15
16
ldi counter1, CNT1 ; 1T 14
17
dec counter2 ; 1T 15
18
brne cnt ; 2T .. bei counter = 0 1T (einmal) 16
19
ret ; 3T 17
Gut, zeile 2, 3, 4 und 16 brauchen zusammen 6 Takte und werden nur
einmal durchlaufen.
Zeile 7 bis Zeile 9 benötigt, wenn Bedingung falsch ist immer 3 Takte.
Mit berücksichtigung von der Schleife mit Anzahl CNT0 Durchläufen komme
ich auf
c0 = 3*(CNT0-1)
DIe zweite schleife, gilt von Zeile 7 bis Zeile 13, sodass gilt:
c1 = (c0+4)*(CNT1-1)
Mit der dritten und letzten also Obersten Schleife, welche von zeile 7
bis 16 werkelt kommt man auf:
Takte = (c1+4)*(cnt2-1)
mit einsetzen der zeitkonstenten:
Takte = ((3*(CNT0-1)+4)*(CNT1-1)+4)*(cnt2-1)
ich kann also durch probieren mit ganzahligen werten ein möglichst
glattes Ergebnis für z.b. cnt2 erzielen um 500ms zu warten.
Ist die Ermittlung zur Laufzeit der Funktion so richtig wie ich es
gemacht habe ?
Ich nutze den ATmega8 mit internen RC-Oszillator mit einem MHz; die
interne Taktquelle ist nicht gerade die geneueste, lohnt es sich
eigentlich so einen aufwand zu betreiben?
Und wie schnell schalten denn die Ausgänge ?
mfg
:-) :-) :-) :-) wrote:
> Ein paar Stuendchen ? ... Der simulator laesst genau zaehlen.
Liefert aber keine Formel in Abhängigkeit der drei 8-Bit Werte CNTx,
bzw. des 24-Bit Wertes, der sich daraus ergibt ;-)
>Ich nutze den ATmega8 mit internen RC-Oszillator mit einem MHz; die>interne Taktquelle ist nicht gerade die geneueste, lohnt es sich>eigentlich so einen aufwand zu betreiben?
Nein!
>Und wie schnell schalten denn die Ausgänge?
1 Takt.
Mach das mit einem Timer und gut ist's!
Das geht aber schnell bei euch :)
Ist dieser Zähler etwas besser, ich meine zählt er Hardwaremäßig oder
ist der Atmel die gesamtezeit nur mit dieser funktion beschäftigt.
1
warte_500ms_b:
2
push r24
3
push r25
4
5
clr r24
6
clr r25
7
8
ldi akku, 3
9
10
cntb:
11
sbiw r24, 1
12
brne cntb
13
dec akku
14
brne cntb
15
16
pop r25
17
pop r24
18
ret
:-) :-) :-) :-) wrote:
> Ein paar Stuendchen ? ... Der simulator laesst genau zaehlen.
Nun also ich bin der Meinung man sollte einfach alles mal ausbrobiert
haben. Der Simulator ist ja ne tolle Sache aber ich traue ihm nicht :)
Real auf dem oszi schaut alles etwas anders aus als es der simulator mir
sagt :)
Falls man sich die Mühe doch machen will, weil zB kein Timer frei ist:
Was du willst ist wohl nicht, für den Codeschnippsel die Anzahl der
Ticks zu berechnen, die er braucht, sondern umgekehrt: Du willst ne
bestimmte Anzahl Ticks vertrödeln, und suchst Code der das tut.
Anbei ist ist ein Header für avr-gcc, der genau das macht: Beim Aufruf
von exact_delay(1000) werden genau 1000 Ticks verbraten, beim Aufruf von
exact_delay(1) genau einer, etc.
Das ganze ist eigentlich nur ein Assembler-Makro. Falls du in Assembler
programmierst, kannst das direkt da keinkopieren...allerdings nur mit
der Macht des GNU-Assemblers ;-)
In C sieht's so aus:
René K_punkt wrote:
> Ist dieser Zähler etwas besser, ich meine zählt er Hardwaremäßig oder> ist der Atmel die gesamtezeit nur mit dieser funktion beschäftigt.
Er ist nicht etwas besser, er ist viel besser.
Er zählt parallel zu deinem Programm, bremst also nix aus. Er kann
Interrupts auslösen in dem du zB eine Zählvariable erhöhen oder Flags
setzen kannst.
Johann
Vielen Dank Johann und spess53 :)
Kann man diesen Hardwarezähler auch beliebig erweitern, z.b. wenn 16 bit
(r24 und r25) nicht ausreichen ?
oder kann ich dies nur durch kaskadierung mit weiteren registern wie
r26, r27 erreichen erreichen ?
was passiert wenn r24:r25 zählt und zeitgleich r26,r27 mit zählen durch
sbiw r26,1 beginnt ?
ich meine ist nur ein zähler als hardware im atmel implementiert ?
und dieser zähler hat auch "nur" 16 bit ?
mfg
spess53 wrote:
> Im Web gibt es einen 'AVR Delay Loop Generator'. Gurgel hilft.
hmmm... wozu kompliziert, wenn's auch einfach geht?
Der Assembler kann doch alles, was man braucht.
So muss man sich weder irgendeine Executable aufm Rechner installieren
noch ständig Code hin- und her zu kopieren und immer wieder Werte
eintippsen.
Größen wie F_CPU etc. lässt man vom Präprozessor verdauen, und der kann
auch meckern wenn Werte nicht passen oder ne Schleife aufgrund ner
Division, die nicht genau aufgeht, ungenau wird -- wenn man sowas haben
will.
Wer braucht dafür nen extra Loop Generator??? Am besten noch in Excel...
Johann
René K_punkt wrote:
> ich meine ist nur ein zähler als hardware im atmel implementiert ?> und dieser zähler hat auch "nur" 16 bit ?
Alle Zähler, die hier vorgestellt wurden, sind rein in Software und
realisieren eine Verzögerung über Rungammeln in einer Warteschleife.
Hardware-Zähler operieren auf eigenen Spezial-Registern (SFRs), über die
sie auch konfiguriert werden. Sie haben mit den normalen µC-Registern
wie R25 nix zu tun.
Schnapp dir am besten mal ein AVR-Handbuch oder wag einen Blick ins
Tutorial, um ne Vorstellung zu bekommen, was ein Hardware-Zähler
überhaupt ist.
Johann
Hi
>ich meine ist nur ein zähler als hardware im atmel implementiert ?>und dieser zähler hat auch "nur" 16 bit
Die Ausstattung mit Timern hängt vom kongreten AVR ab. Ausserdem kann
man einen Timer auch für verschiedene Funktionen benutzen. Z.B. du
konfigurierst einen Timer so, das er alle 10ms einen Interrupt auslöst.
In der Interruptroutine zählst du eine 'Speichestelle' herunter. Wenn du
die z.B. am Anfang mit 100 lädst ist beim Stand 0, 1s vergangen. Das
kann man dann auswerten. Wenn du in dem Interrupt 2 'Speicherzellen'
zählst, kannst du mit einem Timer auch zwei verschiedene Zeiten
erzeugen.
MfG Spess