www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 8051 Zeitschleife in C/inline Assembler


Autor: fragender (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich bastle mir gerade für C (Keil uVision) eine kleine Zeitschleife 
zurecht.

Nun habe ich eine Funktion, wait(), und in der habe ich eine kleine 
Zeitschleife mit Inline Assembler gebastelt.
Mein Takt beträgt 11.0592Mhz, daher ist ein MZ 1.085uS lang.

Hier der Code:
void wait_1ms() {
  #pragma asm
                       ; save R0 and R1 to stack
    push   0xE0        ; push accu to stack
                       ; save R0 and R1 to stack
    mov    0xE0, 0x00  ; save R0 to A
    push   0xE0        ; save A to stack
    mov    0xE0, 0x01  ; save R1 to A
    push   0xE0        ; save A to stack

    M0:  mov  0x01,#2
         mov  0x00,#189
    M1:  djnz 0x00,M1
         djnz 0x01,M1

                       ; restore R0 and R1 from stack
    pop 0xE0           ; get R1
    mov 0x01, 0xE0     ; restore R1
    pop 0xE0           ; get R0
    mov 0x00, 0xE0     ; restore R0
    pop 0xE0           ; pop stack to accu
  #pragma endasm
}

Mit dem CALL zu dieser Funktion und dem RET am Ende komme ich auf 922 
Takte. Das Entspricht 1000,37uS, sehr genau eine Millisekunde.

Funktioniert alles wunderbar, nur saß ich hierfür eine knappe Stunde 
dran, beim Ausprobieren und Herausfinden, wie ich soetwas überhaupt zu 
machen habe.

Timer möchte ich nicht verwenden, da ich die mir für andere Anwendungen 
offen halten will. Am Ende soll das ganze ein kleiner 8Bit-Computer 
werden, den ich an den Fernseher anschliessen kann. Da kann man Timer 
immer brauchen. Einer ist sowieso schon für den UART in Verwendung.

Weiss einer von euch vielleicht wie man sowas einfacher gestalten kann 
oder kennt ein Berechnungsprogramm für solche Zwecke? Für Assembler gibt 
es da ja einige, aber die bringen mir nur für die Innere Zeitschleife 
etwas und da auch nur bedingt, da ich die ja wieder ändern muss, 
jenachdem was mein Code aussenrum braucht.

Autor: Carlos (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du Dir die ganze Rechnerei sparen willst, geht es einfacher:
Direkt vor dem Aufruf es Unterprogramms einen Port-Pin auf Low setzen, 
nach Beendigung des Aufrufs sofort wieder auf High setzen.
Oszilloskop am Port-Pin anschließen und Breite des Low-Impulses 
ausmessen.
Dann einfach eine kleine Wertetabellle für die Scheifenzähler aufstellen 
und ausmessen -> Fertig.
Je nach Bedarf übergibst Du dann die passenden Werte für die innere und 
die äußere Schleife.

Gruß

Carlos.

Autor: Carlos (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Entschuldigung, habe gerade gesehen daß Du ja in C programmierst.
Dann geht es noch einfacher:

P1_1=0;                     // Port-Pin auf Low
for (i=0; i<=wert; i++);    // Reines Warten!
P1_1=1;                     // Port-Pin auf High

Ausmessen -> Wertetabelle für ´wert´ anlegen -> Fertig.


Carlos

Autor: fragender (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
C-Schleifen lass ich extra sein und mach' das mit Inline Assembler, da 
mir das zu ungenau wird. Je nach Compiler-Optimierung wird die anders 
und die Ausgabe am Pin verbraucht ja auch Zeit und ein Oszi habe ich 
leider nicht.

Aber der Ansatz mit einer Tabelle ist gut, warum ich von Anfang an nicht 
schon dran gedacht habe, meist sieht man den Wald vor lauter Bäumen 
nicht mehr....
Einfach das Call, Ret, Sichern und Wiederherstellen des Stacks 
ausrechnen und die Schleife dazwischen mit einer Tabelle berechnen...

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Besser du machst keine Warteschleife um irgendwas zu verzögern oder 
Blinken zulassen, weil der Controller sonst nichts anderes macht in 
dieser Zeit.

Wenn Du andere Aufgaben noch lösen willst solltest dich mit dem Gedanken 
anfreunden einen Timer laufen zu lassen der von mir aus alle 50 ms ne 
Variable hochzählt.

Diese Variable kannst Du dann auswerten um zum Bsp. ein Bit zu setzen.

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.