mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 1ms Pause-Schleife


Autor: Ithamar Garbe (antimon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

irgendwie hab ich nach stundenlangem Googlen, ausprobieren etc. keinen
Erfolg gehabt, bevor ich ganz verzweifle, wende ich mich lieber an die
Profis...

Ich möchte eine Schleife programmieren, die mir in etwa 1ms Pause
erzeugt, dieser möchte ich dann über einen Parameter die Anzahl der
Durchläufe (sprich: die Anzahl der ms) übergeben.

Mein Ansatz hat leider nicht funktioniert:

[assembler]
delay:
  LDI    r17, 2
dely1:
  LDI    r16, 166
dely:
  DEC    r16
  BRNE  dely
  DEC    r17
  BRNE  dely1
  DEC    r25
  BRNE  delay
  RET
[/assembler]

Meine Idee war folgende: DEC und BRNE brauchen zusammen 3 Takte, wird
diese Schleife 165x ausgeführt, haben wir ungefähr 500 Takte. Das Ganze
dann 2x durchlaufen entspricht 1000 Takte - also bei 1Mhz wäre das 1ms
Und im Register r25 steht die Anzahl der Gesamtdurchläufe, sprich die
Anzahl der ms... aber ich komm nicht auf 1ms wenn ich in r25 ne 2
reinschreibe-wo liegt mein Denkfehler?

Und wenn ich in einer Variablen fq=4000000 die Taktfrequenz bei einem
externen Quarz drinstehen habe, wie mache ich es am geschicktesten,
dass ich obige Schleife dann auch 4x so oft durchlaufen lasse?

Irgendwie hab ich heut schon den halben Tag vertan, ohne auf ein
Ergebnis zu kommen... vielen Dank also schon mal für Eure Hilfe!!

Autor: Marc Gauger (marc_gauger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Brne ist doch erst wenn der wert Negativ ist oder? und 2 minus 1 minus 1
= 0 und nicht negativ, also würd ich sagen schreib einfach mal 1 rein.
vielleicht kommst du dann auf deine ms.

Nur eine Idee.

MFG Marc

Autor: Andi K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist doch Easy:

.equ AVRTakt=8
Wait1000uS:
 ldi r24,low(1000*AVRTakt/4)
 ldi r25,high(1000*AVRTakt/4)
WaituS:
  sbiw r25:r24,1
 brne WaituS
 ret

In AVRTakt einfach die tatsächliche Frequenz in MHz definieren,
fertig.
Kann auch so was wie 3.62345 etc. sein.
Ist zwar jetzt nicht auf den Takt genau aber es reicht.
Für ziemlich genau gibt es sowieso nur Timer-Interrupt.

Für z. B. 50µS läßt sich das erweitern mit

Wait50uS:
 ldi r24,low(50*AVRTakt/4)
 ldi r25,high(50*AVRTakt/4)
 rjmp WaituS

Die Formel N*AVRTakt/4 rechnet die Anzahl der Schleifendurchläufe unter
Berücksichtung, das ein Durchlauf 4 Takte dasuert, aus.
Bei 8MHz sind dann 65535 / 8 * 4 = 32,7675 mS möglich.
Ließe sich für eine längere Zeit auch auf 24 oder 32Bit-Zählung
erweitern.

MfG
Andi

Autor: Ithamar Garbe (antimon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wahrscheinlich denk ich da zu kompliziert... und es geht auch
einfacher...

Was du meinst, ist aber vermutlich BRMI (Branch if Minus), BRNE ist
Branch if not equal, also wenn das Ergebnis ungleich 0 ist...

Autor: Andi K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder so:

WaitmS:
 ldi r24,low(1000*AVRTakt/4-1)
 ldi r25,high(1000*AVRTakt/4-1)
WaitmS1:
  sbiw r25:r24,1
 brne WaitmS1
 nop
 dec r16
 brne WaitmS
 ret

In r16 die Anzahl der mS und dann aufrufen.
Das NOP ist zum Ausgleich wegen dem Zyklus von 4 Takten.

MfG
Andi

Autor: Ithamar Garbe (antimon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
lol - also soo easy ist das leider nicht... zumindest für mich nicht ;)

Ich wusste ned mal dass man so einfach zwei Register konkatenieren
kann, bisher hab ich nur einen HC68011 programmiert, und da ist die
Umstellung auf AVR schon ziemlich groß...

Also prinzipiell ist dein Code supereinfach und funktioniert auch
(fast) gut... ich hab nur das Problem dass die Ausgabe auf dem µC um
den Faktor 4 zu schnell vor sich geht. Im Simulator läuft der µC mit 4
Mhz, stelle ich AVRTakt auf 4 ein, kommt ziemlich genau 1ms raus.
Der reale µC hat zwar einen 4Mhz Quarz dran, der aber noch nicht
aktiviert ist, läuft also mit den internen 1Mhz. Und bei AVRTakt=1 und
hundertfachem Schleifendurchlauf blinkt er 4x/Sekunde... woran kann das
liegen?

Ansonsten vielen Dank für den Code, der hat mir schon einiges an Ärger
erspart!!

Autor: kryon2000 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Denk daran das der Aufruf der Unterroutine auch nochmal 7 takte benötigt
(rcall + ret) ;-)

Autor: kryon2000 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deine Routine von oben würde so aussehen:
ldi  r25, 1
rcall  delay    ;1011 takte  

delay:      ;------------------------
  LDI    r17, 2      ;---------------

dely1:
  LDI    r16, 166  ;-------
dely:        ;   498 t    1002t     1004t
  DEC    r16    ;
  BRNE  dely    ;-------

  DEC    r17
  BRNE  dely1    ;---------------


  DEC    r25  
  BRNE  delay    ;-----------------------
  RET


Der Aufruf würde also 1011 takte verschwenden wenn r25 = 1 wäre.

Autor: Andi K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na ja, bei einer Pause von 1mS braucht man glaube ich nicht über 7 Takte
(1µS) zu reden.


@Ithamar Garbe (Antimon): Wenn Du sicher bist, das der AVR mit 1MHz
läuft, hast Du dann AVRTakt auf 1 eingestellt?

MfG
Andi

Autor: Mika (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Im Anhang gibts nen Schleifengenerator. Hat bisher perfekt
funktioniert.
Gruss Mika

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.