Datum:
Hallo,
ich bin kein Softwerker und irgendwie zu doof...
...folgenden Code habe ich zusammengestrickt bekommen (und der tut):
void WriteAdress(char ADDRESS, char DATA, char SR)
{
char *address_ptr; // adress pointer
address_ptr = (char *) ADDRESS;
switch(SR)
{
case 0:
*address_ptr &= ~DATA;
break;
case 1:
*address_ptr |= DATA;
break;
case 2:
*address_ptr = DATA;
break;
}
}
Aufruf mit:
WriteAdress(ADDBASE + BASEOFFSET + X, DATA, SELECT);
--------------------------------------------------------
Nun meine Frage:
Wie kann ich das durch einfache, universelle Macros ersetzen?
Ziel: Direktes Schreiben von Registern inkl. Offset, damit nicht P1OUT,
P2OUT, P1DIR, P1IE etc. verwendet werden müssen.
Also sinngemäß:
#define REG_SETBITS(ADDRESS,DATA) ????????
#define REG_CLEARBITS(ADDRESS,DATA) ????????
Datum:
Tonmeister schrieb: > Ziel: Direktes Schreiben von Registern inkl. Offset, damit nicht P1OUT, > P2OUT, P1DIR, P1IE etc. verwendet werden müssen. > > Also sinngemäß: > > #define REG_SETBITS(ADDRESS,DATA) ???????? > #define REG_CLEARBITS(ADDRESS,DATA) ???????? Ist das jetzt eine Fangfrage? Hol dir aus deiner Funktion den Teil raus, der beim direkten Setzen ausgeführt wird. Was bleibt übrig? Und daraus ergibt sich dann: #define REG_SETBITS( ADRESS, DATA ) *(unsigned char*)(ADRESS) = (DATA) (du solltest wirklich unsigned char nehmen, wenn du mit Bytes hantierst, und nicht char) > damit nicht P1OUT, P2OUT, P1DIR, P1IE etc. verwendet werden müssen. Was stört dich daran? Besser lesbar ist das auch nicht, wenn du das durch die jeweiligen Adressen in Zahlenform ersetzt. Dafür ist es fehleranfälliger.
Datum:
Danke! ...und das war keine Fangfrage! Das Problem ist immer wieder die Syntax! Was will der Compiler sehen, damit er das tut, was ich von ihm will? Ich bastele eben nur in meiner Freizeit ein bißchen mit den MSPs rum und kann eigentlich gar nicht programmieren! P.S.: Kennt jemand eine gute Übersicht (max. einige Seiten DIN A4), wo alle (wichtigen) Befehle und dazugehörigen Syntaxen übersichtlich dargestellt sind? (z.B. wie die PerlRefCard) P.S.2: Ich hasse Pointer!
Datum:
>> damit nicht P1OUT, P2OUT, P1DIR, P1IE etc. verwendet werden müssen. >Was stört dich daran? >Besser lesbar ist das auch nicht, wenn du das durch die jeweiligen >Adressen in Zahlenform ersetzt. Dafür ist es fehleranfälliger. Mein aktuelles Projekt sind kapazitive Taster/Slider. Hierzu sind 8 Caps auf zwei Portbänken angebunden. Je nach Layout kann das beim nächsten Projekt wieder anders verschaltet sein. Ich habe durch das direkte Schreiben der Register EINE Funktion, die immer funktioniert, egal, an welche Ports ich die Caps angeschlossen habe und die auch in weiteren Projekten ohne Veränderung verwendet werden kann. Ich kann jetzt einfach: MeasureCapPair(C1, C1OFFSET, C2, C2OFFSET); MeasureCapPair(C2, C2OFFSET, C1, C1OFFSET); schreiben und mit dem OFFSET einstellen, auf welcher PortBank die Caps liegen. So die Idee. Wenn jemand elegantere Lösungen hat: Immer her damit! :)
Datum:
Tonmeister schrieb: > P.S.: Kennt jemand eine gute Übersicht (max. einige Seiten DIN A4), wo > alle (wichtigen) Befehle und dazugehörigen Syntaxen übersichtlich > dargestellt sind? (z.B. wie die PerlRefCard) Wenn wir schon dabei sind. Kennt jemand eine gute Übersicht (max ein paar Seiten DIN A4), die ich nur lesen muss und dann kann ich fliessend Japanisch?
Datum:
Karl Heinz Buchegger schrieb: > Tonmeister schrieb: > >> P.S.: Kennt jemand eine gute Übersicht (max. einige Seiten DIN A4), wo >> alle (wichtigen) Befehle und dazugehörigen Syntaxen übersichtlich >> dargestellt sind? (z.B. wie die PerlRefCard) > > Wenn wir schon dabei sind. > Kennt jemand eine gute Übersicht (max ein paar Seiten DIN A4), die ich > nur lesen muss und dann kann ich fliessend Japanisch? FALSCH! Wenn schon, dann muß es: Kennt jemand eine gute Übersicht (max ein paar Seiten DIN A4), die ich nur lesen muss und dann kann ich japanische Grammtik? Du BIST Softwerker, stimmts? ;)
Datum:
Nutze einfach #define und bedingte Compilierung
#ifdef (PORT_P1) #define P1OUT PORT_OUT #define P1DIR PORT_DIR ... #endif #ifdef (PORT_P2) #define P2OUT PORT_OUT #define P2DIR PORT_DIR ... #endif int main (void) { ... PORT_OUT = BIT1; ... } |
Datum:
Tonmeister schrieb: > Kennt jemand eine gute Übersicht (max ein paar Seiten DIN A4), die ich > nur lesen muss und dann kann ich japanische Grammtik? Was hilft dir die Grammatik, wenn du sie nicht anwenden kannst. Ein Pointer schreibt sich in der Deklaration mit einem * zwischen Datentyp und Variablennamen. Beispiel: int * myPointer; Ein Pointer wird dereferenziert, indem man in der Verwendung einer Expression, die den Datentyp 'Adresse von Datentyp T' hat, einen * voranstellt. Beispiel: i = *myPointer; Das ist alles, was es an Grammatik zu Pointern zu sagen gibt. (Na, ja fast alles. Pointerarithmetik müsste man noch auf Grammatikebene definieren und ein paar Details hab ich wahrscheinlich ausgelassen). Bist du deswegen perfekt im Umgang mit Pointern?
Datum:
#define schrieb: > Nutze einfach #define und bedingte Compilierung >
> #ifdef (PORT_P1) > #define P1OUT PORT_OUT > #define P1DIR PORT_DIR > ... > #endif > #ifdef (PORT_P2) > #define P2OUT PORT_OUT > #define P2DIR PORT_DIR > ... > #endif > > int main (void) { > ... > PORT_OUT = BIT1; > ... > } > |
Mmmmh... ...das habe ich noch nicht ganz verstanden. Wenn ich z.B. 3 Caps auf PB1 habe und 5 auf PB2 und beim nächsten Projekt 6 auf PB1 und 2 auf PB2, wie kann ich dann mit der bedingten Compilierung dafür sorgen, daß ich die CapSense-Funktion nicht ändern muß? Jetzt schreibe ich im Header: #define Cx BITx #define CxOFFSET OFFSET und die Funktion muß nicht geändert werden. Ich habe ja meist Caps auf beiden PB's (oder möchte in Zukunft mehr als 8 Caps einsetzen)... ...und noch mal ne ganz andere Frage: Ich habe jetzt die eine ursprüngliche Implementierung mit Funktion und die neue mit Macro. Welche Implementierung ist den schneller und/oder speichersparender?
Datum:
Tonmeister schrieb: > Ziel: Direktes Schreiben von Registern inkl. Offset, damit nicht P1OUT, > P2OUT, P1DIR, P1IE etc. verwendet werden müssen. Was ist ein Offset beim Port, meinst Du damit ein einzelnes Bit?
Datum:
http://gcc.gnu.org/onlinedocs/cpp/Macros.html Da steht eigentlich alles zu Macros was man so wissen muss (gcc spezifisch, aber das meiste ist standardisiert)
Datum:
asdf schrieb: > http://gcc.gnu.org/onlinedocs/cpp/Macros.html > Da steht eigentlich alles zu Macros was man so wissen muss (gcc > spezifisch, aber das meiste ist standardisiert) SOWAS habe ich gesucht! (aber irgendwie über Google nicht gefunden)
Datum:
#define schrieb: > Tonmeister schrieb: >> Ziel: Direktes Schreiben von Registern inkl. Offset, damit nicht P1OUT, >> P2OUT, P1DIR, P1IE etc. verwendet werden müssen. > > Was ist ein Offset beim Port, meinst Du damit ein einzelnes Bit? Nein.
// set port direction to output (PxDIR)
REG_SETBITS(ADDBASE + CaOffset + 2,Ca);
REG_SETBITS(ADDBASE + CbOffset + 2,Cb);
// set ports to GND (PxOUT)
REG_CLEARBITS(ADDBASE + CaOffset + 1,Ca);
REG_CLEARBITS(ADDBASE + CbOffset + 1,Cb);
|
Hier mal ein Codeschnipsel (...und jetzt schon mit Macros!! ;)) Es kann also Ca an PB1 sitzen und Cb an PB2 oder beim nächsten Projekt beide an PB1 und trotzdem kann ich PxDIR, PxOUT,PxIE etc. in einer Funktion konfigurieren. Ganz grundsätzlich wollte ich einfach direkt in ein Register schreiben und mit Address-Offsets arbeiten, wußte aber die Syntax nicht und war zu doof, sie herauszufinden.
Datum:
Tonmeister schrieb: > Ganz grundsätzlich wollte ich einfach direkt in ein Register schreiben > und mit Address-Offsets arbeiten Ich verstehe Deine Aufgabenstellung immer noch nicht. Du zeigst die Aufrufe Deiner Makros. Könntest Du eine Makrodefinition einstellen? Was ist ADDBASE? Was ist CxOffset? Wie wird Cx deklariert? Bitte lass mich nicht unwissend sterben.
Datum:
#derfine schrieb: > Tonmeister schrieb: >> Ganz grundsätzlich wollte ich einfach direkt in ein Register schreiben >> und mit Address-Offsets arbeiten > > Ich verstehe Deine Aufgabenstellung immer noch nicht. Du zeigst die > Aufrufe Deiner Makros. Könntest Du eine Makrodefinition einstellen? > Was ist ADDBASE? Was ist CxOffset? Wie wird Cx deklariert? > > Bitte lass mich nicht unwissend sterben. ADDBASE = 0x0020, also Register P1IN Header-Schnipsel: . . #define REG_SETBITS(ADDRESS, DATA) *(unsigned char*)(ADDRESS) |= (DATA) #define C1 BIT3 #define C2 BIT2 . . ...damit ist aber noch nicht definiert, auf welchem Port die Caps liegen. also weiter: #define C1OFFSET 8 // C1 auf P2 #define C2OFFSET 0 // C2 auf P1 Somit entspricht REG_SETBITS(ADDBASE + C1Offset + 2,C1); gleich P2DIR |= C1; Warum schreibe ich nicht gleich P2DIR |= C1? Weil ich dann beim nächsten Projekt die Caps genau gleich im Layout verschalten muß oder den Code ändern muß! So muß ich nur den Header ändern!
Datum:
mmmhhhhh, .... Meine Version mal so schnell ins Unsaubere Projekt A
#define SET_C1 P2OUT |= C1; #define CLR_C1 P2OUT &= ~C1; ... int foo (void) { ... SET_C1 ... |
Projekt B
#define SET_C1 P1OUT |= C1; #define CLR_C1 P1OUT &= ~C1; ... int foo (void) { ... SET_C1 ... |
Datum:
#define schrieb: > mmmhhhhh, .... > > Meine Version mal so schnell ins Unsaubere > Projekt A >
> #define SET_C1 P2OUT |= C1; > #define CLR_C1 P2OUT &= ~C1; > ... > > int foo (void) { > ... > SET_C1 > ... > |
> Projekt B >
> #define SET_C1 P1OUT |= C1; > #define CLR_C1 P1OUT &= ~C1; > ... > > int foo (void) { > ... > SET_C1 > ... > |
Da fehlt noch einiges! Um die Ladezeit und die Entladezeit des Caps zu messen, muß zwischen IN/OUT, Interruptquellen, Interuptübergängen L/H, H/L etc. umgeschaltet werden. D.h., man braucht noch zusätzlich: > Meine Version mal so schnell ins Unsaubere > Projekt A
> #define SET_C1 P2OUT |= C1; > #define CLR_C1 P2OUT &= ~C1; #define SetInterruptTransition P2IES |= C1; #define ClearInterruptTransition P2IES &= ~C1; #define SetInterruptEnable P2IE |= C1; #define ClearInterruptEnable P2IE &= ~C1; |
u.s.w.u.s.f. Das ist mir zu viel Definiererei! Ich muß nur C1 = BITx und C1OFFSET = Y im Header definieren. Das war's.
Datum:
Tonmeister schrieb: > Somit entspricht > > REG_SETBITS(ADDBASE + C1Offset + 2,C1); > > gleich > > P2DIR |= C1; Um das in in ein paar Wochen noch zu verstehen, würde ich mir für die +2 eine selbstsprechende Ersetzung suchen. REG_SETBITS(ADDBASE + C1Offset + PDIR_OFS,C1);
Datum:
Tonmeister schrieb: > gleich > > P2DIR |= C1; > > > Warum schreibe ich nicht gleich P2DIR |= C1? > > Weil ich dann beim nächsten Projekt die Caps genau gleich im Layout > verschalten muß oder den Code ändern muß! So muß ich nur den Header > ändern! Musst du doch gar nicht.
#define CAPS_DIR P2DIR #define CAPS_WAS_WEIS_ICH C1 .... CAPS_DIR = CAPS_WAS_WEIS_ICH; |
und gut ists. Und wenn sich beim nächsten Projekt da was ändert, dann änderst du ganz einfach die ersten beiden #define aber deswegen musst du doch nicht in diese 'Niederungen' von Adressen und Offsets.
Datum:
Karl Heinz Buchegger schrieb: > #define CAPS_DIR P2DIR > #define CAPS_WAS_WEIS_ICH C1 > > .... > > CAPS_DIR = CAPS_WAS_WEIS_ICH; > und gut ists. es werden auch mehrere Ports gemischt.
Datum:
RAM schrieb: > Karl Heinz Buchegger schrieb: >> #define CAPS_DIR P2DIR >> #define CAPS_WAS_WEIS_ICH C1 >> >> .... >> >> CAPS_DIR = CAPS_WAS_WEIS_ICH; >> und gut ists. > > es werden auch mehrere Ports gemischt. Was willst du mir damit sagen? Letzten Edes kann man es immer so machen, dass man die 'Information', die man änderbar machen will, in einem eigenen Makro rauszieht.
#define C1_DIR P2DIR #define C2_PORT P2OUT #define C1_PIN C1 #define C2_DIR P2DIR #define C2_PORT P2OUT #define C2_PIN C5 ... C1_DIR |= C1_PIN; C2_DIR |= C2_PIN; .... C1_PORT |= C1_PIN; // auf C1 eine 1 geben C2_PORT &= ~C2_PIN; // dafür C2 auf 0 schalten |
ändert sich was, werden pro Komponente genau 3 define angepasst. Der Rest vom Programm wird vom Compiler angepasst. Wenn man will, kommen noch 3 Makros dazu
#define SET_BIT(p,b) (p) |= (b) #define CLR_BIT(p,b) (p) |= (b) #define IS_SET(p,b) (p) & (b) SET_BIT( C1_DIR, C1_PIN ); SET_BIT( C2_DIR, C2_PIN ); ... SET_BIT( C1_PORT, C1_PIN ); CLR_BIT( C2_PORT, C2_PIN ); |
Das Ganze wird auch nicht weniger einfach mit deiner Adresse+Offset Rechnerei. Nur unübersichtlicher. Und wenn du das übersichtlich machen willst, landest du bei genau wieder dem gleichen Aufwand. Wenn nicht sogar mehr. Nur mit dem einen Unterschied, dass du plötzlich selbst für die korrekten Adressoffsets zuständig bist und im anderen Fall haben dir das die Entwickler deines Compilers bereits abgenommen.
Datum:
Karl Heinz Buchegger schrieb: > RAM schrieb: >> Karl Heinz Buchegger schrieb: >>> #define CAPS_DIR P2DIR >>> #define CAPS_WAS_WEIS_ICH C1 >>> >>> .... >>> >>> CAPS_DIR = CAPS_WAS_WEIS_ICH; >>> und gut ists. >> >> es werden auch mehrere Ports gemischt. > > Was willst du mir damit sagen? > > Letzten Edes kann man es immer so machen, dass man die 'Information', > die man änderbar machen will, in einem eigenen Makro rauszieht. > > >
> #define C1_DIR P2DIR > #define C2_PORT P2OUT > #define C1_PIN C1 > > #define C2_DIR P2DIR > #define C2_PORT P2OUT > #define C2_PIN C5 > > ... > > > > C1_DIR |= C1_PIN; > C2_DIR |= C2_PIN; > > .... > > > C1_PORT |= C1_PIN; // auf C1 eine 1 geben > C2_PORT &= ~C2_PIN; // dafür C2 auf 0 schalten > |
> > ändert sich was, werden pro Komponente genau 3 define angepasst. Der > Rest vom Programm wird vom Compiler angepasst. > > Wenn man will, kommen noch 3 Makros dazu >
> #define SET_BIT(p,b) (p) |= (b) > #define CLR_BIT(p,b) (p) |= (b) > #define IS_SET(p,b) (p) & (b) > > > SET_BIT( C1_DIR, C1_PIN ); > SET_BIT( C2_DIR, C2_PIN ); > > ... > > SET_BIT( C1_PORT, C1_PIN ); > CLR_BIT( C2_PORT, C2_PIN ); > |
> > > Das Ganze wird auch nicht weniger einfach mit deiner Adresse+Offset > Rechnerei. Nur unübersichtlicher. Und wenn du das übersichtlich machen > willst, landest du bei genau wieder dem gleichen Aufwand. Wenn nicht > sogar mehr. Nur mit dem einen Unterschied, dass du plötzlich selbst für > die korrekten Adressoffsets zuständig bist und im anderen Fall haben dir > das die Entwickler deines Compilers bereits abgenommen. Ich bin nicht RAM! Aber das ist ja gar nicht das Thema! Ich muß nicht nur PxOUT in der Funktion verändern, sondern auch PxDIR,PxIE und PxIES, d.h. es wären für einen Cap
> #define C1_DIR P2DIR > #define C1_PORT P2OUT > #define C1_PIN C1 #define C1_PIE P2IE #define C1_IE P2IE |
fünf #defines nötig, das macht bei 8 Caps 40 #defines. Mein Ziel ist aber EINE Funktion für alle möglichen Kombinationen und Layouts von Cap-PärchenZ. Selbst wenn ich o.g. #defines setzte, brauche ich 4 Funktionen für die 4 Cap-PärchenZ. Und beim nächsten Layout (wo ja bekanntlich alles anders ist) muß ich im WC 40 #defines ändern und habe immer noch 4 Funktionen.
Datum:
Karl Heinz Buchegger schrieb: >> es werden auch mehrere Ports gemischt. > > Was willst du mir damit sagen? Das wurde schon durchgekaut: Beitrag "Re: MSP430: Macro um flexibel direkt Register zu beschreiben"