Anfänger Verständnisfrage zu PORT, PIN und DDR

OP #1738677
Lesenswert?

Hallo,

arbeite mich gerade in die Welt der Mikrokontroller ein. Obwohl ich das 
Tutorial http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial zu 
rate gezogen habe, scheine ich noch etwas nicht verstanden zu haben.

Folgendes Verhalten will ich bei meinem Atmega8 programmieren:

Wenn auf PB0 +5V liegen, dann soll auf PB1 +5V ausgegeben werden.
Das entspricht doch der Aussage:

PBO ist als Eingang festzulegen und wenn dieser gleich 1 ist, dann soll 
der Ausgang PB1 ebenfalls zu 1 werden.

Ich dachte mir, dass durch folgenden gcc-code zu erreichen:
1
#include <avr/io.h>
2

3
int main (void) {
4

5
 DDRB &= ~(1<<PB0); //PBO auf 0 -> als Eingang
6
 DDRB |=  (1<<PB1); //PB1 auf 1 -> als Ausgang
7

8
 //PB0 und PB1 sicherheitshalber auf 0 zurücksetzen
9
 PORTB &= ~(1<<PB0);
10
 PORTB &= ~(1<<PB1);
11

12
if (PINB & (1<<PB0)) { //Wenn PB1 auf 1 steht, dann ist auch die Bedingung 1 (wahr)
13
  PORTB |= (1<<PB1); //Ausgang PB1 auf 1 setzen
14
  }
15
}

Jedoch liefert das Progamm nicht das gewünschte Ergebnis. Eine an PB1 
anliegenden Diode leuchtet SOFORT auch wenn das PB0-Beinchen mit nichts 
verbunden ist (messe ich daran die Spannung, so zeigt mir mein Voltmeter 
1,62V).
Gast #1738705
Lesenswert?

Alexander G. schrieb:

> Wenn auf PB0 +5V liegen, dann soll auf PB1 +5V ausgegeben werden.
> Das entspricht doch der Aussage:
>
> PBO ist als Eingang festzulegen und wenn dieser gleich 1 ist, dann soll
> der Ausgang PB1 ebenfalls zu 1 werden.

Richtig.

> Ich dachte mir, dass durch folgenden gcc-code zu erreichen:
>
> #include <avr/io.h>
>
> int main (void) {
>
>  DDRB &= ~(1<<PB0); //PBO auf 0 -> als Eingang
>  DDRB |=  (1<<PB1); //PB1 auf 1 -> als Ausgang
>
>  //PB0 und PB1 sicherheitshalber auf 0 zurücksetzen
>  PORTB &= ~(1<<PB0);
>  PORTB &= ~(1<<PB1);
>
> if (PINB & (1<<PB0)) { //Wenn PB1 auf 1 steht, dann ist auch die Bedingung 1 
(wahr)
>   PORTB |= (1<<PB1); //Ausgang PB1 auf 1 setzen
>   }
> }
>
>
> Jedoch liefert das Progamm nicht das gewünschte Ergebnis. Eine an PB1
> anliegenden Diode leuchtet SOFORT auch wenn das PB0-Beinchen mit nichts
> verbunden ist (messe ich daran die Spannung, so zeigt mir
> mein Voltmeter 1,62V).

Wenn wirklich nichts am Eingang anliegt, nimmt er irgendeinen 
undefinierten Pegel an ("floating"), der vielleicht als high-Pegel oder 
vielleicht als low-Pegel erkannt wird. Also solltest du bei Eingängen 
immer definierte Pegel anlegen und sie nicht einfach in der Luft 
hängen lassen.
Ansonsten prüft dein Programm nach der Initialisierung ein einziges Mal, 
ob der Eingang 1 ist und schaltet dann entsprechend den Ausgang. Danach 
ist es "zu Ende".
Gast #1738707
Lesenswert?

Hallo Alexander,

dein Programm ist schon zu 80% richtig, hier eine korregierte Version:
1
#include <avr/io.h>
2

3
int main (void) {
4

5
 DDRB &= ~(1<<PB0); //PBO auf 0 -> als Eingang
6
 DDRB |=  (1<<PB1); //PB1 auf 1 -> als Ausgang
7

8
 //PB0 und PB1 sicherheitshalber auf 0 zurücksetzen
9
 PORTB &= ~(1<<PB0);
10
 PORTB &= ~(1<<PB1);
11

12
  while(1) {
13
    if (PINB & (1<<PB0)) { 
14
      PORTB |= (1<<PB1); //Ausgang PB1 auf 1 setzen
15
    }
16
    else {
17
      PORTB &= ~(1<<PB1); //Sonst: PortB aus!
18
    }
19
  }
20

21
}
Dein Programm endet direkt nach dem Vergleich und startet danach von 
ganz vorne. In meiner Version wird der Vergleich in einer Endlosschleife 
ausgeführt.
Dass Du an PB1 1.62V misst, kann verschiedene Ursachen haben:

*Wichtig:* Wenn der PB0 in der Luft hängt, kann das auch zufällig als 
"high" interpretiert werden. Suche hierzu mal nach den Stichworten 
"PullUp" und "PullDown"!

Was für einen Controller verwendest Du überhaupt? Manche Controller 
haben standardmäßig andere Funktionen für ihre Pins aktiviert, z.B. die 
JTAG-Funktion. Die muss möglicherweise abgestellt werden.

Zusatzfrage: Betreibst Du die LED mit einem passenden Vorwiderstand? ;)
OP #1738781
Lesenswert?

Hallo,
tolle Hinweise. Danke!
Auf http://www.rn-wissen.de/index.php/Pullup_Pulldown_Widerstand habe 
ich Infos zum Tipp mit dem Pullup/Pulldown-Widerständen gefunden.

==> Habe jetzt zwischen PB0 und GND einen 10kOhm Widerstand. Dadurch 
messe ich nun auch eine sauberen Pegel von 0V als Ausgangszustand.

Habe mich dann gewundert, warum bei folgendem Ablauf die LED nicht 
leuchten wollte:

- Controller anschalten, indem Spannung angelegt wird
- PB0 war noch offen und nach dem Einschalten mit +5V verbinden
-> Nix passierte. KLAR, denn bis ich PB0 auf +5V gelegt hatte, war der 
Controller schon längst am Programmende. ==> Deswegen die Endlosschleife 
wie es die Beiträge von Schmitty und Rolf auch empfehlen.

Um dies Gegenzuprüfen, nochmals mit altem Programm ohne Schleife:
- Controller aus
- PB0 auf +5V
- Controller an
-> Die LED an PB1 leuchtet wie erwartet.

Anm.: Ich spiele hier mit einem Atmega8 und habe die LED an einem 
Vorwiderstand (wie irgendwie auf www.mikrocontroller.net gelesen :-) )

Danke für die Kommentare -> Haben zum Ziel geführt. Danke!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren