#define fuer _delay_loop_2

OP Persönliche Seite #1516257
Lesenswert?

Hallo

Ich steh auf dem Schlauch, oder so... ;)

Wenn ich in meinem Source Code meine Wartefunktion so definiere, stimmt 
die Wartezeit:
1
void delay_1ms( uint8_t ms ) {
2
   while (ms--)
3
      _delay_loop_2( 4000 );    // 4 cycles per iteration
4
}

Für meinen atmega168 mit 16Mhz hab ich überschlagen:
4 Mio Iterationen - 1 s
4 k   Iterationen - 1 ms

Gut. Um ein bisschen portabler zu schreiben, packe ich die Formel in ein 
#define statement und ... meine Funktion tut nicht mehr, die Wartezeit 
wird viel zu lang:
1
// delay loop iterations for 1ms
2
#define ONEMS 1 / 4 * F_CPU / 1000
und
1
void delay_1ms( uint8_t ms ) { 
2
   while (ms--)
3
      _delay_loop_2( (uint16_t) ONEMS );    // 4 cycles per iteration
4
}


Was mach ich falsch?
OP Persönliche Seite #1516302
Lesenswert?

Jörg Wunsch schrieb:

> _delay_ms ist weiter nichts als ein Wrapper um _delay_loop_2, der
> aus F_CPU und dem angegebenen Wert die für _delay_loop_2 notwendige
> Zyklenanzahl berechnet -- also letztlich exakt das, was du willst

Das ist richtig. Da _delay_ms aber mit float Zahlen rumhantiert, will 
ich  diesen "teuren" Aufruf/Code wegoptimieren.

Das Resultat meiner Rechnerei im #define sei also Null, versteh ich noch 
nicht, weshalb das so ist.
Moderator Persönliche Seite #1516319
Lesenswert?

Tom M. schrieb:

> Das ist richtig. Da _delay_ms aber mit float Zahlen rumhantiert, will
> ich  diesen "teuren" Aufruf/Code wegoptimieren.

"teuer" ist das nur für den Compiler.  Der macht daraus dann den
gewünschten Integerwert.

Die Intention hinter den Gleitkommazahlen war einfach, dass auf
deinem Quarz ja nicht drauf steht: 7372800 Hz, sondern: 7,3728 MHz.
Damit kannst du schreiben:
1
#define F_CPU 7.3728E6

ohne dir erst überlegen zu müssen, wie viele Nullen du jetzt anhängst.
Außerdem kannst du halt auch bei _delay_ms schreiben:
1
_delay_ms(0.8);
2
_delay_ms(2.2);

Das empfinde ich als die durchaus natürliche Denkweise eines
Ingenieurs.  Solche Aufrufe werden oft genug benutzt, um bestimmte
Timing-Werte aus einem Datenblatt zu realisieren, und da stehen sie
auch als Gleitkommazahlen -- weil man das am besten lesen kann.

Die Umrechnung in das, was der Controller kann, sollte man halt dann
dem Computer überlassen können.
Gast #1516320
Lesenswert?

(a) das hat nix mit dem Funktionsaufruf zu tun, sondern mit dem 
cast-Operator.

(b) dein Define ist falsch, der cast bezieht sich nur auf die 1.

Beispiel:
1
#include <stdio.h>
2

3
#define ONEMS \
4
  (1 / 4)
5

6
void print_float(float f) {
7
  printf("== %f\n", f);
8
}
9

10
int main() {
11
  print_float((int)ONEMS);
12
  print_float((float)ONEMS);
13
}

Ausgabe:
1
== 0.000000
2
== 0.000000

1/4 ist 0, egal wie und wo es verwendet wird.
OP Persönliche Seite #1516333
Lesenswert?

Hab jetzt auf _delay_ms() umgestellt und siehe da, mein Code a) 
funktioniert b) ist nicht wesentlich grösser. Schön. :)

Ich meine mich gerade zu erinnern, dass man dem Compiler mit einem 
Suffix mitteilen sollte, wenn man mit nicht-integer Zahlen hantiert, 
sowas wie:
1
#define ONEMS 1L / 4 * F_CPU / 1000

1L (long?)... Muss gleich mal K&R rauskramen...
Gast #1516336
Lesenswert?

Tom M. schrieb:
> Hab jetzt auf _delay_ms() umgestellt und siehe da, mein Code a)
> funktioniert b) ist nicht wesentlich grösser. Schön. :)
Endlich :->

> Ich meine mich gerade zu erinnern, dass man dem Compiler mit einem
> Suffix mitteilen sollte, wenn man mit nicht-integer Zahlen hantiert,
> sowas wie:
Es würde schon helfen, wenn du endlich ein paar verdammte Klammern 
setzen würdest:
1
/* FALSCH!!!!!111einself */
2
#define ONEMS 1L / 4 * F_CPU / 1000
3

4
/* Besser, aber immer noch 0 */
5
#define ONEMS (1L / 4 * F_CPU / 1000)
6

7
/* 'Korrekt': */
8
#define (ONEMS 1.0 / 4.0 * F_CPU / 1000.0)


Probier mal aus:
1
#define X 5 + 9
2

3
printf("== %u\n", 10 * X);
Und? Gibt nicht 14*10=140 aus, gell? Komisch.
OP Persönliche Seite #1516351
Lesenswert?

> Es würde schon helfen, wenn du endlich ein paar verdammte Klammern
> setzen würdest:

Hast ja recht, die Klammern... :)


> Und? Gibt nicht 14*10=140 aus, gell? Komisch.

Nee, da nicht: Der Präprozessor tauscht den Text aus, und dann greift 
das altbekannte "Punkt-vor-Strich". Mein Cast war allerdings total übel, 
oder die Klammern ham gefehlt, oder beides. ;)


Danke euch allen, schönen Abend noch. :)

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