Forum: Mikrocontroller und Digitale Elektronik Data-Direction-Adresse immer eine Adresse höher als Port-Ausgabeadresse?


von scheps (Gast)


Lesenswert?

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

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Also eine Ausnahme gibts, hab den Käfer aber nimmer im Kopf.
Aber ansonsten:
#define DDR(x) (*(&x - 1))
#define PIN(x) (*(&x - 2))

von nocheinGast (Gast)


Lesenswert?

Es ist oft so, aber nicht immer, siehe hier, selbes Problem:
Beitrag "Re: Registernamen/Variablennamen erstellen"

von holger (Gast)


Lesenswert?

>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.

von T. roll (Gast)


Lesenswert?

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?

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von c-hater (Gast)


Lesenswert?

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!

von Peter D. (peda)


Lesenswert?


von scheps (Gast)


Lesenswert?

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

von Josef D. (jogedua)


Angehängte Dateien:

Lesenswert?

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
Noch kein Account? Hier anmelden.