Assembler Zeitverzögerung

Persönliche Seite #4791529
Lesenswert?

Pascal schrieb:
> Den Befehl Wait gibt es aber laut doc0856 von Atmel nicht...

Du hättest bei Deiner Frage schon erwähnen müssen, um welchen 
Controller/Prozessor es geht, denn Assembler != Assembler != Assembler.

Was auf einem AVR hü heißt, heißt auf einem ARM hott und auf einem 8051 
brr, und ein STM8 ist schon längst durchgegangen, während für einen 78k 
noch die Scheuklappen 'rausgesucht werden müssen.
#4791574
Lesenswert?

eine Schleiphe, Pseudocode:
Delay:                   ;Einsprungpunkt 'von Aussen'
Lade Reg1, Verzögerung   ;Anzahl der Durchläufe
Label1:
dec Reg1                 ; Schleiphenzähler runterzählen
jnz Label1               ; Wenn Zähler != 0 nächste Runde!
ret                      ; Rücksprung zum MainPrg.

Das kannst Du als Prozedur schreiben, oder als Macro, soll die 
Verzögerung länger sein verschachtelst Du zwei Schleiphen
Gast #4791672
Lesenswert?

EINEN Befehl gibt es bei den meisten µCs nur für das
Nichtstun über eine Befehlszykluszeit.
Der Name ist meist NOP (No OPeration)

Wenn es um mehr, als einige µs geht - und das Programm auch
noch mehr erledigen soll, ist es fast immer günstiger,
dafür einen Timer zu bemühen.

Variante 1:
Einen Timer darauf konfigurieren, dass er regelmäßig das
Programm jede ms o.ä. unterbricht (Interrupt). In der
Interruptroutine wird eine Variable, die man vorher auf die
gewünschte Verögerung in ms gesetzt hat, (falls sie nicht
schon NULL ist,) heruntergezählt und beim Erreichen von NULL
die LED ausgeschaltet, oder was da sonst gemacht werden soll...

Variante 2:
Einen Timer so konfigurieren, dass er nach x µs einen
Interrupt auslöst. In der Interruptroutine sperrt man die
folgenden Interrupts und schaltet die LED ....
#4791826
Lesenswert?

1
wait7516192768clk:      rcall wait3758096384clk
2
wait3758096384clk:      rcall wait1879048192clk
3
wait1879048192clk:      rcall wait939524096clk
4
wait939524096clk:       rcall wait469762048clk
5
wait469762048clk:       rcall wait234881024clk
6
wait234881024clk:       rcall wait117440512clk
7
wait117440512clk:       rcall wait58720256clk
8
wait58720256clk:        rcall wait29360128clk
9
wait29360128clk:        rcall wait14680064clk
10
wait14680064clk:        rcall wait7340032clk
11
wait7340032clk:         rcall wait3670016clk
12
wait3670016clk:         rcall wait1835008clk
13
wait1835008clk:         rcall wait917504clk
14
wait917504clk:          rcall wait458752clk
15
wait458752clk:          rcall wait229376clk
16
wait229376clk:          rcall wait114688clk
17
wait114688clk:          rcall wait57344clk
18
wait57344clk:           rcall wait28672clk
19
wait28672clk:           rcall wait14336clk
20
wait14336clk:           rcall wait7168clk
21
wait7168clk:            rcall wait3584clk
22
wait3584clk:            rcall wait1792clk
23
wait1792clk:            rcall wait896clk
24
wait896clk:             rcall wait448clk
25
wait448clk:             rcall wait224clk
26
wait224clk:             rcall wait112clk
27
wait112clk:             rcall wait56clk
28
wait56clk:              rcall wait28clk
29
wait28clk:              rcall wait14clk
30
wait14clk:              rcall wait7clk
31
wait7clk:               ret

Zyklen gelten für Einsprung mit RCALL bei AVR mit 16-Bit Programmzähler


Gruß

Jobst
Gast #4791977
Lesenswert?

Jacko schrieb:
> Nichtstun über eine Befehlszykluszeit.
> Der Name ist meist NOP (No OPeration)

Wenn man 2 Zyklen warten will, geht auch
goto $+1

oder

D8 nop ; Zyklen 8 warten
D8 nop ; Zyklen 7 warten
D8 nop ; Zyklen 6 warten
D8 nop ; Zyklen 5 warten
D4 return Zyklen 4 warten

Aufgerufen werden Sie mit call.

Ansonsten geht auch noch Schleifen runterzählen.
Ich habe mir Delay-Routinen (8MHz) gebaut mit 4-512 µS, 500µS-127,5 mS 
und 100ms-22,5 Sec (beinhaltet ein clrwdt)

Wenn der MCU zwischen durch was tun soll.
Kann man das ganez über Timer lösen. Man setzt dann ein Timeout und 
prüft Zyklisch ob es schon abgelaufen ist. Das geht mit und ohne 
Interrupt.
#4792222
Lesenswert?

Peter D. schrieb:
> Der ATtiny13 wird sich bedanken mit Stacküberlauf.
> Spätestens ab der 2. Rekursion ist ne Schleife im Vorteil.

Wenn man nichts Anderes im RAM hat, reicht es gerade so.
Nicht alles geht auf jedem Controller. (Welcher uns ja auch noch nicht 
genannt wurde)

Auf Controllern mit ausreichend RAM macht es keinen Unterschied.



Wegstaben V. schrieb:
> wer denkt sich denn solche Zahlen (Sprunglabel) aus?
1
for ((i=30;i>=0;i--)) ; do echo -e "wait`echo "7*2^$i" | bc`clk:\trcall wait`echo "7*2^($i-1)" | bc`clk" ; done

Sind die benötigten Taktzyklen.



Gruß

Jobst
Gast #4792315
Lesenswert?

Pascal hat sich jetzt ein neues Hobby gesucht, nachdem er gemerkt hat, 
dass Assembler doch nicht so einfach ist, wie er es sich gedacht hat. 
Der Arduino dient jetzt als Wurfgeschoss gegen diebische Elstern.
Gast #4792358
Lesenswert?

ASM Superprofi schrieb:
> Pascal hat sich jetzt ein neues Hobby gesucht, nachdem er gemerkt
> hat,
> dass Assembler doch nicht so einfach ist, wie er es sich gedacht hat.
> Der Arduino dient jetzt als Wurfgeschoss gegen diebische Elstern.

Ein Kumpel meintet das C Programmieren ist wie barfuß durch den Schnee 
zu laufen.
Dann ist der Definition nach Assembler Programmieren wie nackt durch den 
Schnee zu kriechen.

Wenn man denken kann wie ein MCU arbeitet ist ASM nicht mehr so 
kompliziert.
#4792368
Lesenswert?

jannyboy schrieb:
> Ein Kumpel meintet das C Programmieren ist wie barfuß durch den Schnee
> zu laufen.
> Dann ist der Definition nach Assembler Programmieren wie nackt durch den
> Schnee zu kriechen.
>
> Wenn man denken kann wie ein MCU arbeitet ist ASM nicht mehr so
> kompliziert.

Deshalb sehe ich es umgekehrt.

Erst bei größeren CPUs, wo nicht mehr alles syncron läuft, bevorzuge ich 
auch C. Da macht ASM dann nur noch wenig Spaß.


Gruß

Jobst
Gast #4792789
Lesenswert?

Ich würde auch ungern ARM ASM programmieren. Das ist dann eher 
Masochismus. Bei den Atmels macht es dann doch noch Spass. Man ist quasi 
in der ersten Reihe und bekommt bare metal alles mit. Ein riesengrosser 
Lerneffekt. Aber ich will jetzt keine unnötige ASM vs C Debatte starten. 
Beide Sprachen haben Ihren Anwendungsfall.
Gast #4793266
Lesenswert?

jannyboy schrieb:
> Ein Kumpel meintet das C Programmieren ist wie barfuß durch den Schnee
> zu laufen.
Er darf gerne versuchen einen kleinen 8bitter mit 2K Flash in Erlang zu 
programmieren :-)

> Dann ist der Definition nach Assembler Programmieren wie nackt durch den
> Schnee zu kriechen.
Ist doch nach der Sauna ganz nett.

ALLE Programmierspachen sind doof.
Wo bleibt der Simultanübersetzer der Forumgestammel in super effizienten 
ASM Code umsetzt ?
Gast #4794267
Lesenswert?

jannyboy schrieb:
> Ich laufe gerne barfuß und nackt durch den Schnee.

Ist wie mit Assembler.

Man kommt nur langsam voran, stößt sich an jedem kleinen Stein und nach 
einer Zeit spürt man die Schmerzen nicht mehr was manche dahingehend 
interpretieren das man weder Schuhe noch motorisierte 
Fortbewegungungsmittel braucht.

Durch die bald einsetzende Hypothermie fühlt man sich richtig gut, sogar 
zu warm ist einem aber eigentlich befindet man sich nur auf dem Weg zum 
Sterbeprozess.

War in Mobys diversen Assembler Threads sehr anschaulich zu beobachten.

Nein nein, mach mal. Assembler ist der kleinste gemeinsame Nenner und 
besser kann man seine MCU nicht kennenlernen.
Später ist man dann froh wenn der Compiler einen riesen Klumpen Arbeit 
erledigt um den man sich früher selbst gekümmert hat.
#4795979
Lesenswert?

jannyboy schrieb:
> Ein Kumpel meintet das C Programmieren ist wie barfuß durch den Schnee
> zu laufen.

C ist der Schraubenschlüssel für Assemblerprogrammierer (weil es auf 
Dauer nicht gut tut, Schrauben mit den Zähnen auf und zu zu machen).

C++ hat den Schraubenschlüssel auch, man kann ihn sogar direkt 
verwenden, oder - wenn man will - über Drähte an einem Fly-By-Wire 
Joystick ferngesteuert.
Gast #4796384
Lesenswert?

Und hier noch eine Analogie: ^^

Assembler: Schraubenschlüssel, Hammer und Feile. Die Teile muss man 
zuerst mit der Feile "ausarbeiten", bevor man sie zusammenschrauben 
kann.

C: Fräse, Dreh- und Bohrmaschine. Feile nach bedarf.

C++: CNC und weitere Computergesteuerte Werkzeuge. Die muss aber auch 
bedienen können. Hand- und Elektrowerkzeuge nach bedarf. Feile ist in 
der Nähe.

Java/DOTNET/BASIC usw: LEGO und Fischertechnik. Vorgefertigte Teile.

:)

MfG,
Andreas
(Firma: matzetronics) #4796404
Lesenswert?

Arduino F. schrieb:
> http://www.bretmulvey.com/avrdelay.html

Dazu hier noch eine, die nur ein Register und ein wenig Stack braucht 
und weite Bereiche abdeckt:
1
.equ  second  = 0x70    ; roughly 1 second with wozwait @ 16Mc/s
2

3
onesec:  ldi  del,second
4
wozwait: push  del
5
wwait3:  push  del
6
wwait2:  push  del
7
wwait1:  subi  del,1  
8
  brne  wwait1
9
  pop  del
10
  subi  del,1
11
  brne  wwait2
12
  pop  del
13
  subi  del,1
14
  brne  wwait3
15
  pop  del
16
  subi  del,1
17
  brne  wozwait
18
  ret
Frei nach Steve Wozniak im Apple ][ Monitor ROM. Das geht mit jedem MC 
mit Stack.
Gast #4796485
Lesenswert?

1
; Warteroutine bei 8 MHz W x 2 µS + 2 µS  
2
Delay1
3
    movwf D1
4

5
    nop
6
    decfsz  D1
7
    goto $-2
8
    return
9

10
Delay50ms
11
    movlw .100
12
  
13
; Warteroutine bei 8 MHz W x 500 µS
14
Delay2
15
    movwf D2
16
    movlw .248
17
  
18
    call Delay1
19
    decfsz D2
20
    goto $-3
21
    return
22

23
; Warteroutine bei 8 MHz W x 100 mS
24
Delay3
25
    movwf D3
26
    
27
    clrwdt
28
    movlw .200
29
    call Delay2
30
    decfsz D3
31
    goto $-4
32
    return
33
    
34
D8    nop
35
D7    nop
36
D6    nop
37
D5    nop
38
D4    return

Achtung PIC-Code :D
Gast #4796582
Lesenswert?

Schlecht. Aber besser als die davor.

Natürlich werde ich meine NICHT posten. Aber den Aufruf einer guten 
Routine sieht so aus:

delayms 12345
oder, wenn man Mikrosekunden möchte:
delayus 12345

Reichweite von 1-65535. Genau so muss sowas aussehen und nicht anders.
Gast #4796710
Lesenswert?

Natürlich habe ich die Drecksroutine kapiert. Aber wer heute noch sowas 
abliefert, der hat doch nicht mehr alle Tassen im Schrank. So eine 
unnötige Stackquälerei. Von der Wartbarkeit reden wir besser gar nicht 
erst.

Aufgabe: Warte 325ms!

Ooooh, kaputt.

Aufgabe: Warte 5us!

Mist, geht nicht.
Gast #4796717
Lesenswert?

ASM Superprofi schrieb:

> Natürlich werde ich meine NICHT posten.

Ich meine auch nicht. Wäre mir einfach peinlich, so deutlich zu zeigen, 
dass ich mal relativ viel Lebenszeit damit verschwendet habe, sowas 
Sinnloses zu programmieren...

> Aber den Aufruf einer guten
> Routine sieht so aus:
>
> delayms 12345
> oder, wenn man Mikrosekunden möchte:
> delayus 12345
>
> Reichweite von 1-65535. Genau so muss sowas aussehen und nicht anders.

Nö. Meine verbraucht Takte und zwar absolut exakt die spezifizierte 
Menge davon (nennen wir sie mal: "n"). Und man kann ihr als Parameter 
0<=n<=2^32-1 übergeben. Will man irgendeine Zeiteinheit warten, übergibt 
man als Parameter irgendwas wie dieses: n/FCLOCK für Sekunden oder 
n/(1000.0*FCLOCK) für ms oder n/(10000000.0*FCLOCK) für µs. Es spricht 
natürlich auch garnix dagegen, für Leute, die nicht einmal solche 
simplen Sachverhalte nachvollziehen können, einen zusätzlichen Satz von 
Makros zu schaffen, die diese Trivialitäten dann auch noch vor dem 
völlig hirnlosen Benutzer verbergen, der dann irgendwo in der Region 
generischer C-C&Pler liegen würde...

Im Endeffekt hätte man dann ziemlich genau den Delay-Schwachsinn, den 
z.B. der avrgcc bietet. Der ist recht schick, weil recht 
resourcen-effizient umgesetzt. Natürlich nicht ganz so effizient wie 
meine Lösung, aber darauf bin ich ausnahmsweise einmal NICHT stolz. 
Denn beides ist gleichermaßen vollkommen verblödete, vollkommen 
sinnlose, absolut schwachsinnige Scheiße! (Und ich schäme mich, 
Lebenszeit in meine Lösung investiert zu haben, zumal ich es schon zum 
Zeitpunkt der Implementierung zumindest im Prinzip besser wusste...)

Der Punkt ist nämlich: Software-Delays an sich sind in den allermeisten 
Fällen vollkommener Schwachsinn. Jedenfalls immer dann, wenn ihre Dauer 
die Dauer eines Interruptframes des Zielsystems nennenswert übersteigt, 
sagen wir mal ganz grob: >Faktor 2..3.

Jegliche SINNVOLLEN Software-Delays lassen sich also beim 
AVR8-Zielsystem mit einer ziemlich kleinen NOP-Rampe mit etwas 
Macro-Magie für die ganz kleinen Zeiten abhandeln (die NOP-Rampe kam 
irgendwo im Thread auch bereits vor, bin jetzt zu faul, hochzuscrollen 
und nachzuschauen, wer sich da als ein Mensch mit Durchblick geoutet 
hat).

Alles andere ist sinnlose Beförderung der Entropie durch sinnlose 
Umwandlung von elektrischer Energie in Abwärme durch den sinnlosen 
Verbrauch von Rechenzeit. Wer sowas braucht oder zu brauchen glaubt, 
kann einfach nur nicht programmieren. That's all.
Gast #4796755
Lesenswert?

Es geht hier um ZEIT verzögerung, nicht um TAKT verzögerung. Dir ist 
der Unterschied anscheinend nicht klar. Anscheinend programmierst du 
Assembler. Das macht die Sache noch korioser. Du solltest wissen, dass 
es keine allgemeine Lösung für alle Probleme gibt und wenn man TAKTE 
abwarten muss, dann heisst der Befehl sicher nicht delayus x, sondern 
nops x!

Und ich glaube nichtmal du verwendest eine taktorientierte Routine, um 
z.B. eine LED 20ms lang einzuschalten.

Ob man dafür den Prozessor in eine nop-Schleife schickt oder in einen 
sleep-state, ist wieder ein ganz anderes Thema und lohnt sich umso 
weniger, je kürzer die Zeiteinheit ist.

Und wenn ich einmalig in der Initialisierungsphase 200ms warten muss, 
werde ich sicher keinen Timer programmieren, sondern die 200ms lang 
Däumchen drehen. Obendrein laufen die MCUs von GUTEN Programmierern 
immer in der niedrigstmöglichen Taktrate. Ich tippe mal darauf, dass die 
meisten C-Programmierer gar nicht wissen, was CLKPR macht, oder haben es 
einmal gesehen, sich gewundert, dass man es nicht beschreiben kann (muss 
kaputt sein!) und haben es dann vergessen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren