Andy11 schrieb:
> ja aber wieviele Warte Schleifen muss ich denn jetz noch hingeben
Mut du ausrechnen :-)
> wie dumm ist das, gibt es da keine andere möglichkeit?
Doch natürlich.
Aber lass dir Zeit. Das lernst du schon noch
(Der Weg führt über Timer)
Mit welchem Takt betreibst du das STK500? Es kann sein, dass es für das
Auge schlichtweg zu schnell schaltet. Im AVR-Studio kannst du den Takt
des STK auf ein paar kHz absenken, dann könnte sich was andern.
Bei 3,7 MHz dauern 255 Takte etwa 0,06ms (1/3700000 * 255 = 6,9*10^-5 s)
Durch die Sprünge und so weiter wird die Schaltzeit noch etwas länger,
aber ich denke du bist einfach zu langsam das zu sehen ;-)
Ich hoffe ich habe mich nicht verrechnet (ich bin nich so doll in asm)
Hubert schrieb:
> Mit welchem Takt betreibst du das STK500? Es kann sein, dass es für das> Auge schlichtweg zu schnell schaltet. Im AVR-Studio kannst du den Takt> des STK auf ein paar kHz absenken, dann könnte sich was andern.
Nicht!
Das gibt Ärger beim ISP flashen.
Auch wenn du im Prinzip recht hast ... wenn er das tut jagst du ihn in
das nächste Problem rein.
Warten entweder über einen mindestens 24-bitigen Zähler oder über einen
der eingebauten Timer.
Was für einen Prozessortakt verwendest du?
Bei angenommenen 1 MHz (der langsamste intern) dauert deine Warteroutine
in etwa 256*3 + 256*3 Takte, als ungefähr 1500 us oder 1,5 ms.
Jetzt läuft dein Programm grad so:
Leds an
1,5 ms warten
Leds aus
1,5 ms warten
;;;;;;;
Du kannst dir z.B mit 3 Registern einen 24-bit-Delay bauen, der dann bis
zu 16 sec verzögert (bei 1 MHz)
;im r16 ist der wert in 16tel Sekunden
;benötigt werden zusätzlich r0 und r1
delay:
clr r0
clr r1
delay_loop:
dec r0
brne delay_loop
dec r1
brne delay_loop
dec r16
brne delay_loop
ret
;hier werden r16 256 256 Takte durchlaufen ;-)
Hi
>ja aber wieviele Warte Schleifen muss ich denn jetz noch hingeben>wie dumm ist das, gibt es da keine andere möglichkeit?
Für längere Warteschleifen mußt du die verschachteln:
1
clr r16
2
aaa: clr r17
3
bbb: dec r17
4
brne bbb
5
dec r16
6
brne aaa
Für längere Delays muss man u.U. eine dritte Schleife benutzen. Suche
mal im Netz nach 'avrdelayloop'. Damit kannst solche Delays generieren
lassen. Etwas fortgeschrittene Programmierer nehmen allerdings einen
Timer.
MfG Spess
Das Studio meckert doch wenn der Takt zu langsam ist - Aber so kann man
sich eine Vorstellung von der Schnelligkeit des AVR machen. Oder ISP
geschwindigkeit anpassen.
Flo schrieb:
> Malpunkte zwischen den letzten Zahlen -.-
Nimm die Leerzeichen raus, dann interpretiert die Fornesoftware das
nicht mehr als Fettdruck
r16*256*256
(ICh weiß, das ist lästig. Ich finds auch doof)
naja ok timer hört sich schon mal gut an, jedoch habe ich gedacht, dass
ein timer bis maximal 1 Register zählen kann und das wären ja dann wohl
wieder die 255
ich möcht jetzt aber auch nicht den Hardwaretimer dazu verwenden, in
Bascom muss ich das ja auch nicht
aber ich habe keine idee, wie ich so einen "timer realisieren könnte"
gibts da ein paar vorschläge?
Hubert schrieb:
> Das Studio meckert doch wenn der Takt zu langsam ist - Aber so kann man> sich eine Vorstellung von der Schnelligkeit des AVR machen. Oder ISP> geschwindigkeit anpassen.
Der ISP Takt darf max, 1/4 der µC Frequenz sein. Wenn er Pech hat, kann
er den µC danach über ISP überhaupt nicht mehr ansprechen, sondern muß
über High-Voltage Programming gehen. Hatten wir vor kurzen hier im
Forum. Ein Schlauberger hat die CPU Frequenz soweit runtergedreht, dass
es keine ISP Einstellung mehr gab, mit der er ihn hätte ansprechen
können :-)
Aber das STK wird doch über die Serielle Schnittstelle angesprochen. Hat
nix mit ISP zu tun. Und wenns nichtmehr geht den TAkt wieder hochdrehen
ohne ISP bis ISP wieder geht.
Andy11 schrieb:
> naja ok timer hört sich schon mal gut an, jedoch habe ich gedacht, dass> ein timer bis maximal 1 Register zählen kann und das wären ja dann wohl> wieder die 255
Der Sekundenzeiger deiner Uhr kann auch nur bis 59 zählen, und trotzdem
kannst du damit Minuten, Stunden, ja sogar Tage stoppen. Wie machst du
das?
> aber ich habe keine idee, wie ich so einen "timer realisieren könnte"> gibts da ein paar vorschläge?
Ganz ehrlich:
Auch wenn ich ein großer Verfechter von Timern bin: Du solltest
verstehen, warum deine kurze Schleife viel zu schnell abgearbeitet wird,
was du dagegen tun kannst und vor allen Dingen, wie du ausrechnen
kannst, wie lange ein bestimmtes Code Stück braucht.
Genau das ist nämlich einer der Vorteile von Assembler: Du hast
Kontrolle über jeden einzelnen Taktzyklus (na ja ... fast)
Hubert schrieb:
> Aber das STK wird doch über die Serielle Schnittstelle angesprochen.
Ach?
Wusste gar nicht das das STK den Chip über die serielle Schnittstelle
programmiert :-)
>>Ach?>>Wusste gar nicht das das STK den Chip über die serielle Schnittstelle>>programmiert :-)
Witzig, das hier Moderatoren so nen Mist schreiben. Ich habe nicht
gesagt das der Chip über die Sreielle Schnittstelle programmiert wird.
Das STK500 wird über den Comport angesprochen, ob da ein AVR im Sockel
steckt oder nicht.
Auch wenn ich ein großer Verfechter von Timern bin: Du solltest
3
verstehen, warum deine kurze Schleife viel zu schnell abgearbeitet wird,
4
was du dagegen tun kannst und vor allen Dingen, wie du ausrechnen
5
kannst, wie lange ein bestimmtes Code Stück braucht.
6
Genau das ist nämlich einer der Vorteile von Assembler: Du hast
7
Kontrolle über jeden einzelnen Taktzyklus (na ja ... fast)
ich habe wirklich schon viele aufgaben außerhalb assembler gemeistert,
ich weiß aber echt nich wie ich das mach, mir fehlt einfach der
Denkansatz
geht jetz der TImer über den alle hier sprechen ganz anders vom coding
her, oder besteht da ein ähnlichkeit?
ein Timer ist ein nebenläufiger Zähler, der über einen Prescaler
(Vorteiler) mit einem geringeren Takt versotgt werden kann als der
Prozessor läuft. Bei bestimmten Ereignissen wie einem Zählwertüberlauf
(Overflow) oder einem erfolgreichen Vergleich mit einem anderen Wert
(Compare-Match) kann ein Interrupt ausgelöst werden, also eine
Programmunterbrechung.
In dieser Unterbrechung kannst du dann z.B. peridische Dinge tun, wie
eine Zeitvariable hochzählen und ähnliches. Danach wird das
Hauptprogramm fortgesetzt.
Einfach mal im Tutorial unter Timer schauen, oder im Datenblatt ein
bisschen Schmökern. ;-)
Andy11 schrieb:
> ich habe wirklich schon viele aufgaben außerhalb assembler gemeistert,> ich weiß aber echt nich wie ich das mach, mir fehlt einfach der> Denkansatz
Es ist ganz einfach.
Überschlagsmässig kannst du davon ausgehen, dass jeder Befehl im AVR
einen Taktzyklus braucht. Branch Befehle brauchen 2 Takte, wenn die
Bedinung zutrifft
1
Zwischen:
2
ldi r16, 255
3
4
Warte:
5
dec r16 1 Takt
6
cpi r16, 0 1 Takt
7
brne Warte 2 Takt
Das heist: Ein Durchlauf durch die Schleife dauert 4 Takte. Durch r16
machst du 255 Durchläufe durch die Schleife. Macht 255 mal 4 = 1020
Takte.
Agenommen dein µC läuft mit 1Mhz. WIe lange dauert das dann?
Nun 1Mhz heist, dein µC hat in 1 Sekunde 1 Million Takte zur Verfügung.
Du brauchst nur 1020. Diese 1020 Takte dauern daher
1 Mio 1 Sekunde
1020 x
-----------------------------
1020 * 1
x = ---------- = 0.00102 Sekunden
1000000
Solange dauert es daher, bis dein µC die Schleife 255 mal abgearbeitet
hat. (Bei einer Taktfrequenz von 1Mhz)
Andy11 schrieb:
> in Bascom sag ich aber auch nur
Du musst dich jetzt entscheiden:
Soll dir BASCOM in Zukunft weiterhin alles abnehmen oder willst du
selber für deine Verfehlungen verantwortlich sein und endlich mal deinem
µC auf die Beinchen schauen, was der so treibt :-)
Man kann beides tun. So wie man Auto fahren kann, ohne sich um die
Details des Motors kümmern zu müssen. Aber Autoschrauber wird man nur
dann, wenn man einen Lötkolben am richtigen Ende anfassen kann und einen
eine defekte Batterie nicht sofort die Schweißperlen auf die Stirn
treibt weil man nicht weiß wo man die suchen muss ... und was zum Teufel
macht die Batterie in meinem Auto und wie sieht die eigentlich aus.
Oder glaubst du, dass BASCOM was anderes macht um 1 Sekunde zu warten
:-)
Andy11 schrieb:
> ist mir schon klar, es ging mir nur darum es auch vernünftig> anzuschreiben in assembler
Wo liegt jetzt das Problem?
Du willst vielleicht eine Verzögerung von insgesamt 0.2 Sekunden.
0.00102 Sekunden hast du schon. Wenn du daher diese Konstruktion
0.2 / 0.00102 = 196
mal ausführst, hast du die 0.2 Sekunden
1
Zwischen:
2
3
ldi r17, 196
4
5
Warte1:
6
ldi r16, 255
7
8
Warte:
9
dec r16
10
cpi r16, 0
11
brne Warte
12
13
dec r17
14
cpi r17, 0
15
brne Warte1
OK. stimmt nicht ganz genau, weil natürlich die Bearbeitung von r17 auch
seine Zeit braucht.
Du brauchst noch längere Zeiten?
Nun du hast noch r18, r19, r20 ..... und du kannst noch genügend viele
Schleifen immer weiter drumherum bauen.
Wenn man 60 mal 1 Sekunde wartet, hat man in Summe auch 1 Minute
gewartet :-) Will man 1 Stunde warten, dann wartet man eben 60 Minuten,
wobei jede einzelne der Warteminuten dadurch entsteht, dass man 60 mal 1
Sekunde wartet.
Eigentlich ganz einfach und stellt dich im realen Leben vor keinerlei
Probleme.
BASCOM macht letzten Endes auch nichts anderes. Nur rechnet sich BASCOM
eben still und heimlich aus, wie oft welche Teile wiederholt werden
müssen, damit 1 Sekunde Wartezeit entsteht. Jetzt weißt du wie's gemacht
wird. Vorher hast du dich nicht darum gekümmert :-)
Andy11 schrieb:
> aber hier habe ich auch 2* (255*4) Taktzyklen und das müsste dann> 2040/1Mio = 2ms
Moment.
Bis jetzt war alles mehr oder weniger hypothetisch, weil du bisher deine
Taktrequenz nicht bekant gegeben hast.
Und ausserdem wird der innerste Teil nicht 2*255 mal abgearbeitet,
sondern 255*255 mal:
Das letzte Codestück zählt r16 von 255 bis 0 runter. Und das r17=255 mal
> lang sein und trotzdem ist der Unterschied deutlich zu> erkennen
Welcher Unterschied?
>Und ausserdem wird der innerste Teil nicht 2*255 mal abgearbeitet,>sondern 255*255 mal
was wieso jetz=?
ok das hier
//
dec r16
cpi r16, 0
brne Warte
//
kommt zwar beim 2ten Teil auch immer wieder vor aber das sind trotzdem
nicht 255²
>Welcher Unterschied?
das Blinken
Andy11 schrieb:
> kommt zwar beim 2ten Teil
welchen 2ten Teil. Die Schleifen sind jetzt ineinander geschachtelt!
Du hast den Code hier
1
Zwischen:
2
ldi r16, 255
3
ldi r17, 255
4
5
Warte:
6
dec r16
7
cpi r16, 0
8
brne Warte
9
10
dec r17
11
cpi r17, 0
12
brne Warte
13
ret
Ich markiere dir mal die Schleifen und rücke etwas ein
1
Zwischen:
2
ldi r16, 255
3
ldi r17, 255
4
5
Warte: ; <---+<--+
6
dec r16 ; | |
7
cpi r16, 0 ; | |
8
brne Warte ; ----+ |
9
|
10
dec r17 ; |
11
cpi r17, 0 ; |
12
brne Warte ; --------+
wenn r17 um 1 runtergezählt wurde und noch nicht bei 0 angelangt ist,
beginnt r16 erneut von 255 bis wieder 0 runterzuzählen. Daraufhin wird
r17 wieder um 1 erniedrigt und r16 macht wieder seinen 255-er Drchlauf
usw. usw. In Summe wird alse r16 insgesammt 255 mal (durch r17) von 255
auf 0 runtergezählt. 256*256
> beginnt r16 erneut von 255 bis wieder 0 runterzuzählen
aber wieso?? der Registerinhalt ist doch schon 0, würde der jetzt weiter
runterzählen ist die Zahl dann negativ
ich sag ja dem register nicht, dass sein wert wieder 255 ist, oder macht
er das automatisch wenn er 0 ist, dass er dann sozusagen bei
über/unterlauf wieder auf der anderen seite beginnt zu zählen--> sprich:
wenn der zähler nicht weiter kann, geht er in den AUsgangszustand
Hallo,
Zur Frage: wenn ich ein Register, das Null ist, dekrementiere, gibt es
einen Unterlauf, und der Wert im Register ist danach 255.
Und noch so am Rande: bei dem Code
>Warte:> dec r16>> cpi r16, 0> brne Warte>> dec r17>> cpi r17, 0> brne Warte>ret
kann man sich die Zeile "cpi ... , 0" sparen, da das "dec" das Zero-Flag
bei Null setzt und daher direkt der Branch ("brne") folgen kann.
Andy11 schrieb:
>> beginnt r16 erneut von 255 bis wieder 0 runterzuzählen>> aber wieso?? der Registerinhalt ist doch schon 0, würde der jetzt weiter> runterzählen ist die Zahl dann negativ
der kann nicht negativ werden. Auf dieser Ebene gibt es so erst mal kein
Vorzeichen. Nach 0 kommt wieder 255.
> ich sag ja dem register nicht, dass sein wert wieder 255 ist
nein.
aber wenn r16 0 ist und du machst einen dec drauf, dann ist r16 danach
255
Genauso umgekehrt 255 + 1 -> 0
so schlecht war das mit der Uhr da weiter oben gar nicht :-) Nach 59
kommt 0. Das geht immer so rundum.
Hi
>aber wieso?? der Registerinhalt ist doch schon 0, würde der jetzt weiter>runterzählen ist die Zahl dann negativ.
Nein. du fängst wieder mit $FF an.
MfG Spess