Forum: Compiler & IDEs Pointer auf PORT oder bessere Lösung


von Tom (Gast)


Lesenswert?

Hallo Leute!

Ich erklär kurz mal das Problem welchem ich gegenüber stehe:

Bspw. habe ich 8 verschiedene Lampen, die sich (andere Elektronik 
vernachlässigt) über einen verschiedenste Pins am AVR ein und 
ausschalten lassen. Genauso hab ich wild verteilt über den AVR Eingänge, 
die mir sagen, ob eine Lampe ein ist.

Was ich jetzt gerne machen würde wäre eine intelligente Gruppierung des 
Ganzen, so dass ich flexibel bin aber trotzdem gut aussehenden Code hab. 
Bspw (pseudocode!):

#define... Lampe-ON[0] PORTA.3
#define... Lampe-ON[1] PORTD.7
#define... Lampe-ON[2] PORTH.2
...
#define... Lampe-FB[0] PINA.1
#define... Lampe-FB[1] PING.7
......

void lampe_ein(n) {
     toller_befehl[n]..
}

void lampe_aus(n) {
     toller_befehl2[n]..
}


und so weiter. Ich will also ungern in jeder Funktion, irgendwelche 
switch oder if abfragen oder sonstiges haben, sondern würde gern alles 
einmal definieren und dann ist Ruhe im Karton ;)


Besten Dank für Input! :-)

Euer -Tom

von Ralf (Gast)


Lesenswert?

Header-Datei?

Ralf

von Ralf (Gast)


Lesenswert?

Also etwa so:
1
#ifndef _LAMPEN_H_
2
  #define _LAMPEN_H_ 1
3
4
  #define Lampe_0 PORTA.3
5
  #define Lampe-1 PORTD.7
6
  #define Lampe-2 PORTH.2
7
8
  #define Lampe_0_ON (Lampe_0 = 1)
9
  #define Lampe-1_ON (Lampe_1 = 1)
10
  #define Lampe-2_ON (Lampe_2 = 1)
11
12
  #define Lampe_0_OFF (Lampe_0 = 0)
13
  #define Lampe-1_OFF (Lampe_1 = 0)
14
  #define Lampe-2_OFF (Lampe_2 = 0)
15
#endif

Dann diese Headerdatei überall einbinden, wo's nötig ist, und fertig.

Ralf

von Tom (Gast)


Lesenswert?

Hey, erstmal danke für die bisherigen Antworten!

was ich ein bisschen "doof" fand ist dann halt in jeder Routine 
schreiben zu müssen...

void lampe_on (int n) {
if (n == 0) Lampe_0_ON;
if (n == 1) Lampe_1_ON;
if (n == 2) Lampe_2_ON;
if (n == 3) Lampe_3_ON;
if (n == 4) Lampe_4_ON;
if (n == 5) Lampe_5_ON;
if (n == 6) Lampe_6_ON;
if (n == 7) Lampe_7_ON;
}

void lampe_off (int n) {
if (n == 0) Lampe_0_OFF;
if (n == 1) Lampe_1_OFF;
if (n == 2) Lampe_2_OFF;
if (n == 3) Lampe_3_OFF;
if (n == 4) Lampe_4_OFF;
if (n == 5) Lampe_5_OFF;
if (n == 6) Lampe_6_OFF;
if (n == 7) Lampe_7_OFF;
}

Dagegen hab ich einen heiligen Grahl gesucht ;)

Besten Dank!

von Karl H. (kbuchegg)


Lesenswert?

Tom wrote:
>
> Dagegen hab ich einen heiligen Grahl gesucht ;)
>

Hmm.
1
volatile uint8_t* LampPorts[] = { &PORTA, &PORTH, &PORTC, &PORTA, &PORTE };
2
volatile uint8_t  LampPins[]  = { 1<<PA0, 1<<PH1, 1<<PC5, 1<<PA4, 1<<PE4 };
3
4
void lampe_on (int n)
5
{
6
  *(LampPorts[n]) |= LampPins[n];
7
}
8
9
void lampe_off (int n)
10
{
11
  *(LampPorts[n]) &= ~LampPins[n];
12
}

So ungefähr. Soll heißen: ungetestet

von Micha (Gast)


Lesenswert?


von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Da du hier im GCC-Forum bist, mal in der Syntax vom AVR-GCC.  Ich
vermute, du suchst sowas:
1
#include <avr/io.h>
2
3
#define LAMPE1 PORTA, 0
4
#define LAMPE2 PORTB, 2
5
#define LAMPE3 PORTC, 5
6
7
#define ON 1
8
#define OFF 0
9
10
#define LAMPE_SWITCH_int(port, bit, onoff) \
11
  if (onoff) { (port) |= (1 << (bit)); } \
12
  else { (port) &= ~(1 << (bit)); }
13
#define LAMPE_SWITCH(arg, onoff) LAMPE_SWITCH_int(arg, onoff)
14
#define LAMPE_N_SWITCH(n, onoff) LAMPE_SWITCH(LAMPE##n, onoff)
15
16
int
17
main(void)
18
{
19
        LAMPE_N_SWITCH(3, ON);
20
        LAMPE_N_SWITCH(1, OFF);
21
        LAMPE_N_SWITCH(2, ON);
22
23
        return 42;
24
}

Edith: Micha war schneller. ;-)

von Tom (Gast)


Lesenswert?

Hi,

jetzt meld ich mich nochmal zu Wort! :-) Wenn ich das richtig 
durchschaut hab, ist das nun eine Lösung für "Schreibfaule", die das so 
hardcoded in der Applikation benutzen wollen.

Mein Szenario sah so aus:

- Ein Auswahlfeld in einem HTML Formular am AVR, wo man die Lampe 1 - 30 
auswählen kann und dann auf den button ausschalten oder einschalten 
drückt.


- Programmcode empfängt den HTTP POST Request und extrahiert die zu 
schaltende Lampennummer in eine Variable n

dann soll aufgerufen werden "lampe_ein(n)"


Es handelt sich also um ne Sachlage, die nicht durch den precompiler 
gelöst werden kann. ich bräuchte einen pointer auf ein bit eines Ports 
in einem array.

bspw:

Lampe[0] = PINA.3;
Lampe[1] = PIND.5;


aber so, dass ich dann halt Lampe[n] = 0 schreiben kann und sie geht 
aus.

Wenns nicht geht, nicht so tragisch aber schön wärs ;)


Sorry falls ich die Lösung nicht verstanden hab von oben und das schon 
so geht.

-Tom

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Prinzipiell hast du 2 Möglichkeiten "Dynamik" reizubringen, die bereits 
genannt wurden:

1) Die benörigten SFR-Adressen, Masken etc. werden in einem Array 
abgelegt und per Lampen-Index drauf zugegriffen und die Aktion 
ausgeführt.

2) Eine if-else-Orgie resp. switch-case unterscheidet die einzelnen 
Lampen, in den Fällen stehen direkt die SFR-Adressen, die sich zur 
Laufzeit ja nicht ändern.

Bei Ansatz 1) ist zu beachten, daß die so erzeugten Zugriffe nicht 
atomar sind, d.h. wenn eine ISR auf dem selben Port rumnudelt, kann's 
durch den nicht-atomaren Code sporatische Fehler geben.

Johann

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.