Forum: Mikrocontroller und Digitale Elektronik Alles Invertiert


von Dirk S. (glbtrotter)


Lesenswert?

Hallo ich bin neu bei der µC Programmierung

Habe nun meine ersten Gehversuche jedoch sind Ein und Ausgaben komplett 
invertiert!
Ich nutze Atmel Studio 6.1 mit dem STK500 und einem Atmel 8515 Chip

Hier ein kleiner Programm Schnipsel
1
int main(void)
2
{
3
   DDRD=0b00000000;  // PORT D - Switche alles auf 'Eingang' setzen
4
   DDRB=0xFF;    // PORT B - LED's alle auf Ausgang setzten
5
    while(1)
6
    {
7
      // PORTB=0b01010101; // wird invertiert angezeigt
8
    if (PIND & 0b00000001)    // wenn Switch 0 betätigt    
9
     {
10
     PORTB =~0b11111000;  // wird immer angezeigt
11
     }    // Ausgabe nur richtig mit inverter ~!!!!
12
    else
13
     {
14
     PORTB =~0b00000001; // wird angezeigt wenn SW 0 betätigt
15
     }
16
    }
17
}
Eigentlich sollte wenn PIND0-betätig --> doch die if - Anweisung 
durchlaufen werden und nicht die else? oder

und auch hier sind die PORTB Bit Ausgaben nur 'richtig' wenn sie mit 
~invertiert werden?!?

ich habe leider keinerlei Einstellung dafür gefunden? Aber so kann es 
doch auch nicht richtig sein, oder? müsste man ja immer negiert 
denken?!?

Was mache ich falsch?

Grüsse!!
Dirk

von Harry L. (mysth)


Lesenswert?

Die LEDs auf dem STK500 werden aktiv LOW geschaltet.
Das Verhalten ist völlig normal.

von Spess53 (Gast)


Lesenswert?

Hi

>Was mache ich falsch?

Beim STK500 liefert ein gedrückter Taster L und eine LED leuchtet bei L.

MfG Spess

von Thomas E. (thomase)


Lesenswert?

Dirk S. schrieb:
> ich habe leider keinerlei Einstellung dafür gefunden? Aber so kann es
> doch auch nicht richtig sein, oder? müsste man ja immer negiert
> denken?!?
Nicht immer. Sonst kriegst du irgendwann Depressionen. Aber bei µC ist 
es zu ca. 99,37468% so, daß mit dem Betätigen eines Tasters GND 
geschaltet wird und eine LED in aller Regel auch mit GND angesteuert 
wird.

mfg.

von Bernd S. (bernds1)


Lesenswert?

Dirk S. schrieb:
>
> Was mache ich falsch?
>
Gar nichts :-)
Es ist alles richtig so. Schau dir mal die Schaltung vom STK500 an. Da 
siehst du, daß die LED's an +5V hängen. Das heißt also, wenn sie 
leuchten sollen, muß vom Controller ein LOW am Ausgang kommen.

Und mit den Tastern ist es genauso. Sie hängen zwischen dem Eingang und 
GND. Wenn sie offen sind, sorgt ein Pull-up von 10k dafür, daß der 
Eingang auf HIGH liegt. Und wenn du den Taster drückst, legst du LOW an 
den Eingang.

von Karl H. (kbuchegg)


Lesenswert?

Dirk S. schrieb:

> ich habe leider keinerlei Einstellung dafür gefunden? Aber so kann es
> doch auch nicht richtig sein, oder? müsste man ja immer negiert
> denken?!?

Du gewöhnst dich daran.
Genauso wie du dich daran gewöhnt hast, die oberste Farbe in einer 
Verkehrsampel 'rot' zu nennen. Man hätte sie genausogut auch 'blau' 
nennen können. Dann würden wir eben von blauen Lippen sprechen und 
hätten blaue Erdbeeren. Es ist eine reine Konvention, dass wir für eine 
bestimmte Farbe das Wort 'rot' benutzen, aber beileibe kein Naturgesetz.

Und genauso auch hier.
Es ist kein Naturgesetz, dass eine 1 die Bedeutung hat 'eingeschaltet'. 
Es ist eine reine Konvention, die man treffen kann, aber nicht muss. Und 
wenn es Gründe gibt, warum anders rum (0 bedeutet eingeschaltet) besser 
oder einfacher ist, dann macht man das eben so.

von Svenska (Gast)


Lesenswert?

Und statt immer negativ zu denken, kannst du auch dem Compiler sagen, 
dass er vor der Ausgabe invertieren soll. Den Taktzyklus hast du 
sicherlich noch übrig. :-)

von Bernd S. (bernds1)


Lesenswert?

Noch einfacher kann man es sich machen, indem man sich gar nicht auf 
"aus" oder "ein" festlegt. Man muß wissen, wie die Schaltung aussieht, 
die am Controller dranhängt. Und das ist alles. Eine 1 bedeutet immer, 
daß am entsprechenden Pin ein HIGH ausgegeben wird. Und bei einer 0 dann 
eben LOW. Und wenn man jetzt weiß, daß die LED mit der Anode auch an 
HIGH angeschlossen ist, dann weiß man auch, daß sie nicht leuchtet, wenn 
auf beiden Seiten das gleiche Signal (nämlich HIGH) anliegt. Ok?

Und bei den Tastern ist es genauso. Wenn man weiß, daß bei nicht 
betätigten Tastern immer ein HIGH am Eingang anliegt, muß man dann im 
eigenen Programm auf "LOW" abfragen, wenn man wissen will, ob der Taster 
gedrückt ist. Denk nochmal in Ruhe drüber nach, ist eigentlich ganz 
einfach :-)

von Karl H. (kbuchegg)


Lesenswert?

ZUmal man in C ja auch die Möglichkeiten hat, sich das ganze so zu 
abstrahieren, dass man
* im Programmtext dieses 'Detail' gar nicht berücksichtigen muss
* man dieses 'Detail' an einer Stelle zentral zusammenfasst
* man Ausgangspins sowieso normalerweise nicht durch Zuweisung eines 
Wertes an den kompletten Port erledigt

1
#define LED_PORT PORTB
2
#define LED_BIT  PB1
3
4
#define TURN_LED_ON   LED_PORT &= ~( 1 << LED_BIT )
5
#define TURN_LED_OFF  LED_PORT |= ( 1 << LED_BIT )
6
7
#define KEY_PRESSED   (PIND & ( 1 << PD0 ))
8
9
10
int main(void)
11
{
12
   DDRD=0b00000000;  // PORT D - Switche alles auf 'Eingang' setzen
13
   DDRB=0xFF;    // PORT B - LED's alle auf Ausgang setzten
14
15
   while(1)
16
   {
17
     if (KEY_PRESSED)    // wenn Switch 0 betätigt    
18
     {
19
       TURN_LED_ON;
20
     }
21
     else
22
     {
23
       TURN_LED_OFF;
24
     }
25
   }
26
}

So sieht das im eigentlichen Programmtext doch schon viel besser aus.

von Timm T. (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> So sieht das im eigentlichen Programmtext doch schon viel besser aus.

Das ist für größere Programme aber bedingt Mist, weil Du dann immer 
erstmal schauen musst, wie Du TURN_LED_ON definiert hast. Andererseits 
kann es eine große Erleichterung sein, wenn Du es mehrmals benutzt, und 
die LED dann an einem anderen Pin hängen soll.

Das muss man sich also gut überlegen, wie weit man hier abstrahieren und 
wegdefinieren will. Ist für einen Anfänger vielleicht nicht so geeignet.

von Karl H. (kbuchegg)


Lesenswert?

Timm Thaler schrieb:
> Karl Heinz Buchegger schrieb:
>> So sieht das im eigentlichen Programmtext doch schon viel besser aus.
>
> Das ist für größere Programme aber bedingt Mist, weil Du dann immer
> erstmal schauen musst, wie Du TURN_LED_ON definiert hast.

Inwiefern muss ich das 'dauernd nachsehen'?

Wenn ich das eigentliche Programm schreibe, reicht mir das 'ON' um zu 
wiss....


Ach jetzt versteh ich dich. (denke ich)
ON ist nicht eindeutig. Ist damit 'Bit auf 1' oder 'Licht einschalten' 
gemeint.
OK. Das ist aber eine Frage von gut gewählten Bezeichnungen. Geb ich dir 
recht - ON ist in diesem Zusammenhang vielleicht wirklich nicht so gut 
gewählt. Für mich war zwar klar, dass TURN_LED_ON impliziert, dass 
danach die LED leuchtet, aber das ist meine Konvention, die darauf 
beruht, dass ich mich im Programmtext selber um so Kleinigkeiten wie 
"0-Bit für einschalten" nicht mehr kümmern will. Eine LED auf ON setzen, 
bedeutet für mich automatisch, dass sie danach leuchtet (egal ob das Bit 
dazu auf 0 oder 1 gehen muss). Für jemand anderen mag das anders sein.

von Timm T. (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Eine LED auf ON setzen,
> bedeutet für mich automatisch, dass sie danach leuchtet (egal ob das Bit
> dazu auf 0 oder 1 gehen muss)

Das geht aber zum Beispiel bei LEDs noch weiter. Auch wenn das den TE 
jetzt verwirren sollte.

Du kannst eine LED (geschalten gegen +5V) einschalten, indem Du das Pin 
auf Ausgang setzt. Pin auf high => LED aus, Pin auf low => LED ein.

Du kannst diese LED aber auch einschalten, indem Du den Pin auf low 
setzt. Pin auf Ausgang => LED ein, Pin auf Eingang => LED aus. Also 
nicht über PORTx, sondern über DDRx. Der Ausgang wirkt dann wie ein 
OpenCollector, nicht wie eine Push-Pull-Stufe.

Machst Du das jetzt mit einem Port, an dem noch andere Sachen hängen, 
kann das eigentlich klare TURN_LED_ON, welches in Deinem Beispiel ja 
schonmal den ganzen Port verändert, zu völlig unerklärlichen Fehlern 
führen, weil plötzlich Ausgänge zu Eingängen werden, und sich das in 
ganz anderen Programmteilen auswirkt. Und nach solchen Fehlern kann man 
tagelang suchen... ;-)

Also Abstraktion ja, aber mit Bedacht.

von Karl H. (kbuchegg)


Lesenswert?

Timm Thaler schrieb:

> Machst Du das jetzt mit einem Port, an dem noch andere Sachen hängen,
> kann das eigentlich klare TURN_LED_ON, welches in Deinem Beispiel ja
> schonmal den ganzen Port verändert, zu völlig unerklärlichen Fehlern
> führen, weil plötzlich Ausgänge zu Eingängen werden, und sich das in
> ganz anderen Programmteilen auswirkt. Und nach solchen Fehlern kann man
> tagelang suchen... ;-)

Schau nochmal genau.
Genau das hab ich ausgebaut um damit den 3.ten Punkt zu illustrieren, 
dass man solche komplett-Portzuweisungen in der Praxis sowieso nicht 
macht.

> Also Abstraktion ja, aber mit Bedacht.

Kein Einwand.

von Dirk S. (glbtrotter)


Lesenswert?

Danke schon mal für die vielen Antworten!!
Schön das man mit solchen Anfängerfragen nicht gleich 'gesteinigt' wird 
:-)

Ok mit LOW und HIGH hab ich verstanden. Macht beim weiteren beschalten 
von Transistoren und Relais usw. ja auch Sinn.

ABER wenn ich in meinem obigen Beispiel die If Anweisung wie folgt 
abändere:

if (PIND & 0b11111110)
So sollte es doch funktionieren? oder? tut es aber nicht?

Des Weiteren auch bei dem Beispiel vom Karl Heinz sind alle LED's an un 
bei "Key_Pressed" geht 1 aus!!

Habe ich noch ein weiteres Verständnis Problem?
Sorry für die wirklich blöde Fragerei!

Der Dirk

von Karl H. (kbuchegg)


Lesenswert?

Schnellschuss:

Nur weil auf dem STK500 eine gedrückte Taste ein 0 liefert, bedeutet das 
nicht, dass es dich vom Einschalten des Pullup Widerstandes entbindet
1
int main()
2
{
3
  DDRD = 0x00;
4
  PORTD = ( 1 << PD0 );
5
6
  while( 1 )
7
  {
8
    if( PIND & ( 1 << PD0 ) )
9
      ....

Ohne Pullup wechelst der Eingangspin je nachdem ob die Taste gedrückt 
ist oder nicht zwischen '0' und 'Eingang offen'.

'Eingang offen' ist aber kein definierter Pegel. Das kann 0 sein, das 
kann 1 sein, je nachdem welches elektromagnetische Feld sich gerade in 
der Gegend rumtreibt.


Und bitte: gewöhn dir Bitschreibweisen gleich wieder ganz schnell ab. Es 
gibt Fälle, in denen sie sinnvoll ist. Aber in den meisten Fällen, ist 
es die schlechteste Schreibweise, die du finden kannst.

von hilmar (Gast)


Lesenswert?

> Nur weil auf dem STK500 eine gedrückte Taste ein 0 liefert, bedeutet das
> nicht, dass es dich vom Einschalten des Pullup Widerstandes entbindet

Im Prinzip hat Karl-Heinz Recht, aber in diesem Falle muß man das nicht. 
Die Pull-up-Widerstände sind hardwaremäßig auf dem STK vorhanden (10k).

In einer eigenen Schaltung kann man sich die aber (meist) sparen, denn 
den µC hat schon welche integriert, die man softwaremäßig einschalten 
kann. Das meinte Karl-Heinz.

von Dirk S. (glbtrotter)


Lesenswert?

Das es ohne Pullup zu undefinierten Zuständen kommt ist klar!

Aber ich möchte ja ja nicht die Pull Up's ein-/ausschalten sondern 
lediglich die definierten Pegel abfragen und da hakt es bei mir zur 
Zeit. Ich möchte Grundlegend das System verstehen bevor ich ernsthaft 
beginne.

Ok die Bitschreibweise habe ich für mein Verständnis bisher genutzt. Ist 
sicherlich nicht die übersichtlichste.

Danke für Eure Hilfe!!!

von hilmar (Gast)


Lesenswert?


von J. T. (chaoskind)


Lesenswert?

> Aber ich möchte ja ja nicht die Pull Up's ein-/ausschalten sondern
> lediglich die definierten Pegel abfragen und da hakt es bei mir zur
> Zeit. Ich möchte Grundlegend das System verstehen bevor ich ernsthaft
> beginne.

Und genau für die definierten Pegel sorgen ja deine PullUps. Also 
entweder hast du sie in deine Schaltung eingeplant oder du solltest sie, 
meinetwegen auch ohne dir Gedanken drüber zu machen, einschalten. Denn 
sonst hast du einem der Fälle Taster gedrückt/nicht gedrückt gar keinen 
definierten Pegel.

von hilmar (Gast)


Lesenswert?

> entweder hast du sie in deine Schaltung eingeplant

Nochmal: Sie sind bereits im STK körperlich vorhanden (10k), müssen also 
nciht eingeschaltet werden. Ok?

von Dirk S. (glbtrotter)


Lesenswert?

Also so langsam komme ich dahinter :-)
Danke für Eure Hilfe
Hab mit eine uint Variable angelegt in die ich das 'Eingangsregister' 
schreibe und dieses mit ein paar Test 'cases' wieder anzeigen lassen. 
FUNZT!
1
uint8_t Mein_PortD;
2
3
int main(void)
4
{
5
  DDRD=0x00;  // PORT D - Switche alles auf 'Eingang' setzen
6
  DDRB=0xFF;    // PORT B - LED's alle auf Ausgang setzten
7
8
  Mein_PortD = 0;
9
  
10
  while(1)
11
  {
12
    Mein_PortD = PIND;
13
  
14
    switch (Mein_PortD)
15
    {
16
    case (0xFF-1): 
17
      PORTB=~0b00000001;
18
      break;
19
    case (0xFF-3):
20
      PORTB=~0b00000011;
21
      break;
22
    case (0xFF-4):
23
      PORTB=~0b00000100;
24
      break;
25
    default:
26
      PORTB=~0b00000000;
27
    }
28
  }
29
}
erste Erkenntnisse :-)

von Karl H. (kbuchegg)


Lesenswert?

UNd als nächstes gewöhnst du dir diese 'kompletter Port' Rundumschlag 
Geschichten ab. Das bringt dich nämlich nicht weiter.


Wenn du wissen willst, ob ein bestimmer Eingangspin zb. der Pin PD3, auf 
1 ist
1
   if( PIND & ( 1 << PD3) )
2
     tu was

wenn du wissen willst, ob selbiger Pin auf 0 ist
1
   if( !(PIND & ( 1 << PD3)) )
2
     tu was


wenn du einen bestimmten Pin, zb PB5 am AUsgang auf 1 schalten willst
1
   PORTB |= ( 1 << PB5 );

wenn du denselben Pin auf 0 schalten willst
1
   PORTB &= ~( 1 << PB5 );


#Das# sind deine 'Arbeitspferde'. Diese Operationen musst du im Schlaf 
beherrschen.


Bitmanipulation

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:

> #define KEY_PRESSED   (PIND & ( 1 << PD0 ))

Bei einem Active-Low-Schalter (auf dem STK500?) müsste dies aber heißen:

#define KEY_PRESSED   (!(PIND & ( 1 << PD0 )))

Gruß,

Frank

von Dirk S. (glbtrotter)


Lesenswert?

Hallo also ich finde Karl Heinz hat die 'Grundfunktionen' heute Mittag 
sehr gut erklärt und zusammengefasst.

Jetzt nachdem ich gecheckt habe das das STK500 die Eingänge aktiv auf 
High und durch gedrückte Switches auf LOW gezogen werden, fällt mir 
vieles Leichter!!

Danke für diese ersten Erkenntnisse, jetzt fängt es an Spaß zu machen!!!

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.