Forum: Mikrocontroller und Digitale Elektronik Flexible Portzuweisung


von Steve-o B. (steve_o)


Lesenswert?

Hallo Leute,

hätte mal eine Frage zur flexiblen Portzuweisung.

Ich benutze das AtmelStudio 6 (C++) und einen AVR.

Ich habe ein Programm, das über USART ein paar Benutzereingaben 
empfangen kann. Nun möchte ich je nach Benutzereingabe unterschiedliche 
Ports in meinem Programm nutzen.

z.B.:

if (Benutzereingabe == 1)
{
   USED_PORT = PORTB;
   USED_PIN = PINB;
   iPIN = 1;
}
else
{
   USED_PORT = PORTD;
   USED_PIN = PIND;
   iPIN = 0;
}

//etwas Code....


if(USED_PIN & (1 << iPIN))
{
    USED_PORT |= (1 << iPIN);
}

/*******************************/

Mit den Präprozessoranweisungen wie #define komme ich da leider nicht 
weiter, da ich ja die Benutzereingabe verwenden möchte, um mich auf 
einen Port festzulegen.

Ich weiß, ist ne Anfängerfrage aber ich bin für jede Hilfe dankbar und 
lese auch gerne selber nach, wenn Ihr einen Link kennt, der mein Problem 
erklärt.

Viele Grüße,

Steve-o

von Pfnott (Gast)


Lesenswert?

Naja, man kann auch die Ports direkt zuweisen, ohne ueber variablen zu 
gehen.

DDRB=0x00;

usw.

von Harald (Gast)


Lesenswert?

switch -- case

von Steve-o B. (steve_o)


Lesenswert?

Hey,

switch -- case würde ich benutzen aber ich möchte die Ports auch in 
Interrupt-Routinen über die Variable USED_PORT aufrufen

Hat noch jemand ne Idee?

Danke für die Hilfe.

von Jiro (Gast)


Lesenswert?

portb usw. ist doch eigendlich auch nur ne adresse irgendwohin, thema 
pointer

von Karl H. (kbuchegg)


Lesenswert?

1
volatile uint8_t * PortToUse;
2
volatile uint8_t * PinToUse;
3
         uint8_t   iPin;
4
5
6
...
7
8
  if (Benutzereingabe == 1)
9
  {
10
    PortToUse = &PORTB;
11
    PinToUse = &PINB;
12
    iPin= 1;
13
  }
14
  else
15
  {
16
    PortToUse = &PORTD;
17
    PinToUse = &PIND;
18
    iPin= 0;
19
  }
20
21
//etwas Code....
22
23
24
  if( *PinToUse & (1 << iPin))
25
  {
26
    *PortToUse |= (1 << iPin);
27
  }
28
29
  ...


Und Variablen-Namen in Grossbuchstaben gewöhnst du dir gleich wieder ab. 
Bezeichner, die ausschliesslich in Grossbuchstaben geschrieben sind, 
reservierst du einzig und alleine ausschliesslich für Makros.

von holger (Gast)


Lesenswert?

>Und Variablen-Namen in Grossbuchstaben gewöhnst du dir gleich wieder ab.

Und variable Shifts am besten auch. Die kosten richtig Zeit;)

von Karl H. (kbuchegg)


Lesenswert?

holger schrieb:
>>Und Variablen-Namen in Grossbuchstaben gewöhnst du dir gleich wieder ab.
>
> Und variable Shifts am besten auch. Die kosten richtig Zeit;)


Genau.
Wobei: Wenn man so indirekt auf die Ports zugreift, wird das 
wahrscheinlich auch schon egal sein. :-)
Denn genau genommen muss man da jetzt noch eventuell eine 
Interrupt-Sicherung einbauen


Fazit:
Es geht zwar, aber eigentlich will man das so nicht machen.

von Steve-o B. (steve_o)


Lesenswert?

Hey Leute,

erstmal vielen Dank für eure Hilfe!

Wenn wir schon dabei sind, könntet ihr mir vielleicht erklären was ihr 
mit Variable Shifts meint? Kann nichts gebrauchen, was viel Zeit kostet!

@kbuchegg:

Was meinst du mit Interrupt-Sicherung?
Ich mache die Zuweisung der Ports nur 1x am Anfang des Programms.
Erst danach aktiviere ich die Interrupts und springe in die 
Endlosschleife.

Fazit:
Es geht zwar, aber eigentlich will man das so nicht machen...

Ich kann mein Problem natürlich auch mit einem Flag und ner IF-Abfrage 
lösen.
Wenn mein Weg unsicher ist und später zu Problemen im Programmablauf 
führt, gehe ich gerne einen anderen.

Was genau ist der Grund, warum man das nicht so machen will?

Viele Grüße,

Steve-o

von Karl H. (kbuchegg)


Lesenswert?

Steve-o Bane schrieb:
> Hey Leute,
>
> erstmal vielen Dank für eure Hilfe!
>
> Wenn wir schon dabei sind, könntet ihr mir vielleicht erklären was ihr
> mit Variable Shifts meint? Kann nichts gebrauchen, was viel Zeit kostet!

     1 << variable


das ist eine Operation, die man auf einem AVR nicht haben will, weil sie 
vom Compiler in Form einer Schleife umgesetzt werden muss (teuer)

> @kbuchegg:
>
> Was meinst du mit Interrupt-Sicherung?

Die Absicherung, dass während der Operation

    *PortToUse |= (1 << iPin);

kein Interrupt auftreten darf, in dessen ISR selbst wieder am gleichen 
Port etwas geändert wird.


> Ich mache die Zuweisung der Ports nur 1x am Anfang des Programms.
> Erst danach aktiviere ich die Interrupts und springe in die
> Endlosschleife.

Darum gehts nicht.

Es geht darum, dass diese Operation

   *PortToUse |= (1 << iPin);

vom Compiler nicht in einem Zug (in einer einzigen Assembler Operation) 
umgesetzt werden kann, sondern in mehrere Instruktionen aufgelöst werden 
muss.

Und dann kann dir das passieren:
  Du beginnst einen Satz in einem Buch zu schreiben
  Noch ehe du mit dem Satz fertig bist, wirst du unterbrochen.
  Während du dich um dieses andere kümmerst, kommt jemand und
  tauscht das Buch aus.
  Du kommst von der UNterbrechung zurück und schreibst den Satz
  (im jetzt anderen Buch) weiter, so als ob nichts gewesen wäre.

Das da nur Unsinn dabei herauskommt, dürfte klar sein.

> Was genau ist der Grund, warum man das nicht so machen will?

Weil
  * die Shift-Operation teuer ist
  * man zusätzlichen Aufwand braucht um sich gegen Eventualitäten
    abzusichern, du nur deswegen entstehen, weil man möglichst
    allgemein sein möchte. Beschränkt man sich auf die Fälle, die man
    wirklich braucht, verschwinden diese Probleme ganz von alleine.

von Steve-o B. (steve_o)


Lesenswert?

@kbuchegg:

Vielen Dank für deine schnelle und genaue Antwort!
Du hast mir sehr geholfen!

Ich werde versuchen mein Problem anders zu lösen, ohne dabei 
Variable-Shifts & Co. zu verwenden!

Grüße,

Steve-o

von Peter D. (peda)


Lesenswert?

Steve-o Bane schrieb:
> Ich mache die Zuweisung der Ports nur 1x am Anfang des Programms.

Dann brauchst Du keinen Portpin, sondern kannst die Leitung direkt auf 
VCC oder GND legen.

Einen Portpin will man immer wieder in der Mainloop neu setzen und da 
sind die Interrupts ja aktiv. Der Zugriff muß also atomar erfolgen.

Nur wenn der Pin zur Compilezeit feststeht, kann der Compiler die 
atomaren Befehle SBI/CBI nehmen.


Peter

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.