Forum: Compiler & IDEs Präprozessor verschachteln


von Thomas (Gast)


Lesenswert?

Hallo,

ich habe folgendes Problem mit dem AVR GCC Präprozessor:

Um einfacher auf die IO-Pins des ATMega64 zugreifen zu können habe ich 
mir folgende Präprozessordirektive geschrieben:
1
//Ausgänge auf "1" setzen:
2
  //==> output_high(F, 6);
3
#define output_high(Port, Nr)  PORT ##Port |= (1 << Nr)
4
//#define output_high(Port, Nr)  Port |= (1 << Nr)
5
6
//Ausgänge auf "0" setzen:
7
  //==> output_low(F, 2);
8
#define output_low(Port, Nr)  PORT ##Port &= ~(1 << Nr)
9
//#define output_low(Port, Nr)  Port &= ~(1 << Nr)
10
11
// Eingangspin einlesen:
12
  //==> Status = input_Pin(A,2);
13
#define input_Pin(Port, Nr)    PIN ##Port & (1 << Nr)
14
15
// DDR auf Eingang setzen:
16
  //==> easyDDR_in(F, 5); ==> DDRF &= ~(1 << 5);
17
#define easyDDR_in(Port, Nr)  DDR ##Port &= ~(1 << Nr)
18
19
// DDR auf Ausgang setzen:
20
  //==> easyDDR_out(F, 5); ==> DDRF |= (1 << 5);
21
#define easyDDR_out(Port, Nr)  DDR ##Port |= (1 << Nr)
Diese sind in einer Datei ausgelagert und werden im Main-file 
includiert.
Funktioniert auch einwandfrei, mit
1
 output_high(F,6)
wird PortF, Pin6 logisch 1.

Nun möchte aber auch für Ports einen Alias mittels #define festlegen.
Dazu habe ich eine neue .c-Datei angelegt, die ebenfalls in meinem 
Projekt includet wird. Zu Beginn dieser Datei steht
1
#ifndef _ADC121_PORT
2
  #define _ADC121_PORT  F
3
  #warning "_ADC121_PORT not defined, using default port F"
4
#endif

Dann folgt die Funktion
1
void Test
2
    {
3
    easyDDR_out(_ADC121_PORT, 4);

Leider führt dies zu folgender Ausgabe im "Build"-Fenster:
1
D:\AVR\Akkumanagement\..\libraries\Header-Files/ADC121S021.c:56: error: 'DDR_ADC121_PORT' undeclared (first use in this function)

Das "_ADC121_PORT" wird also vom Präprozessor nicht durch das "F" 
ersetzt.
Was mache ich falsch ???

Danke schonmal !!!!!

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Hinweise was schief get findest zu im i-File, also in der präprozessten 
Quelle.

Das häufigste Missverständnis ist, daß Makros wie Funktionen verwendet 
werden, wobei sie aber nur Textersetz machen. Und da kommt's eben auf 
die Reihenfolge an.

Solche Port-Makros können sehr praktisch sein, aber sie bedeuten auch 
eine Präprozessor- und Makro-Schlammschlacht.

Ich hab mir solche Makros gebastelt als ich mit AVRs anfing. Sie 
funktionieren zwar wie gewünscht und ich hab's praktisch in all meinen 
Projekten, aber ich weiß nicht ob ich das wieder so machen würde; eben 
wegen den komplexen, schwer durchschaubaren Makros.

Die Portzuweisungen für's jeweilige Projekt sind in ports.h:
1
#include <avr/io.h>
2
#include "avr-port-macros.h"
3
#include "avr-port-enum.h"
4
5
enum
6
{
7
    PORT_POWER    = PORTD_6,
8
    PORT_DREHTAST = PORTB_3, // MOSI
9
    PORT_DREHA    = PORTB_0,
10
    PORT_DREHB    = PORTD_7,
11
12
    PORT_DAC_CS = PORTD_2, // 0=Enable
13
    PORT_DAC_AB = PORTD_3, // 0=A, 1=B
14
    ...

Den Makro-Wahn findest du in avr-port-macros.h und avr-port-enum.h in
   Beitrag "Re: Idee für Optimierung? (Scope-Clock auf Speed)"

Wobei da noch die zusätzliche Komplexität behandelt wird, daß ein Port 
nur virtuell ist, d.h. nicht einem I/O-Pin entspricht sondern eine Pin 
an einem Port-Expander.

Die Makros gehen nicht von einer bestimmten Anordnung der Port-SFRs im 
I/O-Bereich aus.

Johann

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.