www.mikrocontroller.net

Forum: Compiler & IDEs Anfänger Verständnisfrage zu PORT, PIN und DDR


Autor: Alexander G. (grossmann200)
Datum:

Bewertung
0 lesenswert
nicht 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:
#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).

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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".

Autor: Schmitty (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Alexander,

dein Programm ist schon zu 80% richtig, hier eine korregierte Version:
#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);

  while(1) {
    if (PINB & (1<<PB0)) { 
      PORTB |= (1<<PB1); //Ausgang PB1 auf 1 setzen
    }
    else {
      PORTB &= ~(1<<PB1); //Sonst: PortB aus!
    }
  }

}
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? ;)

Autor: Alexander G. (grossmann200)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Martin e. C. (eduardo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst die Pullup von Controller einschalten, dann brauchst du keine 
10kOhm Widerstand.

z.B
/* Pins auf Eingang */
  DDRB &= ~((1 << DDB0) | (1 << DDB1) | (1 << DDB2));

/* Interne Pull-Up Widerstände einschalten */
  PORTB |= ((1<<PB0)|(1<<PB1)|(1<<PB2));

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.