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


von fragender (Gast)


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:
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.

von Carlos (Gast)


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.

von Carlos (Gast)


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

von fragender (Gast)


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...

von Klaus (Gast)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.