#define fuer _delay_loop_2

OP Persönliche Seite #1516257
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?
Moderator Persönliche Seite
Was spricht dagegen?
1
void delay_1ms( uint8_t ms ) { 
2
   while (ms--)
3
      _delay_ms(1);
4
}

_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
(wenn ich dich richtig verstanden habe).
OP Persönliche Seite
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.
Gast
Es entscheidet sich erst bei dem Aufruf der Funktion, von welchem Typ 
ONEMS ist. In deinem Fall ist es ein Integer, kann somit nur ganzzahlig 
werden. 1/4 ergibt nach Adam Riese 0.25, somit also 0.
Gast
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(ONEMS);
12
}

Ausgabe:
1
== 0.000000
Gast
1
#include <stdio.h>
2

3
#define ONEMS 1/4*16000000/1000
4
int main() {
5
    printf("%f\n",(float)ONEMS);
6
    printf("%d\n",(int)ONEMS);
7
}

Ergebnis:
1
4000.000000
2
0
Moderator Persönliche Seite
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
(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
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
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
> 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

Eine eigene Frage? Dieser Thread ist über 16 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.