Ports in Array möglich?

Gast #117710
Lesenswert?

Hallo zusammen,
ist es möglich Pins in einem Array zusammenzufassen? Ziel ist es
Ausgänge von verschiedenen Ports von einer Schlaufe aus anzusprechen.
Ich stelle mir das ganze ungefähr so vor:

Definition:
PINS(3) = {PORTA.0,PORTB.3,PORTE.7}

Ansprechen:
PINS(i) = 0;
Gast #117711
Lesenswert?

Kommt darauf an, womit Du programmierst und was für einen µC Du benutzt.
Beim AVR hast Du bei den Port-Bit-Befehlen im low byte das IO-Register
und das Bit definiert, da wird es also relativ einfach mit einem
byte-array für die Pins.

Wenn Du es in C machen willst, mußt Du es aber wohl etwas anders
angehen als oben. Also ein SET_PORT(X) definieren, was dann ein SBI mit
PINS[X] macht.
Gast #117712
Lesenswert?

Für den AVR habe ich mir folgendes zusammengestrickt:


// Port-Address-Definitions
#define PA_PORTA 3
#define PA_PORTB 2
#define PA_PORTC 1
#define PA_PORTD 0
#define PA_INIT_OUTPUT 0x20
#define PA_INIT_HIGH   0x40

#define pinAddr(prt,pin) ((prt << 3) | pin)

#define pinBaseAddr(pa) ( (((pa) >> 3) & 3) * 3 + 0x10 + 0x20)
#define pinPinAddr(pa) pinBaseAddr(pa)
#define pinDdrAddr(pa) (pinBaseAddr(pa) + 1)
#define pinPortAddr(pa) (pinBaseAddr(pa) + 2)

#define pinBit(pa) ((pa) & 0x07)

#define setPort(pa,v) if(v) { (*(volatile uint8_t*)pinPortAddr(pa)) |=
_BV(pinBit(pa)); } else { (*(volatile uint8_t*)pinPortAddr(pa)) &=
~_BV(pinBit(pa)); }
#define getPort(pa) ((*(volatile uint8_t*)pinPortAddr(pa)) &
_BV(pinBit(pa)))

#define setDdr(pa,v) if(v){ (*(volatile uint8_t*)pinDdrAddr(pa)) |=
_BV(pinBit(pa)); } else { (*(volatile uint8_t*)pinDdrAddr(pa)) &=
~_BV(pinBit(pa)); }
#define getDdr(pa) ((*(volatile uint8_t*)pinDdrAddr(pa)) &
_BV(pinBit(pa))

#define getPin(pa) ((*(volatile uint8_t*)pinPinAddr(pa)) &
_BV(pinBit(pa)))

#define initPin(pa) setDdr((pa), (pa) & PA_INIT_OUTPUT); setPort((pa),
(pa) & PA_INIT_HIGH )



Dann die Pins definieren mit:

#define BIT_BTN_1 6
#define BIT_BTN_2 7

#define PIN_BTN_1   (pinAddr( PA_PORTA, BIT_BTN_1 ) | PA_INIT_HIGH)
#define PIN_BTN_2   (pinAddr( PA_PORTA, BIT_BTN_2 ) | PA_INIT_HIGH)


Initialisieren mit:

initPin( PIN_BTN_1 );

bzw.

setDdr( PIN_BTN_1, 0 );
setPort( PIN_BTN_1, 1 );

if ( getPin( PIN_BTN_1 ) )
{
...
}

Die #define-ten Werte kann man dann auch in ein Array schreiben und von
da aus verwenden.
Klappt natürlich nur mit PortA-D. Auf dem Mega16 geht das so, bei
anderen muss die pinBaseAddr ggf. angepasst werden.

Hth!
Gast #117714
Lesenswert?

Hallo,

ich habe leider erst letzte Woche angefangen mit mit Mikrokontrollern
zu beschaeftigen.
Nun sind sie Inhalt meines Praktikums, und ich gucke auf die meisten
Quelltexte wie das sprichwoertliche "Schwein ins Uhrwerk).
Ich trage mich mit dem selben Problem wie im Thread beschrieben.
Das Prog von Hanno sieht richtig interessant aus. Aber koenntest du
bitte mal ein paar Kommentare einfuegen welche beschreiben was was
macht?

Danke schoen im Voraus,

Thomas
Gast #117716
Lesenswert?

Ok, hier mal eine Version mit ein paar Kommentaren.
Noch zwei Bemerkungen:
- Das klappt so nur mit den Ports A bis D auf dem ATmega16. Für andere
Controller muss ggf. der Offset 0x30 bei der pinBaseAddr geändert
werden. Die anderen Ports, die z.B. der ATmega128 hat können nicht so
einfach verwendet werden.
- Das ganze ergibt konstante Ausdrücke, die zur Compile-Zeit
ausgewertet werden, so dass es kompakten und schnellen Code ergibt. Das
stimmt aber nicht mehr, sobald die Konstanten in Variablen abgelegt
werden, mit denen dann gearbeitet wird. Die werden dann erst zur
Laufzeit ausgewertet, was weniger effizient ist.
Beispiel:
  setPort( PA_BTN1, 1 ); // schnell+kompakt, wird zu einem SBI

  unsigned char x;
  x = PA_BTN1;
  setPort( x, 1 ); // langsamer+umfangreicher, wird erst zur Laufzeit
ausgewertet

Grüße,
Hanno
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren