Hallo zusammen, mal ein ganz allgemeine Frage zu den Atmel-Käferchen: Ist die Adresse des Data-Direchtion-Registers eines Ports (z.B. DDRx) immer die nächste Adresse als wie die Port-Ausgabeadresse (z.B. PORTx)? Ich habe mehrere Datenblätter gewälzt (Atmega 8, 328, Attiny13) wo das zutrifft. Gibt es eine allgemeine Aussage, dass das eben immer so ist? Zum Hintergrund: Ich will die PORT und Pins, an denen ich Daten ausgebe, in einem Makro definieren. Wenn ich es genau nehme und später nicht im Code rumwerkeln will muss ich eben auch das DDRBx als MAkro definieren. Wenn es aber immer eine feste Beziehung PORTx /DDRx gibt, kann ich mir ja DDRx ausrechnen.... Gruß scheps
Also eine Ausnahme gibts, hab den Käfer aber nimmer im Kopf. Aber ansonsten: #define DDR(x) (*(&x - 1)) #define PIN(x) (*(&x - 2))
Es ist oft so, aber nicht immer, siehe hier, selbes Problem: Beitrag "Re: Registernamen/Variablennamen erstellen"
>Also eine Ausnahme gibts, hab den Käfer aber nimmer im Kopf. ATMega128. >Wenn es aber immer eine feste Beziehung PORTx /DDRx gibt, kann ich mir >ja DDRx ausrechnen.... Annahmen das irgendwas da ist wo es sein sollte sind der erste Schritt in die Scheisse. Nenn das Kind beim Namen, dann hast du weniger Ärger.
Jeder controller hat ein pin definition file, das den namen einer adresse zuweist. Welchen grund koennte es geben, dieses mitgelieferte file nicht verwenden zu wollen?
Wenn du zB eine Lib schreiben willst in der der User nur PORTA eintippen muss und nicht noch zusätzlich DDRA/PINA. Wenns ne Lib gibt mit mehreren IOs ist sowas schon ganz nett ;) Wenn du nen define im Kopf hast welches diese Funktionalität bietet und dazu das Controllerdeffile nutzt, dann nur her damit.
T. roll schrieb: > Jeder controller hat ein pin definition file, das den namen einer > adresse zuweist. Welchen grund koennte es geben, dieses mitgelieferte > file nicht verwenden zu wollen? Arbeitserleichterung und damit auch Fehlervermeidung in der Programmierung. Es ist ein Unterschied, ob bei #define ERROR_LED_DDR DDRB #define ERROR_LED_PORT PORTB die beiden Angaben zusammenstimmen müssen, oder ob ich die eine Angabe aus der anderen automatisch erzeugen kann. Im letzteren Fall gäbe es keine Möglichkeit für Flüchtigkeitsfehler.
Martin Wende schrieb: > Wenn du nen define im Kopf hast welches diese Funktionalität bietet und > dazu das Controllerdeffile nutzt, dann nur her damit. Ich habs noch nicht ausprobiert. Aber ich denke mit dem Token-Pasting Preprozessor könnte da was gehen.
1 | #include <avr/io.h> |
2 | |
3 | #define DDR_OF_(x) DDR##x
|
4 | #define PORT_OF_(x) PORT##x
|
5 | #define PIN_OF_(x) PIN##x
|
6 | |
7 | #define DDR_OF(x) DDR_OF_(x)
|
8 | #define PORT_OF(x) PORT_OF_(x)
|
9 | #define PIN_OF(x) PIN_OF_(x)
|
10 | |
11 | |
12 | #define LED_ B
|
13 | |
14 | #define LED_DDR DDR_OF(LED_)
|
15 | #define LED_PORT PORT_OF(LED_)
|
16 | #define LED_PIN PIN_OF(LED_)
|
17 | |
18 | int main(void) |
19 | {
|
20 | LED_DDR |= (1<<PB2); |
21 | }
|
Die ersten 6 Makros kommen natürlich sinnvollerweise in ein Header-File. Wechselt man den Port, dann genügt es
1 | #define LED_ C
|
zu ändern und der Rest passt sich an.
Martin Wende schrieb: > Wenn du nen define im Kopf hast welches diese Funktionalität bietet und > dazu das Controllerdeffile nutzt, dann nur her damit. In Assembler ist das mit einem Macro völlig problemlos zu realisieren: ;->@0 Namensprefix ; @1 Portkennung (ein Buchstabe) ; @2 Portbit (einstellige Zahl) .MACRO DEFPIN .EQU @0PORT=PORT@1 .EQU @0DDR=DDR@1 .EQU @0PIN=PIN@1 .EQU @0BIT=PORT@1@2 .ENDMACRO Verwendung z.B. in einer Konfigurationsdatei für eine TWI-Lib: DEFPIN TWI_SCL_,C,0 DEFPIN TWI_SDA_,C,1 Produziert dasselbe wie die etwas länglichere konventionelle Deklaration: .EQU TWI_SCL_PORT=PORTC .EQU TWI_SCL_DDR=DDRD .EQU TWI_SCL_PIN=PINC .EQU TWI_SCL_BIT=PORTC0 .EQU TWI_SDA_PORT=PORTC .EQU TWI_SDA_DDR=DDRD .EQU TWI_SDA_PIN=PINC .EQU TWI_SDA_BIT=PORTC1 Verhindert dabei sicher Tippfehler und damit Konstistenzprobleme innerhalb einer Pindeklaration. Aber mit Macros ist noch viel mehr möglich, z.B. eine automatische anwendungsweite Prüfung auf Pin-Kollisionen zur Entwurfszeit. Asm rules!
Nur noch malzum allgemeinen Verständnis: Grund für das Ganze ist, dass ich verschiedene Pins schalten muss, die ggf über mehrere Ports verteilt sind (!). PORT und PIN definiere ich in einem Makro, aber ich wollte vermeiden das Data-Direction-Reg nochmal extra in nem Makro zu definieren. Das ergibt in meinem Progrämmchen 9 Makros (3 für Port, 3für Pin und leider noch mal 3 fürs DDRx). die letzen 3 wollte ich mir sparen. Ich hab mich jetzt für die Lösung entschieden: Ich definiere die MAkros für PORTs und PINS #define L1_PORT PORTA #define L2_PORT PORTD #define L3_PORT PORTD #define L1_PIN 4 #define L2_PIN 6 #define L3_PIN 2 Dann durchlaufe ich im Programm eine Init-Funktion (die ich eh durchlaufen muss, um noch andere Dinge zu machen). Da prüfe ich ob das PORT überhaupt definiert ist. Wenn er definiert ist wird geprüft ob das Makro auf diesen Port zeigt und dann der entsprechende Pin im DDrx geschaltet. Das könnte man sicher auch in ein MAkro packen, aber da hat der Vorredner recht: Wenns zu kompliziert wird dann in eine Funktion: #ifdef PORTA if (L1_PORT == PORTA) DDRA |= (1<<L1_PIN); if (L2_PORT == PORTA) DDRA |= (1<<L2_PIN); if (L3_PORT == PORTA) DDRA |= (1<<L3_PIN); #endif #ifdef PORTB if (L1_PORT == PORTB) DDRB |= (1<<L1_PIN); if (L2_PORT == PORTB) DDRB |= (1<<L2_PIN); if (L3_PORT == PORTB) DDRB |= (1<<L3_PIN); #endif usw PORTC , PORTD ... Gruß scheps
Danach habe ich auch lange gesucht. Bei mir würde das z.B. jetzt so aussehen:
1 | #include "IoPort.h" |
2 | |
3 | #define LED1 A,2 // Pin 2 an Port A
|
4 | #define LED2 B,4
|
5 | #define LED3 C,7
|
6 | #define LED_ON 0 // active Low
|
7 | #define LED_OFF (!(LED_ON))
|
8 | |
9 | void InitLeds(void){ |
10 | DDR(LED1)= DDRoutput; |
11 | DDR(LED2)= DDRoutput; |
12 | DDR(LED3)= DDRoutput; |
13 | }
|
14 | |
15 | void Test(void){ |
16 | InitLeds(); |
17 | PORT(LED1)= LED_ON; |
18 | PORT(LED2)= LED_OFF; |
19 | PORT(LED3)= LED_ON; |
20 | }
|
Die übrigen Infos stehen (z.T. mit Quellenangaben) in IoPort.h
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.