Forum: Compiler & IDEs Generisches Mapping von Portzugriffen bei ATmega


von Chris (Gast)


Lesenswert?

Hallo zusammen,

ich arbeite mit einem Atmega48PA und möchte gerne meine Pin-Lese, -Setz 
und -Lösch Aktionen etwas generischer darstellen. Mein Traum ist, dass 
z.B. in einer HwSwInterface c oder h Datei etwas steht wie:
1
/* die Funktionen mit den entsprechenden Pins des uC mappen: */
2
#define BUTTON 2 /* Pin 2 */
3
#define LED1 3 /* Pin 3 */
4
#define LED2 4 /* Pin 4 */
5
/* das soll das Pin Tauschen vereinfachen und die Zuordnung übersichtlich machen */
6
...
7
/* die uC Pins auf die Pinnamen mappen(uC-spezifisch, bleibt dann fest): */
8
PortLetterOfPin[1] = 'C';
9
PortNumberOfPin[1] = '6';
10
PortLetterOfPin[2] = 'D';
11
PortNumberOfPin[2] = '0';
12
/* z.B. Pin1 = PC6 */
13
...
und an anderer Stelle sag ich dann nur noch
1
var = READ_PIN(BUTTON);
2
SET_PIN(LED1);
3
...
Ich hab mich schon mit "Token Pasting" und "Stringize" dran versucht, 
aber bekomme nicht das, was ich will - entweder ist PIN undeclared oder 
der compiler verwendet die Namen der Defines anstatt dem Wert dahinter 
(PINPortLetterOfPinBUTTON anstatt PIND usw.) :(
1
/* o=pOrt, i=pIn */
2
#define CmdReadPin(o, i) PIN#o & (1<<PIN#o#i)
3
#define CmdSetPin(o, i) PORT##o |= (1<<PORT##o##i)
4
#define CmdResetPin(o, i) PORT##o &= ~(1<<PORT##o##i)
5
...
6
#define MacReadPin(n)    CmdReadPin(PortLetterOfPin#n, PortNumberOfPin#n)
Wann muss ich ## benutzen und wann #? Muss ich Variablen anlegen für die 
Zuordnungen oder kann man es nur über defines lösen?

Ich hab schon gegoogelt, aber finde nichts. Sowas muss es doch schon 
geben, ich weiß nur nicht wie es heißt...

von Nil (Gast)


Lesenswert?

Ist vom Grundgedanken ja das gleiche wie bei arduino. Schau dir doch 
einfach mal an, wie das dort gelöst wurde.

von gurgler (Gast)


Lesenswert?

Chris schrieb:
> /* o=pOrt, i=pIn */
> #define CmdReadPin(o, i) PIN#o & (1<<PIN#o#i)
> #define CmdSetPin(o, i) PORT##o |= (1<<PORT##o##i)
> #define CmdResetPin(o, i) PORT##o &= ~(1<<PORT##o##i)
Ich glaube das hat hier jemand richtig gemacht:
https://www.mikrocontroller.net/attachment/highlight/254049

von Chris (Gast)


Lesenswert?

Danke für die Antworten, besonders zu Peter Danneggers sbit.h!
Ist die Verwendung so richtig?
1
DDR_A0 = 0;  /* A0 = Eingang */
2
DDR_A1 = 1;  /* A1 = Ausgang */
3
PORT_A0 = 1; /* A0 Pullup */
4
5
if (0 == PIN_A0)
6
  PORT_A1 = 1;

von Chris (Gast)


Lesenswert?

Was ich trotzdem noch gerne hätte, wäre so eine Benutzung von
1
#define INPUT       0
2
#define OUTPUT      1
3
4
#define BUTTON      A0
5
#define LED1        A1
6
7
#define SetDirection(n, x)  DDR_#n=#x
8
#define UsePullup(n)        PORT_#n=1
9
#define SetPin(n, x)        PORT_#n=#x
10
#define ReadPin(n)         !(PIN_#n)
und dann nur noch so verwenden:
1
SetDirection(BUTTON, INPUT);
2
UsePullup(BUTTON);
3
var = ReadPin(BUTTON);
mit diesem Code ist aber 'PIN_' wieder mal undeclared :'(
Ich möchte, dass er aus "ReadPin(BUTTON)" ein "!(PIN_A0)" macht, wie 
bekommt man das hin?

von gurgler (Gast)


Lesenswert?

Versuchs mal damit:
1
#define SetDirection(n, x)  DDR_##n=##x
2
#define UsePullup(n)        PORT_##n=1
3
#define SetPin(n, x)        PORT_##n=##x
4
#define ReadPin(n)         !(PIN_##n)

von gurgler (Gast)


Lesenswert?

Falsch, besser so:
1
#define SetDirection(n, x)  DDR_##n=(x)
2
#define UsePullup(n)        PORT_##n=1
3
#define SetPin(n, x)        PORT_##n=(x)
4
#define ReadPin(n)         !(PIN_##n)

von Chris (Gast)


Lesenswert?

So sucht er aber nur nach einem "PIN_BUTTON", dabei soll er ja das 
vorherige define
[c]
#define BUTTON      A0
[c/]
verwenden und "PIN_A0" nehmen.
Danke  für die Unterstützung, aber ich werd wohl doch eine riesige 
Funktion mit verschachtelten switch(Befehl * Pin) case Anweisungen dafür 
verwenden müssen oder auf meinen Wunsch verzichten müssen.

von Chris (Gast)


Lesenswert?

An den Arduino-Code bin ich nicht rangekommen (oder stell mich zu doof 
an).
So mach ich es momentan:
1
/* file: HwSwInterface.h */
2
#include "sbit.h"
3
4
#define INPUT       0
5
#define OUTPUT      1
6
7
#define SetDirection(n, x)  DDR_##n=(x)
8
#define UsePullup(n)        PORT_##n=1
9
#define WritePin(n, x)      PORT_##n=(x)
10
#define ReadPin(n)         !(PIN_##n)
11
12
#define SET_DIR_BUTTON     SetDirection(A0, INPUT)
13
#define USE_PULLUP_BUTTON  UsePullup(A0);
14
#define READ_PIN_BUTTON    ReadPin(A0)
15
16
#define SET_DIR_LED1       SetDirection(A1, OUTPUT)
17
#define WRITE_PIN_LED1(s)  WritePin(A1, (s))

Ist zwar etwas redundant, aber dafür wenig Aufwand und kostet wenig 
Ressourcen.

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


Lesenswert?

Chris schrieb:
> #define BUTTON      A0
> #define LED1        A1

Damit geht's nicht, denn dein „A0“, „A1“ etc. kann der Präprozessor
nicht zerpopeln.

So geht's aber
1
#define BUTTON A, 0
2
#define LED1   A, 1

Die dafür nötige Präprozessormimik steht schon hier im Thread. Beruht
im wesentlichen darauf, dass man so einen Makro über zwei „Etagen“ der
Präprozessorersetzung an andere Makros weiterreichen kann und dort dann
mit den Teilen und den Worten „PORT“, „PIN“ und „DDR“ dann wieder
zusammengesetzte Worte bilden kann.

von Le X. (lex_91)


Lesenswert?

gurgler schrieb:
> Ich glaube das hat hier jemand richtig gemacht:
> https://www.mikrocontroller.net/attachment/highlight/254049

Der Vollständigkeit:
Peters sbit.h geht einen anderen (performanteren) Weg als Arduino.
Das kann in dem Fall OK sein, bringt aber auch Einschränkungen mit sich 
(die sich.

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.