Hallo zusammen,
die Überschrift sagt eigentlich schon alles: Welchen Datentyp haben
eigentlich die spezial function register, insbesondere für Ports?
In der iom32.h steht _SFR_IO8; gebe ich die Addressen mit printf("addr
= %i,%i\a",&DDRD,&PIND); auf einem Display aus ergibt sich 0x31,0x32 (im
Gegensatz zur Definition in der iom32.h mit:
1
#define PIND _SFR_IO8(0x10)
2
#define DDRD _SFR_IO8(0x11)
3
#define PORTD _SFR_IO8(0x12)
Kann ich eine Funktion/Präprozessormakro schreiben, die bei der Übergabe
des Ports (PORTx) automatisch die beiden passenden anderen Register
(PINx und DDRx) kennt? Und welchen Datentyp übergibt man
sinnvollerweise?
Viele Grüße
W.T.
OK, im Datenblatt werden alle Register zweimal mit jeweils 0x20 Offset
angegeben - und ich finde jetzt auch keins, wo PINx, DDRx und PORTx
nicht direkt hintereinanderliegen. Damit sollte es praktisch kein
Problem sein, nur einen Wert zu übergeben.
Nur irgendwie will es nicht gelingen, mit dem Adressoperator dort
hineinzuschreiben.
Was zu gehen scheint:
Nö, paßt schon. Das, was ich oben gepostet habe macht genau das, was ich
will. Ich hab's nur etwas erweitert:
1
#define DDR(PORT) (\
2
(&PORT==&PORTA) ? (DDRA) :\
3
( (&PORT==&PORTB) ? (DDRB) :\
4
( (&PORT==&PORTC) ? (DDRC) :\
5
( (&PORT==&PORTD) ? (DDRD) :\
6
0 ) ) )\
7
)
8
9
#define PIN(PORT) (\
10
(&PORT==&PORTA) ? (PINA) :\
11
( (&PORT==&PORTB) ? (PINB) :\
12
( (&PORT==&PORTC) ? (PINC) :\
13
( (&PORT==&PORTD) ? (PIND) :\
14
0 ) ) )\
15
)
Jetzt brauche ich pro Pin in die Pinbelegungstabelle nur noch zwei Werte
zu hinterlegen (NAME_PORT und NAME_Pin) und habe die Sachen für AVR und
ARM (NAME_GPIO und NAME_Pin) wieder komplett identisch.
Als static-inline-Funktion wäre mir noch etwas lieber gewesen als durch
Präprozessormagie, weil AtmelStudio dann mit dem Auto-Vervollständigen
sehr komfortabel ist, aber so ist es auch schon schön.
Vielen Dank für's Lesen
W.T.
Walter Tarpan schrieb:> OK, im Datenblatt werden alle Register zweimal mit jeweils 0x20 Offset> angegeben - und ich finde jetzt auch keins, wo PINx, DDRx und PORTx> nicht direkt hintereinanderliegen. Damit sollte es praktisch kein> Problem sein, nur einen Wert zu übergeben.
Beim ATMega 128 stimmt das fuer PORTF nicht
/* Input Pins, Port F */
#define PINF _SFR_IO8(0x00)
/* Data Register, Port F */
#define PORTF _SFR_MEM8(0x62)
/* Input Pins, Port G */
#define PING _SFR_MEM8(0x63)
Mit C geht es nicht, weil bei der gewünschten Schreibweise ja sonst nur
der Wert des Registers und nicht seine Adresse übergeben wird. Aus dem
Wert lässt sich aber normalerweise nicht auf die Adresse schließen ...
Bei Makros mit Parametern solltest Du bei der Definition übrigens
grundsätzlich Klammern um jeden Eingabewert machen. Ansonsten ist die
Auswertungsreihenfolge unter Umständen nicht das, was Du erwartest, da
das Makro ja praktisch nur eine Textersetung macht. Also besser:
1
#define SetBit(PORT, BIT) ((PORT) |= (BIT))
Und noch eine letzte Bemerkung: Der Name SetBit ist verwirrend, da das
Makro nicht nur ein Bit, sondern eine ganze Bitmaske setzt. Ich hätte
bei dem Namen eher diese Definition erwartet:
1
#define SetBit(PORT, BIT) ((PORT) |= 1 << (BIT))
Dein Makro wäre imo mit SetBits treffender benannt. Bzw. wenn man der
üblichen Konvention folgt, dass Makros in Großbuchstaben geschrieben
werden: SET_BITS.
Walter Tarpan schrieb:> und habe die Sachen für AVR und> ARM (NAME_GPIO und NAME_Pin) wieder komplett identisch.
ach, und wie machst du das dann mit den unterschiedlichen Zugriffsarten
bei ARM einschließlich dem ansonsten leistungsfähigen Bitbandung?
Ich verstehe nicht, warum du dir solche Mühen gibst, Zugriffe auf
Portbits in derartiger Weise vereinheitlichen zu wollen. Mit diesem
Bemühen blähst du deine Quellen nur derart auf, daß du irgendwann den
Überblick verloren hast.
Mein Ratschlag: mach dir echte funktionelle Unterprogramme. Beispiel:
void Motor_Ein(void);
void Relais_Aus(void);
und so weiter. Für deinen logischen Firmwareinhalt kannst du dich auf
solche lowlevel-Treiber verlassen und zum Umsetzen auf eine andere
Architektur brauchst du bloß diese lowlevel-Funktionen anzupassen. Das
ist wesentlich effektiver als ein unifizierter Ausdruck "SetBit(PORT,
BIT)".
W.S.