Taktanzahl einer for-Schleife

Gast #3122358
Lesenswert?

Guten Morgen,

ich habe folgenden Code:

while ((PIN_SHT & (1<<PIN_DATA)) && (i < 320000))
    i++;

  if (i >= 320000)
    *error_code = 3;

mit 2Mhz; 320000 = 320ms

So die while schleife kontrolliert, ob der Pin_data high wird oder die 
Zählvariable 320000 erreicht hat und bricht dann die Schleife ab.

jetzt zu meiner frage bei 2MHz habe ich eine Periodendauer von 500ns.

Ich bin ich davon ausgegangen, dass die Prüfung der Bedingung einen Takt 
benötigt und die Inkrementierung einen weiteren Takt. Wodurch ich 2 
Takte habe oder 1µs.

Stimmt das oder brauch die Schleife zur Prüfung der Bedingung mehr als 1 
Takt?

Vielen Dank für eure Hilfe!
Gast #3122370
Lesenswert?

Frank O. schrieb:
> Ich bin ich davon ausgegangen, dass die Prüfung der Bedingung einen Takt
> benötigt

nie. Es sind schon mal 2 Bedingungen die geprüft werden müssen

PIN_SHT & (1<<PIN_DATA)

und

i < 320000

also wenn überhaupt schon mal 2 Takte. Da wir nicht wissen ob um welche 
CPU es sich handelt gehe ich einfach mal von einer 8bit CPU aus. Damit 
braucht man hier schon mal wieder 2 Takte weil das ganze mindestens 
16bit ist.

Aber sinnvoller ist es einfach mal in das erzeugte assembler file zu 
schauen und selber zu rechnen.
Gast #3122372
Lesenswert?

Hi

>Stimmt das oder brauch die Schleife zur Prüfung der Bedingung mehr als 1
>Takt?

Sieh dir einfach den erzeugten Assemblercode an. Aber es sind auf jeden 
Fall einige Takte mehr als 1.

MfG Spess
#3122374
Lesenswert?

Ich gehe mal von einem 8 Bit Prozessor aus:
1 Takt für die Überprüfung der Schleifenbedingung ist kaum realistisch, 
da ja 2 voneinander unabhängige Bedingungen geprüft werden. Zusätzlich 
führst du mit i<320000 einen vergleich mit einer 32-bit Variable durch.
i++ inkrementiert eine 32-bit Variable, also geht das auch nicht in 
einem Takt.
Gast #3122377
Lesenswert?

Hallo,

Die Pruefung brauhct natürlich mehr als einen Takt, Du hast ja auch 2 
bedingungen verknüpft Pin einlesen, bit schiften, verunden, zählvariable 
prüfen... und damm noch ein und verknüpfung der beiden Ergebnisse

am besten du schasut Dir mal den Assembler Code an, den der Compiler 
daraus macht.

Die anzahl der Takte sind vermutlich auch noch von der Eingestellten 
Optimierungsstufe den Compilers (-O0 oder -O2) abhängig.

ps. Die schleife bricht ab, wenn der Pin_data low wird
Gast #3122396
Lesenswert?

Kann mir einer helfen herauszufinden, wieviele Takte das sind ich kenn 
mich mit assembler absolut nicht aus!

  while ((PIN_SHT & (1<<PIN_DATA)) && (i < 320000))
     bfa:  86 9b         sbis  0x10, 6  ; 16
     bfc:  09 c0         rjmp  .+18       ; 0xc10 
<SHT75Temperature+0x50>
     bfe:  80 30         cpi  r24, 0x00  ; 0
     c00:  22 ee         ldi  r18, 0xE2  ; 226
     c02:  92 07         cpc  r25, r18
     c04:  24 e0         ldi  r18, 0x04  ; 4
     c06:  a2 07         cpc  r26, r18
     c08:  20 e0         ldi  r18, 0x00  ; 0
     c0a:  b2 07         cpc  r27, r18
     c0c:  99 f7         brne  .-26       ; 0xbf4 
<SHT75Temperature+0x34>
     c0e:  08 c0         rjmp  .+16       ; 0xc20 
<SHT75Temperature+0x60>
    i++;

Was wird denn jetzt alles gezählt?

Vielen Dank
#3122398
Lesenswert?

Frank O. schrieb:

> mit 2Mhz; 320000 = 320ms
> So die while schleife kontrolliert, ob der Pin_data high wird oder die
> Zählvariable 320000 erreicht hat und bricht dann die Schleife ab.

Mal ganz abgesehen von deiner Milchmädchenrechnung mit den Taktzyklen in 
der Schleife ist das ein ganz schlechtes Design, weil es nicht 
portabel ist. Schon eine simple Änderung der Compilerflags (z.B. 
Debug-Build vs. Release) wird voraussichtlich die Wartezeit verändern. 
Dito eine Änderung der Taktfrequenz.

Wenn du überhaupt busy-waiting verwenden willst, dann geh wenigstens 
über   _delay_us() aus <util/delay.h>. Angesichts der mit 320ms eher 
langen Wartezeit würde ich aber eher einen Timer empfehlen.


XL
Gast #3122429
Lesenswert?

Axel Schwenke schrieb:
> Wenn du überhaupt busy-waiting verwenden willst, dann geh wenigstens
>
> über   _delay_us() aus <util/delay.h>. Angesichts der mit 320ms eher
>
> langen Wartezeit würde ich aber eher einen Timer empfehlen.

Ja vielen Dank!

Ich hätte auch noch einen Timer frei nur das müsste ich wieder über 
Interrupts laufen lassen und ich hab da schon einige verwendet und 
wollte nicht noch weitere verwenden, wodurch sich die chance, dass sich 
2 überschneiden und dadurch versetzt ausgeführt werden erhöht!

Aber ich hab es mal im hinterkopf und werde es einfach mal später 
ausprobieren.

Im Anhang habe ich mal die komplette Funktion hochgeladen!
Ich glaube muss mich mal was mit assembler beschäftigen, dass ist alles 
nicht verstänlich für mich!
Angehängte Dateien:
#3122433
Lesenswert?

Dann machs wenigstens so
1
  i = 0;
2
  while ((PIN_SHT & (1<<PIN_DATA)) && (i++ < 320))
3
    _delay_ms( 1 );
4

5
  if (i >= 320)
6
    *error_code = 3;

dann stimmt die Zeit wenigstens so einigermassen, weil der Rest der 
SChleife im Vergleich zum _delay_ms unter "ferner liefen" fungiert.
Gast #3122438
Lesenswert?

Karl Heinz Buchegger schrieb:
> Dann machs wenigstens so
>
>   i = 0;
>
>   while ((PIN_SHT & (1<<PIN_DATA)) && (i++ < 320))
>
>     _delay_ms( 1 );
>
>
>
>   if (i >= 320)
>
>     *error_code = 3;
>
> dann stimmt die Zeit wenigstens so einigermassen.

Ja habe ich mir auch überlegt genau muss es ja eh nicht sein! ob jetzt 
310 oder 330ms spiel keine Rolle
#3122448
Lesenswert?

Frank O. schrieb:
> Was wird denn jetzt alles gezählt?

Im Datenblatt Deines AVRs gibt es eine Tabelle "Instruction Set 
Summary", in der ist zu jedem ASM-Befehl unter anderem auch die 
Abarbeitungszeit (in Taktzyklen) aufgelistet.

Falls damit immernoch Unklarheiten bestehen, hilft die Hilfe des 
AVR-Studios (Cursor auf ASM-Befehl stellen und F1-Taste drücken) oder 
das PDF mit der ausführlichen Beschreibung des Instruction-Set.

Der Rest ist dann einfaches Addieren...

...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren