Forum: Compiler & IDEs C, Enums mit preprocessor


von mgiaco82 (Gast)


Lesenswert?

1
/*!
2
 \brief Enum for the Slave Select Numbers
3
 */
4
typedef enum {
5
  APP_DAC_SS_NOT_SET = 0, /*!<Slave Select not set */
6
  APP_DAC_SS_0 = 1, /*!<Slave Select for the 1 DAC8555 Device*/
7
  APP_DAC_SS_1 = 2, /*!<Slave Select for the 2 DAC8555 Device*/
8
  APP_DAC_SS_2 = 3, /*!<Slave Select for the 3 DAC8555 Device*/
9
  APP_DAC_SS_3 = 4  /*!<Slave Select for the 4 DAC8555 Device*/
10
} ssc_slave_select_number_t;
11
12
13
//i think the fastest solution for slave select handling
14
#define dac_slave_select(device) \
15
  if(device==DAC_SS_0) PIN_DAC_CS0 = BIT_CLR \
16
  if(device==DAC_SS_1) PIN_DAC_CS1 = BIT_CLR \
17
  if(device==DAC_SS_2) PIN_DAC_CS2 = BIT_CLR \
18
  if(device==DAC_SS_3) PIN_DAC_CS3 = BIT_CLR \
19
20
#define dac_slave_unselect(device) \
21
  if(device==DAC_SS_0) PIN_DAC_CS0 = BIT_SET \
22
  if(device==DAC_SS_1) PIN_DAC_CS1 = BIT_SET \
23
  if(device==DAC_SS_2) PIN_DAC_CS2 = BIT_SET \
24
  if(device==DAC_SS_3) PIN_DAC_CS3 = BIT_SET \

Aufruf:

Es gibt ein dac object. das hat beispielsweise einen member vom typ 
ssc_slave_select_number_t
und so würde ich es gerne aufrufen. Compiler mekert was ist falsch oder 
geht das gar nicht so

dac_slave_select(dac->ss_device_one);

I wollte keine Funktion machen bezüglich Geschwindigkeit.

danke mgiaco

von Karl H. (kbuchegg)


Lesenswert?

mgiaco82 wrote:

> Es gibt ein dac object. das hat beispielsweise einen member vom typ
> ssc_slave_select_number_t
> und so würde ich es gerne aufrufen. Compiler mekert

Dann solltest du dir die Fehlermeldung des Compilers mal genauer 
ansehen.


> was ist falsch oder

Mach doch einfach mal die Textersetzung, die der Präprozessor auch 
macht.

aus
1
int main()
2
{
3
 dac_slave_select(dac->ss_device_one);
4
}

wird so:
1
int main()
2
{
3
  if(dac->ss_device_one==DAC_SS_0) PIN_DAC_CS0 = BIT_CLR
4
  if(dac->ss_device_one==DAC_SS_1) PIN_DAC_CS1 = BIT_CLR
5
  if(dac->ss_device_one==DAC_SS_2) PIN_DAC_CS2 = BIT_CLR
6
  if(dac->ss_device_one==DAC_SS_3) PIN_DAC_CS3 = BIT_CLR;
7
}

Wo sind denn die Strichpunkte?

> I wollte keine Funktion machen bezüglich Geschwindigkeit.

Das Argument zieht nicht. Wenn du gcc benutzt, kannst du ihn zwingen, 
die Funktion zu inlinen und dann hast du genau denselben speed, wie 
durch die Makroexpansion. Nur ist alles wesentlich sicherer.

Das hab ich schon gerne, beim Funktionsaufruf jede Nanosekunde 
rausschinden, dass der Code aber inhärent ineffizient ist, wird komplett 
übersehen. Das dac->ss_device_one wird ja wohl kaum gleichzeitig 
DAC_SS_0 und DAC_SS_1 und  DAC_SS_2 und DAC_SS_3 sein.

->
1
int main()
2
{
3
  if(dac->ss_device_one==DAC_SS_0)
4
    PIN_DAC_CS0 = BIT_CLR;
5
  else if(dac->ss_device_one==DAC_SS_1)
6
    PIN_DAC_CS1 = BIT_CLR;
7
  else if(dac->ss_device_one==DAC_SS_2)
8
    PIN_DAC_CS2 = BIT_CLR;
9
  else if(dac->ss_device_one==DAC_SS_3)
10
    PIN_DAC_CS3 = BIT_CLR;
11
}

und schon hast du im Durchschnitt durch den Wegfall der nicht 
notwendigen Vergleiche mehr Zeit eingespart, als dir eine nicht 
stattfindender Funktionsaufruf bringen würde. Noch besser wär 
allerdings:
1
int main()
2
{
3
  switch( dac->ss_device_one )
4
  {
5
    case DAC_SS_0;
6
      PIN_DAC_CS0 = BIT_CLR;
7
      break;
8
9
    case DAC_SS_1:
10
      PIN_DAC_CS1 = BIT_CLR;
11
      break;
12
13
    case DAC_SS_2:
14
      PIN_DAC_CS2 = BIT_CLR;
15
      break;
16
17
    case DAC_SS_3:
18
      PIN_DAC_CS3 = BIT_CLR;
19
  }
20
}

Da deine DAC_SS_x Werte schön aufsteigend sind, kann hier der Compiler 
mal so richtig zeigen was er kann und eine Sprungtabelle aufbauen.

von Klaus W. (mfgkw)


Lesenswert?

also DIE Fehlermeldung kenne ich noch nicht: "was ist falsch oder geht 
das gar nicht so"

Ansonsten: Wenn dac kein Zeiger ist, dann vielleicht . statt -> nehmen?

von Johannes M. (johnny-m)


Lesenswert?

mgiaco82 wrote:
> C, Enums mit preprocessor
> [...]
> Es gibt ein dac object. das hat beispielsweise einen member vom typ
> ssc_slave_select_number_t
In C gibt es weder Objekte, noch Member. Bitte erzähl mal, was Du 
wirklich willst!

von Karl H. (kbuchegg)


Lesenswert?

Und dann könnte man auch mal untersuchen ob nicht.
1
volatile uint8_t* DacPin[] = { &PIN_DAC_CS0,
2
                               &PIN_DAC_CS1,
3
                               &PIN_DAC_CS2,
4
                               &PIN_DAC_CS3 }
5
6
int main()
7
{
8
  ...
9
  *DacPin[ dac->ss_device_one ] = BIT_CLR;
10
}

nicht alle anderen Varianten locker abhängt.

Fazit: Wieder mal auf Mikrooptimierung durch Makros geschaut und die 
algorithmischen Möglichkeiten völlig ausser acht gelassen. Dabei hätte 
man durch algorithmische Änderungen viel mehr rausholen können, als 
durch solche Mikrooptimierungen.

Nicht umsonst lautet die erste Regel der Optimierung: Don't do it
Die zweite lautet: Don't do it - yet.

von mgiaco (Gast)


Lesenswert?

Hallo Karlheinz,

Danke alles klar. Das dynamisch und wegoptimieren passt nicht zusammen. 
Habe es gerade selber gesehen. Ich mach ne gute alte switch case Lösung.

Hallo Johannes,

Und da bist du dir wirklich sicher? Hast du mal drüber nachgedacht das 
man in C alles machen kann und wie ist C entstanden ober Objective C.

Ich habe nicht gesagt das es in C Objekte gibt, aber man kann in C 
Objektorientiert Programmieren. Und dann kann man die Dinger die dann 
Member haben als Objekte bezeichnen wenn man gerne möchte.

Hier mal ein Beitrag wie ich das so mache, das hab ich mir von Quantum 
Leaps abgeschaut. siehe mein Beitrag
Beitrag "Kapselung in C"

Also bitte mal ganz sachlich bleiben.

Vielen Dank noch mal
mgiaco

von mgiaco (Gast)


Lesenswert?

@Karl heinz Buchegger du bist ech super drauf das ist ja wild. Du weist 
ja glaube ich alles.

danke :-)

von Karl H. (kbuchegg)


Lesenswert?

mgiaco wrote:

> Ich habe nicht gesagt das es in C Objekte gibt, aber man kann in C
> Objektorientiert Programmieren. Und dann kann man die Dinger die dann
> Member haben als Objekte bezeichnen wenn man gerne möchte.
>

Klar kann man das. Man kann auch in Assembler objektorientiert 
programmieren.

Entscheidend ist aber, welche Unterstützung dir die Sprache von sich aus 
dafür gibt und welchen Anteil an der Objektorientierung du nur duch 
konsequente Disziplin erreichen kannst.

Aber an dieser Stelle ist der Einwand, dass es in C keine Objekte und 
keine Member gibt wirklich nicht berechtigt.

Man kann mit Fug und Recht eine Instanz einer Struktur oder einer Union 
als ein Objekt ansehen. Und ein Element einer Struktur als Member. Ist 
im engl. Sprachgebrauch gang und gäbe, das so zu tun, auch wenn der 
Begriff Objekt im Zusammenhang mit objektorientierter Programmierung 
noch etwas weiter gefasst wird.

von Johannes M. (johnny-m)


Lesenswert?

Karl heinz Buchegger wrote:
> Aber an dieser Stelle ist der Einwand, dass es in C keine Objekte und
> keine Member gibt wirklich nicht berechtigt.
Wenn Du das sagst, dann gebe ich mich geschlagen...

von Karl H. (kbuchegg)


Lesenswert?

mgiaco wrote:
> @Karl heinz Buchegger du bist ech super drauf das ist ja wild. Du weist
> ja glaube ich alles.

Nicht wirklich.
Meine Grenzen liegen bei C++ Templates. Da steig ich bei so manchen 
wilden Konstruktionen aus. Ist für mich aber nicht so wichtig als dass 
ich mir da Sorgen machen würde.

(Und die Neuerungen in C99 sind auch ein wenig an mir vorbei gegangen. 
Bin aber dabei, mein Gedächtnis auf diese Neuerungen umzukonditionieren. 
Ist halt nicht einfach, umzuschalten, wenn man ein bestimmtes Problem 20 
Jahre lang nach einem gut funktionierenden Muster gelöst hat und 
plötzlich eröffnet sich mit einer Sprachänderung eine elegantere 
Möglichkeit. Das muss erst mal ins Hirn hinein, sodass der schnelle 
Gedächtnis-Abruf das neue Muster benutzt und nicht weiterhin mit den 
alten Kamellen hochkommt.)

von mgiaco (Gast)


Lesenswert?

Hm das wäre ja super aber, Problem:

hinter PIN_DAC_CS0 steht sbit usw. Keil Compiler.

Gibts da auch noch einen Trick ?

volatile uint8_t* DacPin[] = { &PIN_DAC_CS0,
                               &PIN_DAC_CS1,
                               &PIN_DAC_CS2,
                               &PIN_DAC_CS3 }

danke

von Karl H. (kbuchegg)


Lesenswert?

mgiaco wrote:
> Hm das wäre ja super aber, Problem:
>
> hinter PIN_DAC_CS0 steht sbit usw. Keil Compiler.

OK. Das wusste ich so nicht.
Zeig mal die Makros.

>
> Gibts da auch noch einen Trick ?

Wie sagte schon Monaco-Franze:
"A bissl wos geht imma!"

von mgiaco (Gast)


Lesenswert?

#define PIN_DAC_CS0 P3_P2 /*!<CS0 pin of external D/A converter*/

und P3_2 ist dann ==> sbit P3_P2 = P3^2;

von Karl H. (kbuchegg)


Lesenswert?

> und P3_2 ist dann ==> sbit P3_P2 = P3^2;

Der Schritt ist mir noch nicht klar. Vor allem wie da jetzt das sbit ins 
Spiel kommt.

Kannst du mal den #define für P3_P2 in seiner vollen Pracht zeigen?

Wie ist sbit definiert? Ist das selbst wieder ein Makro?


   PIN_DAC_CS0 = BIT_CLR;
würde dann ja zu

   P3^2 = BIT_CLR;

Das ist aber kein gültiges Standard-C (was nicht heisst, das Keil da was 
erfunden haben könnte).

(BIT_CLR ist das einfach eine 0?)

(Mein Ziel ist es zu verstehen, welcher C-Code letztendlich bei

   PIN_DAC_CS0 = BIT_CLR;

rauskommt, wenn alle Makros aufgelöst wurden. Dort identifizieren wir 
dann, welche Teile variabel sein müssen und arbeiten das dann wieder 
zurück (mglw. mit Makros) auf genehmen, schönen C-Code.

von mgiaco (Gast)


Lesenswert?

ja P3^2 = 0 ist dann das was übrig ist. Was das P3^2 genau macht kann 
weis ich nicht. Der Rest macht der Compiler.

von Karl H. (kbuchegg)


Lesenswert?

mgiaco wrote:
> ja P3^2 = 0 ist dann das was übrig ist. Was das P3^2 genau macht kann
> weis ich nicht. Der Rest macht der Compiler.

OK. (Da musst du mir jetzt ein wenig helfen, ich hab keinen Keil 
Compiler hier)

P3 dürfte wohl der Port Nummer 3 sein und die 2 stehen für den Pin an 
diesem Port.

Ist es möglich, die 2 variabel zu gestalten?
Also sowas in der Art

   P3^PinNr = 0;

wobei PinNr sagen wir mal ein unsigned char ist
1
int main()
2
{
3
  unsigned char PinNr = 2;
4
5
  P3^PinNr = 0;
6
}

(Wenn das klappt, haben wir schon einen Fuss in der Tür.
 Das gewünschte C-Ergebnis würde dann lauten


   unsigned char PinNr[] = { 2, 3, 4, 5 };    // Pins des DAC

   P3^PinNr[dac->ss_device_one] = BIT_CLR;

Die Frage ist an dieser Stelle nur: Sind an dieser Stelle beim ^ nur 
Konstante erlaubt oder können das auch Variablen bzw. Ausdrücke sein.
Die Pin Nummern im Array könnte man noch hinter ein paar Makros 
verstecken, aber im Grunde wärs das dann

Wenn das nicht geht:
Wie setzt du einen Port komplett auf einen Wert (also alle 8 Bit)
   P3 = 0xFF;

Da könnte man auch noch einen Hebel ansetzen.

von mgiaco (Gast)


Lesenswert?

Nö das geht nicht habs probiert. Konstanten kann man da nicht verwenden.

von mgiaco (Gast)


Lesenswert?

> Wenn das nicht geht:
> Wie setzt du einen Port komplett auf einen Wert (also alle 8 Bit)
> P3 = 0xFF;
> Da könnte man auch noch einen Hebel ansetzen.

Ja so kann ich den Port natürlich auch setzten.

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.