Schwierigkeiten mit c macros

Gast #3258946
Sebastian W. schrieb:
> Was du möchtest geht nicht, weil der Preprozessor den Inhalt von
> Variablen nicht kennt.

Vielen dank Sebastian für die Info. :)


Gibt es sonst eine Möglichkeit, so etwas zu machen wenn auch nicht mit 
defines? Ich möchte, dass der Benutzer in einem vorgegebenen Datei 
einfach schreiben kann:

  Init.Port = "A";
  Init.Pin  = "A5";

und ich dann an diversen Stellen in meinem Program einfügen kann:

  DDR + Init.Port |= (1<<Init.Pin); <-- also das soll dann bedeuten DDRA 
|= (1<<A5);


Wie macht man sowas? :)
Gast #3258952
du schreibst dir ein programm welches dann aus der config datei aus 
Init.Port = "A" ein #define INIT_PORT A macht und in code wird nicht 
Init.Port sondernINIT_PORT verwendet...

das programm wird im make prozess mit eingebunden und wird für dem 
compile porzess ausgeführt

So etwas "ähnliches" machen wir hier, da die debugg messages im Code 
nicht ins Flash gehen werden diese mit ID's versehene. Vorm Compilieren 
werden alle Texte in einer Datenbank hinterlegt mit einer ID und das 
Programm fügt im Text Macro die ID ein wenn noch nicht vergeben. und 
dann wird kompilert. für die Betrachtung auf der Konsole braucht man 
natürlich eine eigene Konsole die die IDs wieder in Strings verwandelt.

Grüße
Gast #3258966
lange weg schrieb:
> du schreibst dir ein programm welches dann aus der config datei aus
> Init.Port = "A" ein #define INIT_PORT A macht

Hmm. Wie würde das konkret aussehen? So vll.:
1
switch (Init.Port)
2
{
3
    catch A:
4
         #define INIT_PORT  A
5
    break;
6
    ...
7
}
Gast #3258967
In den Anwender-Parameter-header kommt das hier:
1
#define INITPORT A
2
#define INITPIN 5

In deinen header dann das hier:
1
#define CONCAT2(a,b) a##b
2
#define CONCAT(a,b) CONCAT2(a,b)
3

4
#define INIT_PORT CONCAT(PORT, INITPORT)
5
#define INIT_DDR CONCAT(DDR, INITPORT)
6
#define INIT_PIN_PRE CONCAT(P, INITPORT)
7
#define INIT_PIN CONCAT(INIT_PIN_PRE, INITPIN)

Da PAx, PINx, PBx, usw. bei allen bekannten AVRs immer gleich x sind, 
braucht es INIT_PIN eigentlich nicht, da kann man gleich INITPIN 
verwenden.

Also so:
1
 INIT_DDR |= (1<<INIT_PIN);

oder gleich so:
1
 INIT_DDR |= (1<<INITPIN);

Oliver
Gast #3258972
Nachtrag:

INITPIN als Bezeichner für die Pinnummer ist in meinem obigen Beispiel 
blöd gewählt, da du ja auch noch das PIN-Register des Ports ansprechen 
können wollen willst ;)

Ber das kriegst du schon selber hin.

Oliver
Gast #3259012
Oliver schrieb:
> #define CONCAT2(a,b) a##b
> #define CONCAT(a,b) CONCAT2(a,b)

Noch eine kurze Frage. Wieso reicht das nicht aus:

#define CONCAT(a,b) a##b

Was ist der Sinn von CONCAT2?



lange weg schrieb:
> da wirst einen parser brauchen, nimmst z.b. java mit config files gehts
> rel. simple da brauchst nur über alle drüber iterieren...

Hm oki. Danke :)
Gast #3259180
Oliver schrieb:
> #define INITPORT A
> #define INITPIN 5

Gibt es eine Möglichkeit, das ganze ohne defines mittels eines 
Funktionsaufrufs zu machen?
1
Init(int Port, int Pin)
2
{
3
   DDR + Port |=  (1<<Pin);    <--- das soll sein:  DDRA |= ....  
4
   ...
5

6
}


Ich hoffe ihr versteht was ich meine. :)
Gast #3259902
macro schrieb:
> Ich hoffe ihr versteht was ich meine.

Nein.

Ansonsten halte ich es mit Leuten, die sich im Konstruieren von Macros 
ergehen, so ähnlich wie Osmin: Erst geköpft und dann gehangen, dann 
gespießt auf heiße Stangen, dann..... naja.

Kurzum, Macros sind ein elendiger Mist, den man besser bleiben lassen 
sollte. Wer auf solche Ideen kommt, täte besser daran, seine Algorithmen 
gründlich zu überdenken.

W.S.
Gast #3260692
W.S. schrieb:
> Kurzum, Macros sind ein elendiger Mist, den man besser bleiben lassen
> sollte.

Hi W.S. Deshalb auch meine Frage, ob man macros umgehen kann und vom 
user ausgewählte Ports und pins in Init.Port und Init.Pin ablegen kann. 
Und zwar so ablegen, dass man an vielen Stellen im Quellcode mit DDRx, 
PORTx usw. ansprechen kann.  "Lange weg" hat zwar eine Möglichkeit 
aufgezeigt, aber vielleicht gibt es da auch was einfacheres.


gruß
macro
#3261213
macro schrieb:
> Gibt es eine Möglichkeit, das ganze ohne defines mittels eines
> Funktionsaufrufs zu machen?
>
>
1
> Init(int Port, int Pin)
2
> {
3
>    DDR + Port |=  (1<<Pin);    <--- das soll sein:  DDRA |= ....
4
>    ...
5
> 
6
> }
7
>

Das ginge zur Laufzeit vielleicht so (ist aber nicht genau so effizient 
wie eine Definition zur Compilezeit):
1
volatile uint8_t* WhichIo (char* ioname) {
2
    if (!strcmp(ioname,"DDRA")) return &DDRA;
3
    else if (!strcmp(ioname,"DDRB")) return &DDRB;
4
    else if (!strcmp(ioname,"PORTA")) return &PORTA;
5
    else if (!strcmp(ioname,"PORTB")) return &PORTB;
6
    ...
7
    else return 0;
8
}
9

10
void Init (volatile uint8_t* Ddr, int Pin) {
11
    *Ddr |= 1<<Pin;
12
}
13

14
void ExplicitExample () {
15
    Init(WhichIo("DDRA"),5);
16
    volatile uint8_t* port = WhichIo("PORTA");
17
    *port |= 1<<5;
18
    *port &= ~(1<<5);
19
}
20

21
void ConfigExample () {
22
    char* portname = ReadConfigString("OUTPUTPORT");
23
    char* ddrname = ReadConfigString("OUTPUTDDR");
24
    volatile uint8_t* port = WhichIo(portname);
25
    int pin = ReadConfigInt("OUTPUTPIN");
26
    Init(WhichIo(ddrname),pin);
27
    *port |= 1<<pin;
28
    *port &= ~(1<<pin);
29
}

LG, Sebastian
Gast #3261472
macro schrieb:
> und vom
> user ausgewählte Ports und pins in

Hehe.. der User bist doch du selber!
Ich halte es für keine gute Idee, immerzu zwischen "User" und "Ich hier" 
unterscheiden zu wollen. Ich weiß zwar nicht, was du im konkreten Falle 
mit diesem Init.Port usw. bezwecken willst, aber so etwas überhaupt 
anzudenken, ist wirklich falsch. Bedenke doch bitte, daß ein µC immer in 
eine bestimmte Schaltung eingelötet wird und daß er deshalb 
selbstverständlich gerade an seinen Portpins genau so programmiert 
werden muß, wie es die umgebende Schaltung erfordert. Oder willst du 
gelegentlich gegeneinander ankämpfende Output-Pins erzeugen?

Also, schreib dir die Treiberroutinen einfach so, wie es die benutzte 
Peripherie erfordert und halte die zugehörige Headerdatei frei von 
triberinternem Zeugs. Dort sollten nur die Nutzaufrufe stehen, die man 
vom Rest der Firmware aus benötigt, um über den Treiber mit der Hardware 
und damit mit der Außenwelt zu kommunizieren. Dazu braucht man keine 
Macros.

W.S.
#3261489
W.S. schrieb:
> macro schrieb:
>> Ich hoffe ihr versteht was ich meine.
>
> Nein.
>
> Ansonsten halte ich es mit Leuten, die sich im Konstruieren von Macros
> ergehen, so ähnlich wie Osmin: Erst geköpft und dann gehangen, dann
> gespießt auf heiße Stangen, dann..... naja.
>
> Kurzum, Macros sind ein elendiger Mist, den man besser bleiben lassen
> sollte. Wer auf solche Ideen kommt, täte besser daran, seine Algorithmen
> gründlich zu überdenken.
>
> W.S.

Zitat Dieter Nuhr: "Wer keine Ahnung hat....."

Komisch, daß son Müll immer nur anonym gepostet wird.

Makros sind eine hervorragende Möglichkeit, bestimmte Konstrukte lesbar 
zu halten, und trotzdem das Zielsystem nicht mit unnötigen Berechnungen 
zu belasten.
Ausserdem helfen sie Code portabel zu halten
Wenn du W.S. die Funktion von Makros nicht verstehst, und damit nicht 
umgehen kannst, dann lern es, oder halt die Klappe, aber verbreite nicht 
son Blödsinn, und verunsicher nicht die Leute, die ernsthaft 
programmieren lernen wollen!

Antwort schreiben

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