Hallo,
mit diesem Ausdruck
if (PINA & (1 << PA1)) {.....}
stellt man fest, ob am Pin A1 ein HI anliegt. Liegt ein HI an, wird der
Inhalt des Funktionsblocks ausgeführt.
Mit welchem Ausdruck kann man aber feststellen, ob an PA1 ein LO
anliegt, um den Funktionsblock auszuführen?
Folgende Überlegung:
1. Wert PINA kann 0 oder 1 sein
2. Wert (1 << PA1) ist immer 1 (?!)
Also müsste es mit einer Xor-Verknüpfung gehen:
1. = 1 ; 2. = 1 ; Xor = 0
1. = 0 ; 2. = 1 ; Xor = 1
Falls dem so ist, wie wird das richtig formuliert?
So: (?)
if (PINA ^ (1 << PA1)) {.....}
robur schrieb:> if (PINA & (1 << PA1)) {.....}>> stellt man fest, ob am Pin A1 ein HI anliegt. Liegt ein HI an, wird der> Inhalt des Funktionsblocks ausgeführt.>>> Mit welchem Ausdruck kann man aber feststellen, ob an PA1 ein LO> anliegt, um den Funktionsblock auszuführen?
Zum Beispiel einfach durch Inverieren:
1
if(!(PINA&(1<<PA1))){.....}
> Folgende Überlegung:>> 1. Wert PINA kann 0 oder 1 sein
Du meinst das gesuchte Bit in PINA. PINA selbst ist 8 Bit breit und kann
jeden Wert von 0 bis 255 annehmen.
> 2. Wert (1 << PA1) ist immer 1 (?!)
(1 << PA1) ist 2. Das Bit für Pin A1 ist 1.
> Also müsste es mit einer Xor-Verknüpfung gehen:>> 1. = 1 ; 2. = 1 ; Xor = 0>> 1. = 0 ; 2. = 1 ; Xor = 1>>> Falls dem so ist, wie wird das richtig formuliert?> So: (?)>> if (PINA ^ (1 << PA1)) {.....}
Wenn man sich nur um das eine Bit kümmert, ja. Aber was ist mit den
anderen 7 Bit von PINA? Der ganze Sinn der und-Verknüpfung in
1
PINA&(1<<PA1)
ist es, das eine Bit, das dich interessiert, aus den restlichen
herauszuschälen.
batman schrieb:> Das Grundproblem ist wohl erstmal, den Unterschied zwischen bitweisen> und logischen Operationen zu verstehen.
Wo findet man näheres dazu?
Rolf Magnus schrieb:> Du meinst das gesuchte Bit in PINA. PINA selbst ist 8 Bit breit und kann> jeden Wert von 0 bis 255 annehmen.
Ja, meine natürlich das interessierende Bit von PINA!
Tux schrieb:> Ansonsten sei gesagt dass 1 << PA1 nicht immer 1 ist, sondern nur wenn> PA1 den Wert 0 hat.
Wie jetzt??? Dachte, die 0 im LO-Fall kommt von PINA
Rolf Magnus schrieb:> Zum Beispiel einfach durch Inverieren:> if (!(PINA & (1 << PA1))) {.....}
Also mit drei Klammerpaaren?!
>> if (PINA ^ (1 << PA1)) {.....}>> Wenn man sich nur um das eine Bit kümmert, ja. Aber was ist mit den> anderen 7 Bit von PINA? Der ganze Sinn der und-Verknüpfung inPINA & (1 << PA1)> ist es, das eine Bit, das dich interessiert, aus den restlichen> herauszuschälen.
Verstehe ich nicht ganz.
if (PINA ^ (1 << PA1)) {.....} funktioniert bei mir im Programm übrigens
so nicht.
robur schrieb:> Was ist denn der Wert von PA1 in (1 << PA1)?
Woher sollen wir das wissen - wir kennen weder Deinen Prozessor noch
Deine Toolchain...
Wild geraten: Bei der AVR-libc ist für alle mir geläufigen
AVR-Prozessoren PA1 als Konstante mit dem Wert 1 definiert.
Bitte Bitmanipulation lesen und verstehen - es hat wenig Sinn, hier
einmal wieder alle Grundlagen zu beschreiben.
robur schrieb:> Danke!>> Was ist denn der Wert von PA1 in (1 << PA1)?
(beim avr-gcc auf einem AVR)
1
PA0 0
PA1 1
PA2 2
PA3 3
PA4 4
PA5 5
PA6 6
PA7 7
Welches die Werte von PB0, PB1, PB2, etc. sind, schlüssle ich dir jeztt
nicht auf.
Selbiges für PINB0, PINB1, PINB2, etc. etc.
Das sind alles nur glorifizierte 'Namen' für 0, 1, 2, 3, 4, 5, 6, 7
Meiner Meinung nach hätte man diese ganzen verschiedenen Bezeichnungen
nie einführen sollen, sondern einfach nur BIT0, BIT1, BIT2, ... BIT7
Dann wäre alles klar gewesen, dass zb PA2 dasselbe ist wie PB2 oder PC2
oder PINB2 oder PD2 oder ...
Karl Heinz Buchegger schrieb:> Meiner Meinung nach hätte man diese ganzen verschiedenen Bezeichnungen> nie einführen sollen, sondern einfach nur BIT0, BIT1, BIT2, ... BIT7> Dann wäre alles klar gewesen, dass zb PA2 dasselbe ist wie PB2 oder PC2> oder PINB2 oder PD2 oder ...
Naja, so, finde ich, ist später der Code lesbarer bzw. man sieht dann
schneller, welcher Pin hier grad angesteuert wird.
Mit PA1 weiß man sofort, dass Pin 1 am Port A angesteuert wird bzw.
werden soll, wenn da nur ne 1 steht ist noch lange nicht klar, welcher
Pin hier gesteuert werden soll. ;)
Michael Köhler schrieb:> Karl Heinz Buchegger schrieb:>> Meiner Meinung nach hätte man diese ganzen verschiedenen Bezeichnungen>> nie einführen sollen, sondern einfach nur BIT0, BIT1, BIT2, ... BIT7>> Dann wäre alles klar gewesen, dass zb PA2 dasselbe ist wie PB2 oder PC2>> oder PINB2 oder PD2 oder ...>> Naja, so, finde ich, ist später der Code lesbarer bzw. man sieht dann> schneller, welcher Pin hier grad angesteuert wird.> Mit PA1 weiß man sofort, dass Pin 1 am Port A angesteuert wird
Nö.
Genau das weißt du eben nicht.
PORTB |= ( 1 << PA1 );
was gilt denn nun? Port A oder Port B? Ist das A in PA1 in irgendeiner
Art und Weise relevant? Nein, ist es nicht.
> bzw.> werden soll, wenn da nur ne 1 steht ist noch lange nicht klar, welcher> Pin hier gesteuert werden soll. ;)
was fehlt dir bei
PORTB |= ( 1 << BIT1 );
an Information?
Karl Heinz Buchegger schrieb:> Ist das A in PA1 in irgendeiner> Art und Weise relevant? Nein, ist es nicht
Doch! :-P Zumindest ist es Flexibler. PA1 steht für die Pinbezeichnung
des Prozessors (also ein Konkreter Hardwarepin), im Register könnte
aber der PA1 auch dadurch manipuliert werden, dass Bit5 gesetzt wird.
Ich weiß nicht ob es getan wurde, aber im Prinzip wären auch nochmal
alle "Spezialnamen" interessant, so dass man sagen kann
1
ADCPORT|=(1<<ADC1);
Was automatisch auf jedem Prozessor der einen ADC hat 'richtig'
kompilieren würde.
Überspitzt gesagt:
>> was fehlt dir bei
Karl Heinz Buchegger schrieb:> was fehlt dir bei>> PORTB |= ( 1 << BIT1 );>> an Information?
Nun, vielleicht hab ich mich vertippt und wollte nicht PORTB sondern
PORTA manipulieren. Das sehe ich damit nicht aber mit
PORTB |= (1 << PA1);
sehe ich sofort, dass etwas nicht stimmen kann. Der Code ist IMO (das
heißt: meiner Meinung nach ;)) lesbarer. Im Prinzip wirft das direkt
deine Fragen von weiter oben auf:
Karl Heinz Buchegger schrieb:> was gilt denn nun? Port A oder Port B?
Wollte man mit
Karl Heinz Buchegger schrieb:> PORTB |= ( 1 << BIT1 );
wirklich das BIT1 von PORTB manipulieren?
Bedenke hierbei auch, dass Datenblatt. BIT1 von PORTB heißt dort ebenso
PB1 und nicht BIT1 ;)
Die Bezeichnungen sind IMO durchweg schlüssig und konsequent
eingehalten. Wenn ich die Ports alle mit BIT0, BIT1, BIT2...
durchnummeriere wird spätestens bei zwei Ports unübersichtlich und wer
dann noch meint bei vier Ports den Überblick zu haben hat ein verdammt
gutes Gedächtnis, ich zähle mich nicht dazu.
Und so ganz nebenbei. Niemand hindert dich daran
#define BIT0 0
#define BIT1 1
#define BIT2 2
…
in deinen Quellcode zu schreiben ;)
Michael Köhler schrieb:> durchnummeriere wird spätestens bei zwei Ports unübersichtlich und wer> dann noch meint bei vier Ports den Überblick zu haben hat ein verdammt> gutes Gedächtnis, ich zähle mich nicht dazu.
Na ja.
Das ganze geht ja weiter.
Denn
PORTB |= ( 1 << PA1 );
sollte ja so sowieso nicht im Code stehen.
Da sollte stehen
LED_PORT |= ( 1 << ERROR_LED );
oder überhaupt gleich
LED_ON( ERROR_LED );
so gesehen zieht für mich das Argument mit dem Überblick so nicht ganz.
Denn die Pinnummern kommen dann nur mehr an einer einzigen Stelle
gesammelt vor. und ob da dann steht
1
#define LED_PORT PORTB
2
#define ERROR_LED PB1
3
#define READY_LED PB2
oder
1
#define LED_PORT PORTB
2
#define ERROR_LED BIT1
3
#define READY_LED BIT2
oder meintwegen, wenn man sich an 'BIT' stört
1
#define LED_PORT PORTB
2
#define ERROR_LED P1
3
#define READY_LED P2
schenkt sich nun wirklich nichts.
> Und so ganz nebenbei. Niemand hindert dich daran
Ist schon klar.
Das Problem ist aber, dass regelmässig Anfänger in PA1 etwas
hineininterpretieren, was nicht vorhanden ist. Mit PA1 ist für den
Compiler per se erst mal keine wie immer geartete Verbindung mit Port A
verbunden. Die Bezeichnung suggeriert etwas, was nicht da ist.
Läubis Argumentation kann ich noch was abgewinnen, auch wenn er wohl
auch selbst zugeben muss, dass der Fall etwas an dern Haaren
herbeigezogen ist. Aber möglich wäre er.
Karl Heinz Buchegger schrieb:> Die Bezeichnung suggeriert etwas, was nicht da ist.
Na dein BIT1 tut das aber auch nicht!
Karl Heinz Buchegger schrieb:> Mit PA1 ist für den> Compiler per se erst mal keine wie immer geartete Verbindung mit Port A> verbunden.
Das ist zwar richtig, bei der µC-Programmierung muss man aber IMO immer
eine Verbindung zur Hardware schaffen da der Code so (PA1) oder so
(BIT1) ohne Hardware keinen Sinn macht.
Ach, und übrigens, dein Vorschlag die Ports und Pins entsprechende zu
definieren: Ich weiß nicht wie andere das machen aber ich mach das so
wie du vorgeschlagen hast. d.h. ein LCD-Port heißt bei mir im Code auch
immer so, oder ein OK-Knopf (z.B. PB3) heist bei mir auch
#define OK_Button PB1
Eben wegen der Lesbarkeit ;)
Karl Heinz Buchegger schrieb:> Läubis Argumentation kann ich noch was abgewinnen, auch wenn er wohl> auch selbst zugeben muss, dass der Fall etwas an dern Haaren> herbeigezogen ist. Aber möglich wäre er.
Naja spätestens be den Timern etc. wird doch fröhliches Bit-Würfeln
zwischen denProzessor Familien gespielt... Da würdest du ja auch nicht
plädieren einfach immer Bit0...Bit7 zu verwenden um SFRS zu
konfigurieren oder ;-) Und ein Port ist auch nur ein SFR was zufällig
eine 1:1 Beziehung zur Wirklichkeit hat.
Klar ist es sinnvoll da nicht unötig zu würfeln (gerade wenn man mal
ASM schreiben muss), technisch notwendig ist es nicht das das so 'schön
sortiert' ist, und dass C da keine Typsicherheit bietet ließe sich wohl
nur durch einen z.B. objektorientierten Ansatz gewährleisten.
Ich finde es auch nicht zwangsweise übersichtlicher, es ist aber
konsequent.
Läubi .. schrieb:> Karl Heinz Buchegger schrieb:>> Läubis Argumentation kann ich noch was abgewinnen, auch wenn er wohl>> auch selbst zugeben muss, dass der Fall etwas an dern Haaren>> herbeigezogen ist. Aber möglich wäre er.>> Naja spätestens be den Timern etc. wird doch fröhliches Bit-Würfeln> zwischen denProzessor Familien gespielt... Da würdest du ja auch nicht> plädieren einfach immer Bit0...Bit7 zu verwenden um SFRS zu> konfigurieren oder ;-)
Langsam, langsam. Ich habs nichts gegen die diversen Bitnamen der andern
Register.
Mir gehts ausschliesslich um die Bezeichnungen für die Portpins. Es gibt
ja nicht nur PA1. Da ist ja auch noch eine eigene Bezeichnung für das
Bit im DDR Register, es gibt ein PIN_A0 und ich glaube auch ein PORT_A0
(auch wenn ich jetzt die genauen Schreibweisen auch nicht mehr weiß.
Aber es gibt sie)
Yo, jeder so wie er es mag. Ich denke auch, dass das schlichtweg
Geschmackssache ist. Klar, wenn ich jetzt ein Code schreibe weiß ich
auch was ich da mache. Wenn ich mir den Code aber in einem Jahr anschaue
weiß ich im Leben nicht mehr, was z.B. mit
PORTB |= (1 << PB1);
eingeschaltet wurde. Mit
PORTB |= (1 << ERROR-LED);
weiß ich recht schnell, dass hier eine Fehleranzeige eingeschaltet wurde
ohne mir groß noch mal Schaltung und Code anzusehen. Aber das hält
jeder, wie er denkt ;)
Michael Köhler schrieb:> Ach, und übrigens, dein Vorschlag die Ports und Pins entsprechende zu> definieren: Ich weiß nicht wie andere das machen aber ich mach das so> wie du vorgeschlagen hast. d.h. ein LCD-Port heißt bei mir im Code auch> immer so, oder ein OK-Knopf (z.B. PB3) heist bei mir auch>> #define OK_Button PB1>> Eben wegen der Lesbarkeit ;)
Dazu kommt dann aber i.d.R. ein
#define OK_Port PORTB
Da ist die Info dann eben schon redundant, was es für mich nicht besser
macht.
Gut wäre vielleicht ein Makro, das aus der Definition PB1 dann auch den
richtigen PORTB assoziiert. Hmm gibbs das schon?
Michael Köhler schrieb:> weiß ich recht schnell, dass hier eine Fehleranzeige eingeschaltet> wurde ohne mir groß noch mal Schaltung und Code anzusehen
Also ich schalt meine LEDs immer nach GND ;-P
batman schrieb:> Gut wäre vielleicht ein Makro, das aus der Definition PB1 dann auch den> richtigen PORTB assoziiert. Hmm gibbs das schon?
Gab es hier im Forum irgendwo schon mal ja. Schön ist aber was anderes.
batman schrieb:> Dazu kommt dann aber i.d.R. ein>> #define OK_Port PORTB
In meinem letzten Projekt war es ein Port der verschiedene Status
angezeigt hat. Da gab es dann eine LED für TANK_FULL, eine LED für
PUMP_RUN, eine LED für DOOR_CLOSE usw. Der Port hieß STATUS_PORT, was
für ne Überraschung ;)
Läubi .. schrieb:> Also ich schalt meine LEDs immer nach GND ;-P
Echt? Bei mir ists oft Vcc ;-P
Michael Köhler schrieb:> Echt? Bei mir ists oft Vcc ;-P
Deswegen halte ich es für gewagt, zu sehen was passiert nur am Code ohne
die Schaltung zu kennen :-)
Was ist daran missverständlich? Alles andere ist mir viel zuviel
Schreibarbeit.
Da der Präprozessor nichts ersetzen muß, geht ein Build dann auch noch
ein paar ns schneller. Carpe diem!
mfg.
Läubi .. schrieb:> Deswegen halte ich es für gewagt, zu sehen was passiert nur am Code ohne> die Schaltung zu kennen :-)
DAS hab ich oben schon geschrieben ;)
Michael Köhler schrieb:> bei der µC-Programmierung muss man aber IMO immer> eine Verbindung zur Hardware schaffen da der Code so (PA1) oder so> (BIT1) ohne Hardware keinen Sinn macht.