CAST und #if in einer Header-Datei (XC8)

Gast #4114860
Lesenswert?

Hallo zusammen!

Ich hoffe ich bin hier richtig?

Meine IDE ist MPlab X mit dem XC8 Compiler (Free-Version).
Controller: PIC16F1789 (was aber erst mal keine Rolle spielen dürfte)

folgenden Code habe ich in einer Header-Datei:

#define TMR_TEST                27.2
#define TMR_DEVIDER             ((int)TMR_TEST)


#if TMR_DEVIDER < 1
    #define RTCC_DEVIDER    RTCC_DIV_1
    #define DV 0
#elif TMR_DEVIDER < 2
    #define RTCC_DEVIDER    RTCC_DIV_2
    #define DV 1
#elif TMR_DEVIDER < 4
    #define RTCC_DEVIDER    RTCC_DIV_4
    #define DV 2
#elif TMR_DEVIDER < 8
    #define RTCC_DEVIDER    RTCC_DIV_8
    #define DV 3
#elif TMR_DEVIDER < 16
    #define RTCC_DEVIDER    RTCC_DIV_16
    #define DV 4
#elif TMR_DEVIDER < 32
    #define RTCC_DEVIDER    RTCC_DIV_32
    #define DV 5
#elif TMR_DEVIDER < 64
    #define RTCC_DEVIDER    RTCC_DIV_64
    #define DV 6
#elif TMR_DEVIDER < 128
    #define RTCC_DEVIDER    RTCC_DIV_128
    #define DV 7
#elif TMR_DEVIDER < 256
    #define RTCC_DEVIDER    RTCC_DIV_256
    #define DV 8
#else
    #error
#endif


Ausgeführt wird hier der #error obwohl der CAST von 27.2 (float) nach 
int 27 ergibt. Eigentlich muss #elif TMR_DEVIDER < 32 ausgeführt werden.

Ändere ich es wie folgt:

#define TMR_TEST                27
#define TMR_DEVIDER             TMR_TEST

wird #elif TMR_DEVIDER < 32 ausgeführt.

Kann mir das jemand erklären?

Vielen Dank!

Gruß

Florian
Gast #4115133
Lesenswert?

Danke für die schnellen Antworten!

Wenn ich in der Main einen der defines in eine Variable schreiben lasse 
und diese dann über einen breakpoint anschaue, steht in der Variablen 
das erwartete Ergebnis. Ich lasse z.B. einen Wert berechnen wie:


#define ZEIT.     127
#define WERT      (1/(ZEIT/4000.0))

In der Main dann:

float Test;

While(1)
{
Test = WERT;
}

Dabei steht in Wert dann 35...


Schreibe ich aber:

#define WERT       ((int)(1/(ZEIT/4000.0)))

steht in Test 35.0.

Der Cast nach int muss also funktioniert haben.
.0 ist klar, weil Test ja Datentyp "float" ist. Ändere ich auch das auf 
int oder char steht in Test nur noch 35. Der Compiler bemängelt hier 
auch nichts. Wenn Test aber vom Typ int oder char ist und ich den Cast 
nach int beim define weglasse (also wieder 35.49 hinter WERT steht) 
bemängelt der Compiler eine unerwartete Zuweisung von float nach int 
(oder eben char).

Wenn ich jetzt aber annehme, dass der Cast nach int beim define 
funktioniert, dann ist mir völlig unklar, warum dann die if / elif 
Anweisungen nicht zum logischen Ergebnis führen. Die Vermutung liegt 
aber nahe, dass es durchaus mit dem Cast zu tun hat, weil wenn ich

#define WERT       35

schreibe stimmt auch das was beim if / elif passiert.

Ich verstehe ganz einfach den Unterschied zwischen

#define WERT       35

und

#define WERT       ((int)(1/(ZAHL/4000.0)))

nicht, weil sowohl im einen, als auch im anderen Fall der Wert der 
Variablen Test 35 ist. Für das if / elif nach dem define ist aber 
offensichtlich ein Unterschied vorhanden. Und den würde ich gerne 
kennen...


Vielen Dank

Gruß

Florian
Gast #4115146
Lesenswert?

Florian schrieb:
> Für das if / elif nach dem define ist aber
> offensichtlich ein Unterschied vorhanden. Und den würde ich gerne
> kennen...

du musst zwischen Präprozessor und Compiler unterscheiden.

cast macht nur der Compiler, das ifdef macht aber der Präprozessor. 
Damit sollte eigentlich klar sein, warum es nicht geht.
Gast #4116195
Lesenswert?

Vielen Dank!

Soweit verstehe ich das jetzt.

Die ganze if Geschichte kann der Präprozessor also nicht sinnvoll 
ausführen, weil die Berechnungen der defines noch nicht gemacht sind zu 
diesem Zeitpunkt.

Die einzige Lösung für den Fall wäre also, wenn ich die defines so lasse 
(mitsamt CAST) und die if Geschichte dann vom Controller einmalig am 
Anfang ausführen lasse. Z.B. in einer INIT-Funktion.


Aber was ich immer noch nicht verstehe ist, warum es mit dem alten 
Compiler unter MPLAB 8 so funktioniert hat? Ist der 
Präprozessor/Compiler in dieser Hinsicht also "schlechter" oder "dümmer" 
geworden? Der Vorteil war eben, ohne RAM oder Flash zu verbrauchen den 
kompletten INIT für einen Timer zu haben (und nicht alles selbst rechnen 
zu müssen).

Gruß

Florian
Persönliche Seite #4116278
Lesenswert?

Es dürfte genügen, das hier

#define TMR_TEST 27.2
#define TMR_DEVIDER ((int)TMR_TEST)

zu verkürzen und für TMR_TEST direkt einen ganzzahligen Wert zu 
verwenden, bzw. auf TMR_TEST zu verzichten und gleich den ganzzahligen 
TMR_DIVIDER* zu nutzen.

Warum muss "TMR_TEST" ein nichtganzzahliger Float-Wert sein?

*) Den Teiler schreibt man übrigens divider
Gast #4116355
Lesenswert?

Nochmal Danke für die Erklärungen und Ansätze!

der Code aus meinem 1. Post dient als Beispiel was die defines Betrifft 
um mein Problem vereinfacht darstellen zu können. (Bitte nicht 
steinigen!!)

Das ist die eigentliche Version:

#define INT_FREQ                (1/(Entprellzeit/4000.0))
#define INTER_CLOCK_CORR        35
#define CLK_EFF                 (OSC_CLK/4.0)
#define CLK_PERINTERRUPT        (CLK_EFF/INT_FREQ)
#define TMR_DEVIDER             ((int)(CLK_PERINTERRUPT/256))


#if TMR_DEVIDER < 1
    #define RTCC_DEVIDER    RTCC_DIV_1
    #define DV 0
#elif TMR_DEVIDER < 2
    #define RTCC_DEVIDER    RTCC_DIV_2
    #define DV 1
#elif TMR_DEVIDER < 4
    #define RTCC_DEVIDER    RTCC_DIV_4
    #define DV 2
#elif TMR_DEVIDER < 8
    #define RTCC_DEVIDER    RTCC_DIV_8
    #define DV 3
#elif TMR_DEVIDER < 16
    #define RTCC_DEVIDER    RTCC_DIV_16
    #define DV 4
#elif TMR_DEVIDER < 32
    #define RTCC_DEVIDER    RTCC_DIV_32
    #define DV 5
#elif TMR_DEVIDER < 64
    #define RTCC_DEVIDER    RTCC_DIV_64
    #define DV 6
#elif TMR_DEVIDER < 128
    #define RTCC_DEVIDER    RTCC_DIV_128
    #define DV 7
#elif TMR_DEVIDER < 256
    #define RTCC_DEVIDER    RTCC_DIV_256
    #define DV 8
#else
    #error CPU-Clock zu gering
#endif


#define REST (((int)(CLK_PERINTERRUPT/(1<<DV))) % 256)
#define RTCC_Preset (256- ( REST - (INTER_CLOCK_CORR/(1<<DV))))


Entprellzeit ist bei mir 127 (im Moment zum Probieren).

Der Gedanke ist mit dem Programm den Timer entsprechend aufzuziehen, so 
dass dieser dann in der gewünschten Zeit die Taster / Schalter 
entprellt. Und schön ausprobieren / einstellen (man will ja auch nicht 
zu lange warten) kann man das dann wenn man nur die Entprellzeit von 1 
bis 255 in ms angeben muss. Natürlich geht das auch wenn ich es einmalig 
den Controller berechnen lasse oder zumindest alles nach den defines den 
Controller machen lasse. Kostet aber halt wieder Flash und RAM. Und da 
das früher gut funktioniert hat, hätte ich halt gerne.... ;-)

Das sind übrigens Teile von accurateinterrupt.h die man im Netz findet. 
Verwendet habe ich die damals mit einem HI-Tech Compiler unter MPlab 8.

Danke für den Hinweis mit "DEVIDER" --> "DIVIDER". Ich habs schon 100x 
gelesen, mir ist es aber nie aufgefallen.

Gruß

Florian

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