Forum: Mikrocontroller und Digitale Elektronik Pin in abhängigkeit einer variablen ein/aus-schalten


von Dominik (Gast)


Lesenswert?

guten abend,
ich habe ein kleines logisches Problem.

Ich möchte den Pin (AVR) anhand einer variable setzen.
Dies habe ich bisher mittels einer if-Bedingung
1
if(1 == ledOn)
2
{
3
  DDRD |= (1 << PIND3);
4
}
5
else
6
{
7
  DDRD &= ~(1 << PIND3);
8
}

gibt es da auch einen eleganteren weg, wo ich direkt den wert der 
Variable benutzen kann?

von Falk B. (falk)


Lesenswert?

Dominik schrieb:
> gibt es da auch einen eleganteren weg, wo ich direkt den wert der
> Variable benutzen kann?

Jain. Man kann es über eine Tabelle machen. Wo liegt denn dein Problem? 
In der Ästhetik?

von Dominik (Gast)


Lesenswert?

Falk B. schrieb:
> In der Ästhetik?

Ja

naja, zumindest kann ich dafür ne inline funktion machen. Damit wird es 
doch ein bisschen leserlicher.

von Sebastian (Gast)


Lesenswert?

Man kann eleganterweise "1 == " weglassen

Man kann das auch in einer Zeile schreiben:
1
DDRD = DDRD & ~(1<<PIND3) | (ledOn<<PIND3);

Aber ob das eleganter ist?

LG, Sebastian

von HildeK (Gast)


Lesenswert?

Dominik schrieb:
> gibt es da auch einen eleganteren weg, wo ich direkt den wert der
> Variable benutzen kann?

Schau dir mal die sbit.h von Peter D. an. 
Beitrag "Re: Frage zu Struktur für IO-Port bei AVRs"
Dann könnte die Stelle so aussehen:
1
#include "sbit.h"
2
.
3
.
4
.
5
6
 LED = ledOn;
wenn ledOn nur die Werte 0 und 1 annimmt. Und hinter LED steht ein 
Makro.

von HildeK (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe noch meine Demodatei dazu gefunden ...

von Rolf M. (rmagnus)


Lesenswert?

HildeK schrieb:
> wenn ledOn nur die Werte 0 und 1 annimmt.

Idealer- und ästhetischerweise nutzt man dafür einen bool, dann ist das 
automatisch gegeben.

von Jim M. (turboj)


Lesenswert?

Rolf M. schrieb:
> Idealer- und ästhetischerweise nutzt man dafür einen bool, dann ist das
> automatisch gegeben.


Nö, ist es AFAIK nicht - und kann einem bei -Os oder -O3 auf die Füße 
fallen.
Der Optimizer darf das in einem ganzen Register belassen, damit sind 
auch Werte <0 oder >1 möglich.

von EAF (Gast)


Lesenswert?

Jim M. schrieb:
> und kann einem bei -Os oder -O3 auf die Füße
> fallen.

Beispiel?

von Michael B. (laberkopp)


Lesenswert?

Dominik schrieb:
> gibt es da auch einen eleganteren weg,

digitalWrite(3,ledOn); aus der Arduino-Bibliothek.

Aber das setzt nicht das Datenrichtungsregister DDRD sondern das 
Ausgaberegister PORTD, und es nutzt nicht die Eingangspinbitnummer 
PIND3, sondern PD3.

Die Frage ist also, was du eigentlich wolltest und warum das alles.

von Stefan F. (Gast)


Lesenswert?

Dominik schrieb:
> gibt es da auch einen eleganteren weg, wo ich direkt den wert der
> Variable benutzen kann?

Man kann den Code hinter einem Makro verbergen:
1
#define writeBit(port,bit,value) { if ((value)>0) (port) |= (1<<bit); else (port) &= ~(1<<bit); } 
2
3
writeBit(DDRD,3,ledOn)
Aber wirklich eleganter ist das auch nicht. Ich habe früher zu viele 
solcher Makros verwendet. Sie verschleiern, was wirklich passiert. 
Dadurch provozieren sie falsche Verwendung und machen Fehlermeldungen 
schwerer verständlich.

Eine ganz normale C Funktion ist gut lesbar und produziert in der Regel 
genau den gleichen Maschinencode, ist also nicht ineffizient:
1
void setze_status_led(bool ein) 
2
{
3
    if(ein)
4
    {
5
       DDRD |= (1 << PIND3);
6
    }
7
    else
8
    {
9
       DDRD &= ~(1 << PIND3);
10
    }
11
}
12
13
setze_status_led(ledOn);

Wobei man auch aufpassen muss, wie man die Variable nennt. "ledOn" kann 
die LED nämlich auch aus schalten. Gute passende Namen sind wichtig, 
falls es kein Wegwerf-Projekt ist.

von Rolf M. (rmagnus)


Lesenswert?

Jim M. schrieb:
> Rolf M. schrieb:
>> Idealer- und ästhetischerweise nutzt man dafür einen bool, dann ist das
>> automatisch gegeben.
>
> Nö, ist es AFAIK nicht - und kann einem bei -Os oder -O3 auf die Füße
> fallen.

Nein.

> Der Optimizer darf das in einem ganzen Register belassen, damit sind
> auch Werte <0 oder >1 möglich.

Der interne Wert, den der Compiler für einen bool nutzt, kann dir aber 
egal sein. Wenn man ihn in einen Integer konvertiert, kommt immer 0 für 
false und 1 für true raus. Das garantiert der Standard.

von EAF (Gast)


Lesenswert?

Stefan F. schrieb:
> eleganter

Über "elegant" kann man streiten.

Hier ein eleganter und optimierter "Arduino" Code:
1
#include <CombiePin.h>
2
3
using Led = Combie::Pin::OutputPin<LED_BUILTIN>;
4
5
int main() 
6
{
7
   Led{}.init();
8
   Led{} = 1;
9
   while(1);
10
}


Und das zugehörige Kompilat:
1
00000080 <main>:
2
          #endif  
3
        }
4
        
5
        void  INLINE initOutput()
6
        {
7
            *getDdrPort(arduinoPin) |= getMaske(arduinoPin);
8
  80:  25 9a         sbi  0x04, 5  ; 4
9
10
00000082 <.LBB23>:
11
          return *getInPort(arduinoPin)  &  getMaske(arduinoPin);
12
        }
13
    
14
        void  INLINE setHigh()
15
        {
16
          *getOutPort(arduinoPin)  |=  getMaske(arduinoPin);
17
  82:  2d 9a         sbi  0x05, 5  ; 5
18
19
00000084 <.L2>:
20
21
int main() 
22
{
23
   Led{}.init();
24
   Led{} = 1;
25
   while(1);
26
  84:  ff cf         rjmp  .-2        ; 0x84 <.L2>

von Eine Anmerkung (Gast)


Lesenswert?

> Die Frage ist also, was du eigentlich wolltest und warum das alles.

Das Problem ist doch gerade, jeder Programmiere wählt die Lösung, die 
ihm persönlich am besten gefällt.

Dominiks ursprüngliches Beispiel ergibt ewig langen Programmcode. Nach 
dem runter scrollen hat man schon wieder vergessen, was oben stand.

Arduinos digitalWrite() ist zwar kompakt, hat sich aber außerhalb der 
Arduino Welt nicht durchgesetzt.

Jeder bastelt da irgend etwas anderes. Der Code lässt sich nicht 
wiederverwenden. Nachvollziehen, was die Macros, Wrapper und Frameworks 
machen, wird aufwendiger als komplett neu entwickeln.

Nimm als Beispiel die Normen aus Maschinenbau oder Bauwesen. Alle 
Ingenieure benutzen die selben Symbole und die selben Bezeichnungen. 
Jeder sieht auf den ersten Blick, was der Kollege konstruiert hat.

Wieso können wir uns nicht auf einen einheitlichen Weg einigen?

von Stefan F. (Gast)


Lesenswert?

EAF schrieb:
> Und das zugehörige Kompilat:

Das der Compiler so etwas gut optimieren kann, brauchst du nicht zu 
beweisen. Das Thema hatten wir schon oft genug. Auch eine ganz normale 
Funktion erzeugt in der Regel den selben optimalen Maschinencode.

Die Frage nach der "Ästhetik" finde ich viel wichtiger.

Eine Anmerkung schrieb:
> Arduinos digitalWrite() ist zwar kompakt, hat sich aber außerhalb der
> Arduino Welt nicht durchgesetzt.

Der Maschinencode der dabei heraus kommt ist aber alles andere als 
Kompakt. Wenn man sich mal den Quelltext der Funktion anschaut, wundert 
mich das auch nicht. Da passiert ja noch einiges mehr, als nur den 
einzelnen PIN auf HIGH oder LOW zu setzen. Womit wir wieder beim 
"verschleiern" sind. Die Funktion macht mehr, als ihr Name suggeriert, 
was ich nicht gut finde. Andererseits ist sie trotz der Verschleierung 
halbwegs deppensicher, das muss man auch mal würdigen.

von EAF (Gast)


Lesenswert?

Stefan F. schrieb:
> Das Thema hatten wir schon oft genug

Und doch gibt es hier weiterhin eine "Arduino Basher" und "C++ auf µC 
ist ineffektiv/unsinnig" Fraktion.
Erinnere dich!

von spess53 (Gast)


Lesenswert?

Hi

>Und doch gibt es hier weiterhin eine "Arduino Basher" und "C++ auf µC
>ist ineffektiv/unsinnig" Fraktion.

Immer noch die gleichen Phrasen, die du schon als 'Arduino Fanboy' von 
dir gegeben hast.

MfG Spess

von Mirko (Gast)


Lesenswert?

Einen µC-Pin in Abhängigkeit von einer Variablen schalten...
Zu schwer?

Warum nicht Ikebana?
Da gibt es sehr schöne VHS-Kurse, die dich hoffentlich nicht so
schnell überfordern...

von Wilhelm M. (wimalopaan)


Lesenswert?

Dominik schrieb:

>
1
> if(1 == ledOn)
2
> {
3
>   DDRD |= (1 << PIND3);
4
> }
5
> else
6
> {
7
>   DDRD &= ~(1 << PIND3);
8
> }
9
>
>
> gibt es da auch einen eleganteren weg, wo ich direkt den wert der
> Variable benutzen kann?

Meinst Du wirklich DDRD? Oder sollte es eher PORTD sein? Kennst Du den 
Unterschied?

von M. K. (sylaina)


Lesenswert?

Dominik schrieb:
> guten abend,
> ich habe ein kleines logisches Problem.
>
> Ich möchte den Pin (AVR) anhand einer variable setzen.
> Dies habe ich bisher mittels einer if-Bedingung
>
1
> if(1 == ledOn)
2
> {
3
>   DDRD |= (1 << PIND3);
4
> }
5
> else
6
> {
7
>   DDRD &= ~(1 << PIND3);
8
> }
9
>
>
> gibt es da auch einen eleganteren weg, wo ich direkt den wert der
> Variable benutzen kann?

DDRD setzt aber nur die Datenrichtung des angegebenen Pins, nicht seinen 
logischen Zustand. Was du wohl eher möchtest ist
1
if(1 == ledOn)
2
{
3
  PORTD |= (1 << PD3);
4
}
5
else
6
{
7
  PORT &= ~(1 << PD3);
8
}

Wenn ledOn nur den Zustand 0 oder 1 annehmen kann, dann kann man das 
verkürzt schreiben mit:
1
PORTD = PORTD & ~(1 << PD3) | (ledOn << PD3);

Das ist aber IMHO etwas schwerer zu lesen, die If-Bedingung ist meiner 
Ansicht nach für den Menschen übersichtlicher/einfacher zu 
lesen/verstehen und der Compiler wirds eh passend optimieren.

von Wilhelm M. (wimalopaan)


Lesenswert?

EAF schrieb:
> Stefan F. schrieb:
>> eleganter
>
> Über "elegant" kann man streiten.

In der Tat!

> Hier ein eleganter und optimierter "Arduino" Code:
>
1
> #include <CombiePin.h>
2
> 
3
> using Led = Combie::Pin::OutputPin<LED_BUILTIN>;
4
> 
5
> int main()
6
> {
7
>    Led{}.init();
8
>    Led{} = 1;
9
>    while(1);
10
> }
11
>

Wenn Du schon ein Monostate einsetzt, dann sollte man das auch richtig 
machen ;-) So ist das jedenfalls unnötiger Murks.

von EAF (Gast)


Lesenswert?

Wilhelm M. schrieb:
> dann sollte man das auch richtig
> machen ;-)

Dann mache doch mal eine Vorführung.

von Wilhelm M. (wimalopaan)


Lesenswert?

EAF schrieb:
> Wilhelm M. schrieb:
>> dann sollte man das auch richtig
>> machen ;-)
>
> Dann mache doch mal eine Vorführung.

Ok, schicke Dir einen Link zum nä. Konzert ;-)

Du weißt was das Monostate-Pattern ist?

von Peter D. (peda)


Lesenswert?

HildeK schrieb:
> LED = ledOn;
> wenn ledOn nur die Werte 0 und 1 annimmt.

Das ist egal, LED verlangt ein Bool, da Bitvariable. Bei Bedarf erfolgt 
eine automatische Umwandlung.

von HildeK (Gast)


Lesenswert?

Peter D. schrieb:
> Das ist egal, LED verlangt ein Bool, da Bitvariable. Bei Bedarf erfolgt
> eine automatische Umwandlung.

Nicht ganz, aber mein Durchblick bei sbit.h ist nicht so der Renner 😀.

Im Simulator sieht es zumindest so aus, als ob der Wert nur mit der 
Maske 0x01 behandelt wird. Heißt:
LED = 1; // on
LED = 2; // off
LED = 3; // on  - und so weiter.
Das ist für mich keine automatische Umwandlung in Bool, denn es ist 
nicht das selbe wie: alles, was ungleich 0 (false) ist, ist dann 1 
(true).

Deshalb war mein Hinweis nicht ganz unberechtigt.

von Mascha V. (maschak)


Lesenswert?

Eine Anmerkung schrieb:
> Jeder bastelt da irgend etwas anderes. Der Code lässt sich nicht
> wiederverwenden. Nachvollziehen, was die Macros, Wrapper und Frameworks
> machen, wird aufwendiger als komplett neu entwickeln.
>
> Nimm als Beispiel die Normen aus Maschinenbau oder Bauwesen. Alle
> Ingenieure benutzen die selben Symbole und die selben Bezeichnungen.
> Jeder sieht auf den ersten Blick, was der Kollege konstruiert hat.
>
> Wieso können wir uns nicht auf einen einheitlichen Weg einigen?

Als Mädchen mit entsprechenden Erfahrungen sage ich es so: Jeder will 
den Größten haben...

Einheitlicher Weg würde ja bedeuten, dass niemand mehr "Java ist 
besser!", "Nein C ist besser!", "Nein Rust ist besser!" sagen dürfte, 
sondern dass sich alle einigen müssten auf ein gemeinsames Ziel. Aber 
das geht doch nicht! Nicht unter Jungs jedenfalls ^^

von Mascha V. (maschak)


Lesenswert?

Eine Anmerkung schrieb:
> Wieso können wir uns nicht auf einen einheitlichen Weg einigen?

Ich nochmal... Mir kommt das so vor als ob es darum geht, ob 
Programmieren Kunst oder Handwerk ist. Manche wollen Geld damit 
verdienen, und manche wollen Applaus ^^

von Peter K. (Gast)


Lesenswert?

1
VAR LED1 : BOOLEAN;
2
If LED1 = 1 THEN PortD.3:=1 ELSE PortD.3:=0;

MfG
 Pascal:-)

von Mascha V. (maschak)


Lesenswert?

Dominik schrieb:
> guten abend,
> ich habe ein kleines logisches Problem.
>
> Ich möchte den Pin (AVR) anhand einer variable setzen.
> Dies habe ich bisher mittels einer if-Bedingung
>
1
> if(1 == ledOn)
2
> {
3
>   DDRD |= (1 << PIND3);
4
> }
5
> else
6
> {
7
>   DDRD &= ~(1 << PIND3);
8
> }
9
>
>
> gibt es da auch einen eleganteren weg, wo ich direkt den wert der
> Variable benutzen kann?

Der Code ist grundsätzlich scheiße.

Warum? Weil ihn niemand versteht, der nicht C-Experte ist so wie du.

Wenn ledOn bool ist, dann ist die if-clause schon falsch. Und zweitens 
gehört (1 << PIND3) in eine eigene Funktion verpackt, weil "don't repeat 
yourself".

von Rolf M. (rmagnus)


Lesenswert?

HildeK schrieb:
> Peter D. schrieb:
>> Das ist egal, LED verlangt ein Bool, da Bitvariable. Bei Bedarf erfolgt
>> eine automatische Umwandlung.
>
> Nicht ganz, aber mein Durchblick bei sbit.h ist nicht so der Renner 😀.
>
> Im Simulator sieht es zumindest so aus, als ob der Wert nur mit der
> Maske 0x01 behandelt wird. Heißt:
> LED = 1; // on
> LED = 2; // off
> LED = 3; // on  - und so weiter.
> Das ist für mich keine automatische Umwandlung in Bool,

Anders herum wird ein Schuh draus. Auf der rechten Seite der Zuweisung 
muss ein bool stehen, und dann kommt in LED eine 0 an, wenn der false 
ist und eine 1, wenn er true ist. Eine 2 oder 3 gibt es dann gar nicht. 
Es ging doch darum:

HildeK schrieb:
> #include "sbit.h"
> .
> .
> .
>  LED = ledOn;

und um meinen Hinweis, ledOn dann als bool zu definieren.

: Bearbeitet durch User
von HildeK (Gast)


Lesenswert?

Rolf M. schrieb:
> Anders herum wird ein Schuh draus. Auf der rechten Seite der Zuweisung
> muss ein bool stehen, und dann kommt in LED eine 0 an, wenn der false
> ist und eine 1, wenn er true ist. Eine 2 oder 3 gibt es dann gar nicht.

Ja, richtig! Welcher Typ die Variable 'ledOn' beim TO jedoch hatte, ist 
unbekannt. Deshalb schrieb ich dazu:

HildeK schrieb:
> wenn ledOn nur die Werte 0 und 1 annimmt.
also auf den boolschen Zahlenraum beschränkt ist.
Du hast sinnvollerweise ergänzt, dass man für ledOn gleich eine 
Boolvariable nehmen sollte. Zumindest wäre einen Cast auf bool nötigt.

Nur Peter D. hatte gemeint:

Peter D. schrieb:
> Bei Bedarf erfolgt eine automatische Umwandlung.

Diese Umwandlung sehe ich nicht. Deshalb hab ich das mal getestet.

von Stefan F. (Gast)


Lesenswert?

Mascha schrieb:
> zweitens gehört (1 << PIND3) in eine eigene Funktion verpackt,
> weil "don't repeat yourself".

Den Scherz finde ich nicht lustig.

von Mascha V. (maschak)


Lesenswert?

Stefan F. schrieb:
> Den Scherz finde ich nicht lustig.

War ja auch keiner ;)

von Norbert (Gast)


Lesenswert?

Ich hätte den hier im Angebot:
1
DDRD = ledOn ? DDRD | (1 << PIND3) : DDRD & ~(1 << PIND3);

von Dirk F. (dirkf)


Lesenswert?

Beim Microchip XC8 Compiler für PICs  ist diese Funktion direkt dabei:

#define LED1 LATAbits.LATA2
#define LED2 LATBbits.LATB4

LED1 = 1;
LED2 = 0;

von Norbert (Gast)


Lesenswert?

Dirk F. schrieb:
> Beim Microchip XC8 Compiler für PICs  ist diese Funktion direkt
> dabei:
>
> #define LED1 LATAbits.LATA2
> #define LED2 LATBbits.LATB4
>
> LED1 = 1;
> LED2 = 0;

Gratulation! ;-)
assert(PIC == AVR) -> failed
assert(question == answered) -> failed

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.