Forum: Mikrocontroller und Digitale Elektronik 8051 Ride7 Delay-Funktion


von Nil (nilsnilss)


Lesenswert?

Ich brauch für ein simples Programm eine ganz einfache Delay-Routine, 
die nicht besonders genau sein soll, sondern einfach ca. X ms 
Verzögerung im Programm hervorrufen soll.
Unten ein kurzes Test-Programm welches einfach im Sekundentakt die LEDs 
an P2 blinken lassen soll.
Leider passiert gar nichts.
Werden die beiden Schleifen einfach wegoptimiert und wenn ja, was kann 
ich dagegen tun?

Ah und der Controller läuft übrigens mit 1Mhz (12Mhz Quarz, Takt wird 
intern aber noch durch 12 geteilt).
1
#include <at89c5131.h>
2
#include <intrins.h>
3
4
void delay_ms(int k)
5
{
6
    int i=1000;  
7
8
    while(--k)
9
    {
10
        while(--i)
11
        {
12
            _nop_();
13
        }
14
        
15
    }
16
}
17
18
int main(void)
19
{ 
20
    while(1)
21
    {
22
        delay_ms(1000);
23
    
24
        P2 = 0xFF;
25
    
26
        delay_ms(1000);
27
    
28
        P2 = 0;
29
    }
30
31
    return 0;
32
}

von Bernd N (Gast)


Lesenswert?

volatile int i=1000;

von Nil (nilsnilss)


Lesenswert?

Daran hab ich auch schon gedacht, bringt leider keinerlei Änderung.

von Georg G. (df2au)


Lesenswert?

Und denk dran, dass dein i nur beim ersten Durchlauf der Schleife auf 
1000 gesetzt wird. Danach ist es 0 und die innere Schleife dauert 
entsprechend länger.

von Georg G. (df2au)


Lesenswert?

Nils Friess schrieb:
> Werden die beiden Schleifen einfach wegoptimiert

Das sollte ein schneller Blick auf den Object Code zeigen.

von jjflash (Gast)


Lesenswert?

1.) volatile ist zwingend notwendig, da ansonsten der Compiler das 
tatsächlich "wegoptimiert" ... (war mal ein Fehler bei meinen 
Auszubildenden)

2.) würdest du mit einem Oszilloskop an den Port 2 gehen würdest du wohl 
höchstwahrscheinlich was sehen. Welche Frequenz hast du dort ?

von jjflash (Gast)


Lesenswert?

Georg G. schrieb:
> Und denk dran, dass dein i nur beim ersten Durchlauf der Schleife auf
> 1000 gesetzt wird. Danach ist es 0 und die innere Schleife dauert
> entsprechend länger.

volatile int i;

i = 1000;

So ist die beim Eintritt immer 1000 (nehm ich zumindest mal an ... )

von Nil (nilsnilss)


Lesenswert?

Oszilloskop hab ich keins zur Verfügung.
Hier mal das Listing. Also für mich sieht das nicht wirklich nach großer 
Optimierung aus. Die Funktion wird quasi eins zu eins übersetzt.
1
            ; FUNCTION _delay_ms (BEGIN)
2
              ; Register R6R7 is assigned to parameter k
3
              ; R2R3 is assigned to i
4
                                           ; SOURCE LINE # 6 
5
0000 7A03           MOV    R2,#003H
6
0002 7BE8           MOV    R3,#0E8H
7
0004         ?WHILE2:
8
                                           ; SOURCE LINE # 8 
9
0004 EF             MOV    A,R7
10
0005 1F             DEC    R7
11
0006 7001           JNZ    ?LAB3
12
0008 1E             DEC    R6
13
0009         ?LAB3:
14
0009 EE             MOV    A,R6
15
000A 4F             ORL    A,R7
16
000B 600C           JZ     ?NXT2
17
000D         ?WHILE3:
18
                                           ; SOURCE LINE # 10 
19
000D EB             MOV    A,R3
20
000E 1B             DEC    R3
21
000F 7001           JNZ    ?LAB4
22
0011 1A             DEC    R2
23
0012         ?LAB4:
24
0012 EA             MOV    A,R2
25
0013 4B             ORL    A,R3
26
0014 60EE           JZ     ?WHILE2
27
                                           ; SOURCE LINE # 12 
28
0016 00             NOP    
29
0017 80F4           SJMP   ?WHILE3
30
0019         ?NXT2:
31
                                           ; SOURCE LINE # 16 
32
0019 22             RET    
33
34
            ; FUNCTION _delay_ms (END)

von Nil (nilsnilss)


Lesenswert?

Habs jetzt mal mit For-Schleifen probiert, den Wert von i ein wenig 
variiert und siehe da: es klappt (einigermaßen genau)
1
#include <at89c5131.h>
2
#include <intrins.h>
3
4
sfr at P2 A;
5
6
volatile int i;
7
8
void delay_ms(int k)
9
{
10
    for(k; k>0; k--)
11
    {
12
        for (i = 50; i>0; i--)
13
        {
14
            _nop_();
15
        }
16
        
17
    }
18
}
19
20
int main(void)
21
{ 
22
    A = 0x12;
23
24
    while(1)
25
    {
26
        delay_ms(1000);
27
    
28
        A = 0xFF;
29
    
30
        delay_ms(1000);
31
    
32
        A = 0;
33
    }
34
35
    return 0;
36
}

von Georg G. (df2au)


Lesenswert?

jjflash schrieb:
> So ist die beim Eintritt immer 1000 (nehm ich zumindest mal an ... )

Soweit richtig. Aber nach dem ersten Durchlauf durch die innere Schleife 
wird sie nicht wieder mit 1000 initialisiert sondern mit 0, entsprechend 
65000. Deine Sekunde Verzögerung wird also in erster Näherung eine 
Minute sein. Probiere es noch einmal und hab einfach viiiiiieeeeeeel 
Geduld.

von nils (Gast)


Lesenswert?

Aaah jetzt hat's Klick gemacht, werd ich mal ausprobieren sobald ich 
wieder zuhause bin.

von jjflash (Gast)


Lesenswert?

Georg G. schrieb:
> Aber nach dem ersten Durchlauf durch die innere Schleife
> wird sie nicht wieder mit 1000 initialisiert sondern mit 0,

stimmt

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.