Schwierigkeiten mit c macros

Gast #3258946
Lesenswert?

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
Lesenswert?

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 #3258967
Lesenswert?

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
Lesenswert?

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 #3259180
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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

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