Hallo, ich habe ein #define PINconf_SPI1_MISO 0x24 was heißt das SPI1 an Port B Pin 4 hängt. Jetzt möchte ich die Information im Programm nutzen und z.B PIN_SPI1_MISO und PORT_SPI1_MISO verwenden. Ich habe in einem Zentralen .h File alle PINconf* definiert, allerdings möchte ich jetzt nicht bei allen Pins ein extra define für Port und Pin machen. Deswegen wollte ich das Problem so lösen: DECLARE_PIN(SPI1_MISO, 0x24) #define DECLARE_PIN(name,conf) { \ #define PIN_##name conf && msk_GPIO_PIN\ #define PORT_##name conf && msk_GPIO_PORT\ } Dieser Ansatz verursacht diesen Fehler: error: '#' is not followed by a macro parameter ich habe dann gelesen, dass man in defines keine defines machen kann, deswegen frage ich euch nach einem anderen Ansatz für mein Problem. Habt ihr eine ander Idee? PS: Ich programmiere einen Cortex M0 mit CoIDE
mit glue geht das:
1 | |
2 | #define GLUE(a, b) a##b
|
3 | #define PORT(x) GLUE(PORT, x)
|
4 | #define PIN(x) GLUE(PIN, x)
|
5 | #define DDR(x) GLUE(DDR, x)
|
6 | #define sbi(var, bit) (var|=1<<bit)//set
|
7 | #define cbi(var, bit) (var&=~(1<<bit))//clear
|
8 | #define tbi(var, bit) (var^=1<<bit)//toggle
|
9 | #define gbi(var, bit) (var>>bit&1)//get
|
10 | #define wait _delay_ms(1000)
|
11 | #define wait10 {_delay_ms(3333);_delay_ms(3333);_delay_ms(3333);}
|
12 | #define u8 uint8_t
|
13 | #define u16 uint16_t
|
14 | #define u32 uint32_t
|
15 | #define v volatile
|
16 | ...
|
17 | #define pinSET(x,y) PORT(x) |=(1<<y)
|
18 | #define pinCLR(x,y) PORT(x)&=~(1<<y)
|
19 | #define pinTOG(x,y) PORT(x)^=(1<<y)
|
20 | |
21 | #define pinDIRin(x,y) DDR(x)&=~(1<<y)
|
22 | #define pinDIRout(x,y) DDR(x)|=(1<<y)
|
23 | //#define pinDIRaf(x,y) GPIO(x)->MODER |= (2<<(y*2))//
|
24 | #define pinVAL(x,y) (PIN(x)&(1<<y))
|
25 | //#define pinSPEED(x,y) GPIO(x)->OSPEEDR|=(GPIO_Speed_50MHz<<(y*2))//2=>50
|
26 | #define pinPULLUP(x,y,z) PORT(x)|=(1<<y)//0_no 1_up
|
Makros sind ein Relikt aus (Makro-)Assemblern, die es nach C geschafft haben. Man sollte sie einfach ganz weglassen. Du kannst beliebige Datenstrukturen als Konstanten definieren:
1 | struct Pin { |
2 | uint8_t port; |
3 | uint8_t pin; |
4 | };
|
5 | |
6 | static const Pin SPI1_MISO { 3, 4 }; // Port 3, Pin 3 |
Franz F. schrieb: > #define DECLARE_PIN(name,conf) { \ > #define PIN_##name conf && msk_GPIO_PIN\ > #define PORT_##name conf && msk_GPIO_PORT\ Geht nicht.
Dr. Sommer schrieb: > Makros sind ein Relikt aus (Makro-)Assemblern, die es nach C geschafft > haben. Man sollte sie einfach ganz weglassen. Du kannst beliebige > Datenstrukturen als Konstanten definieren: >
1 | struct Pin { |
2 | > uint8_t port; |
3 | > uint8_t pin; |
4 | > }; |
5 | >
|
6 | > static const Pin SPI1_MISO { 3, 4 }; // Port 3, Pin 3 |
Hallo, wenn ich aber soetwas machen möchte muss ich immer 8 bit werte verwenden. Ich wollte es ungefähr so machen.
1 | #define msk_GPIO_PIN 0b0000000000001111 //GPIO_Pin_0...15
|
2 | #define msk_GPIO_PORT 0b0000000011110000 //GPIO_Port A...P
|
3 | #define msk_GPIO_PuPd 0b0000001100000000 //00 No Pull
|
4 | //01 Pulldown
|
5 | //10 Pullup
|
6 | #define msk_GPIO_Speed 0b0000110000000000 //00 GPIO_Speed_Level_1
|
7 | //01 GPIO_Speed_Level_2
|
8 | //10 GPIO_Speed_Level_3
|
9 | #define msk_GPIO_OType 0b0001000000000000 //0 Push Pull
|
10 | //1 Open Drain
|
11 | #define msk_GPIO_Mode 0b0110000000000000 //00 Input
|
12 | //01 Output
|
13 | //10 Analog
|
14 | //11 Alternate Function
|
15 | #define msk_GPIO_Def_Out 0b1000000000000000 //Default state in Output
|
Deswegen würde es sich anbieten im Präprozessor die Port und Pin als eigene Defines zu definieren.
Franz F. schrieb: > wenn ich aber soetwas machen möchte muss ich immer 8 bit werte > verwenden. Hä, wieso das? Du kannst natürlich auch uint16_t und uint64_t oder was auch immer verwenden... Franz F. schrieb: > Deswegen würde es sich anbieten im Präprozessor die Port und Pin als > eigene Defines zu definieren. Voll kompliziert. Mach lieber ein Struct mit Portnummer, Pin-Nummer, PuPd-Wert, Speed-Wert etc. Dann machst du dir eine Init-Funktion, die diesen struct entgegennimmt und den Pin entsprechend initialisiert.
Also bei avr-gcc mach ich das so:
1 | #define FOO A,2
|
2 | #define BAR A,3
|
3 | #define BAZ B,0
|
4 | |
5 | |
6 | // helper macros
|
7 | #define _SET(type,name,bit) type##name |= _BV(bit)
|
8 | #define _CLR(type,name,bit) type##name &= ~_BV(bit)
|
9 | #define _GET(type,name,bit) (type##name & _BV(bit))
|
10 | |
11 | // use these macros in the application
|
12 | #define SET_AS_OUTPUT(pin) _SET(DDR,pin)
|
13 | #define SET_AS_INPUT(pin) _CLR(DDR,pin)
|
14 | #define SET_HIGH(pin) _SET(PORT,pin)
|
15 | #define SET_LOW(pin) _CLR(PORT,pin)
|
16 | #define TOGGLE(pin) _SET(PIN,pin)
|
17 | #define IS_HIGH(pin) _GET(PIN,pin)
|
18 | |
19 | |
20 | |
21 | [...]
|
22 | |
23 | |
24 | int main(void) { |
25 | SET_AS_OUTPUT(FOO); |
26 | SET_AS_OUTPUT(BAR); |
27 | |
28 | SET_HIGH(FOO); |
29 | |
30 | [...]
|
Der gcc schluckt das anstandslos. Vielleicht kannst Du dieses Verfahren sinngemäß anpassen und anwenden. Der Trick besteht einfach im Umweg über die Helper-Macros und der Textersetzung die bei der Auflösung der Makros stattfindet und aus dem "scheinbar" nur einem Parameter und dem geschickt eingesetzten Komma "automagisch" wieder zwei Parameter macht.
Bernd K. schrieb: > #define _SET(type,name,bit) type##name |= _BV(bit) Hallo, das "##" ist ja nicht das Problem. Der Präprozessor kann anscheinend keine defines in makros ausführen: http://stackoverflow.com/questions/1135822/escaping-a-symbol-in-a-define-macro
Franz F. schrieb: > Der Präprozessor kann anscheinend keine defines in makros ausführen: So ist es. Und das war schon immer so. Weshalb dir Bernd eine Alternative zu deinem Ansatz präsentierte.
:
Bearbeitet durch User
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.