8051 Zeitschleife in C/inline Assembler

Gast #1340832
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:
1
void wait_1ms() {
2
  #pragma asm
3
                       ; save R0 and R1 to stack
4
    push   0xE0        ; push accu to stack
5
                       ; save R0 and R1 to stack
6
    mov    0xE0, 0x00  ; save R0 to A
7
    push   0xE0        ; save A to stack
8
    mov    0xE0, 0x01  ; save R1 to A
9
    push   0xE0        ; save A to stack
10

11
    M0:  mov  0x01,#2
12
         mov  0x00,#189
13
    M1:  djnz 0x00,M1
14
         djnz 0x01,M1
15

16
                       ; restore R0 and R1 from stack
17
    pop 0xE0           ; get R1
18
    mov 0x01, 0xE0     ; restore R1
19
    pop 0xE0           ; get R0
20
    mov 0x00, 0xE0     ; restore R0
21
    pop 0xE0           ; pop stack to accu
22
  #pragma endasm
23
}

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.
Gast #1341265
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.
Gast #1341273
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
Gast #1341362
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...
Gast #1341735
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

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.