Forum: Mikrocontroller und Digitale Elektronik Als Ausgang gesetzt als Eingang erkannt?


von DerNeue (Gast)


Lesenswert?

Guten Morgen,

ich melde mich mal wieder, aufgrund eines weiteren Verständnisproblems.
Ich habe mit Hilfe des LCD Tutorials erfolgreich und ohne Probleme ein 
LCD zum laufen bekommen und nutze dieses jetzt, anstelle von LEDs, als 
Visualisierung für weitere Versuche.

Nun habe ich ein Taster an den Eingang (PD6) eines Atmega8 gedrahtet und 
habe mir auf dem LCD das betätigen des Tasters anzeigen lassen. Soweit 
so gut hat alles funktioniert.

Jetzt kommt die Sache die ich nicht ganz verstehe.
Wenn ich am Anfang des Programms die Anschlüsse PD6 und PD7 als Ausgang 
schalte sollte die Sache mit dem Taster meines Verständnisses nach nicht 
mehr funktionieren.

Allerdings klappt dies trotzdessen immernoch. Sobald ich den Taster 
drücke zeigt mir das LCD die reaktion an. Demnach sieht es so aus, dass 
ich ein als Ausgang gesetzten Anschluss im Program trotzdem als Eingang 
auslesen kann. Wie kann das sein?

*LCD.h:*
1
...
2
#ifndef LCD_PORTS
3
#define LCD_PORTS
4
 
5
#define LCD_PORT      PORTD
6
#define LCD_DDR       DDRD
7
 
8
// 4 Bit LCD Datenbus DB4-DB7, das unterste Bit DB4 kann auf den Portbits 0..4 liegen
9
 
10
//  LCD DB4-DB7 <-->  PORTC Bit PC0-PC3
11
#define LCD_DB        PD0
12
 
13
// LCD Steuersignale RS und EN
14
 
15
//  LCD RS      <-->  PORTC Bit PC4     (RS: 0=Data, 1=Command)
16
#define LCD_RS        PD4
17
 
18
//  LCD EN      <-->  PORTC Bit PC5     (EN: 1-Impuls für Daten)
19
#define LCD_EN        PD5
20
 
21
#endif // LCD_PORTS

*LCD.c:*
1
void lcd_init( void ) {
2
    // verwendete Pins auf Ausgang schalten
3
    uint8_t pins = (0x0F << LCD_DB) |   // 4 Datenleitungen
4
                   (1<<LCD_RS) |        // R/S Leitung
5
                   (1<<LCD_EN);         // Enable Leitung
6
    LCD_DDR |= pins;
7
 
8
    // initial alle Ausgänge auf Null
9
    LCD_PORT &= ~pins;
10
 
11
    // warten auf die Bereitschaft des LCD
12
    _delay_ms( LCD_BOOTUP_MS );
13
 
14
    // Soft-Reset muss 3mal hintereinander gesendet werden zur Initialisierung
15
    lcd_out( LCD_SOFT_RESET );
16
    _delay_ms( LCD_SOFT_RESET_MS1 );
17
 
18
    lcd_enable();
19
    _delay_ms( LCD_SOFT_RESET_MS2 );
20
 
21
    lcd_enable();
22
    _delay_ms( LCD_SOFT_RESET_MS3 );
23
 
24
    // 4-bit Modus aktivieren 
25
    lcd_out( LCD_SET_FUNCTION |
26
             LCD_FUNCTION_4BIT );
27
    _delay_ms( LCD_SET_4BITMODE_MS );
28
 
29
    // 4-bit Modus / 2 Zeilen / 5x7
30
    lcd_command( LCD_SET_FUNCTION |
31
                 LCD_FUNCTION_4BIT |
32
                 LCD_FUNCTION_2LINE |
33
                 LCD_FUNCTION_5X7 );
34
 
35
    // Display ein / Cursor aus / Blinken aus
36
    lcd_command(LCD_SET_DISPLAY |
37
                LCD_DISPLAY_ON |
38
                LCD_CURSOR_OFF |
39
                LCD_BLINKING_OFF); 
40
 
41
    // Cursor inkrement / kein Scrollen
42
    lcd_command( LCD_SET_ENTRY |
43
                 LCD_ENTRY_INCREASE |
44
                 LCD_ENTRY_NOSHIFT );
45
 
46
    lcd_clear();
47
}

*main.c:*
1
#include <avr/io.h>
2
#include "lcd.h"
3
#include <util/delay.h> 
4
int main(void)
5
{
6
    
7
  DDRD = 0b11111111;
8
  lcd_init();
9
  
10
    while(1)
11
    {
12
    if ( PIND & (1<<PD6) )
13
    {
14
      lcd_setcursor(0,0);
15
      lcd_string("Knopf gedrückt");
16
      
17
    }
18
    
19
  
20
    }
21
 
22
    return 0;
23
}

Was übersehe ich da?

Gruß

DerNeue

von Dussel (Gast)


Lesenswert?

DerNeue schrieb:
> Was übersehe ich da?
Je nachdem, wie Ausgang und der Taster geschaltet sind, erzeugst du 
einen Kurzschluss. Das ist schonmal gar nicht gut. Zwar weiß ich nicht, 
wie das das Verhalten erklären kann, aber außerhalb der Spezifikation 
ist sehr viel möglich.

von hagi (Gast)


Lesenswert?

Du liest den Ausgangslatch ein. Hier wird vermutlich
zufällig das Bit auf ein Wert stehen der als
"Taste gedrückt" erkannt wird.

Zeig doch in deinem Display beide Tastenzustände an:
"gedrückt" else "nicht gedrückt"

von Dussel (Gast)


Lesenswert?

Gerade ist mir eine mögliche Erklärung eingefallen: Soweit ich weiß, 
kann man PIN immer lesen und es zeigt auch immer an, was gerade für ein 
Zustand am physikalischen Pin anliegt. Bei einem Ausgang ist das immer 
der Zustand des Ausgangs. Wenn der 5V ausgibt, ließt PIN ein High ein. 
Wenn der Taster einen Kurzschluss verursacht, kann der Pin nicht genug 
Strom liefern, so dass das Potential anliegt, auf das der Taster 
kurzschließt. Un dieser Zustand wird eingelesen. Gut ist das aber für 
den Controller nicht.

von LostInMusic (Gast)


Lesenswert?

>Wie kann das sein?

Solange der Taster nicht gedrückt ist, ist die Sache klar: Der 
Ausgangstransistor im µC zieht den Pin auf VCC. Das will er auch noch 
tun, wenn Du den Taster drückst, aber der Taster zwingt den Pin 
erbarmungslos auf GND und ebendieses liest Du korrekt bei einer Abfrage 
des Pinlevels ein. Durch den Ausgangstransistor fließt in diesem Fall 
ein hoher Strom, der ihn auch zerstören kann.

von DerNeue (Gast)


Lesenswert?

LostInMusic schrieb:
>>Wie kann das sein?
>
> Solange der Taster nicht gedrückt ist, ist die Sache klar: Der
> Ausgangstransistor im µC zieht den Pin auf VCC. Das will er auch noch
> tun, wenn Du den Taster drückst, aber der Taster zwingt den Pin
> erbarmungslos auf GND und ebendieses liest Du korrekt bei einer Abfrage
> des Pinlevels ein. Durch den Ausgangstransistor fließt in diesem Fall
> ein hoher Strom, der ihn auch zerstören kann.

Hm ich hatte den Anschluss zwar als Ausgang deklariert aber noch nicht 
auf high geschaltet. Der Taster den ich benutze legt den Anschluss auf 
High sobald ich diesen betätige. Damit würde der Ausgang doch auf dem 
selben Potential liegen.

hagi schrieb:
> Du liest den Ausgangslatch ein. Hier wird vermutlich
> zufällig das Bit auf ein Wert stehen der als
> "Taste gedrückt" erkannt wird.
>
> Zeig doch in deinem Display beide Tastenzustände an:
> "gedrückt" else "nicht gedrückt"

Wenn ich dies tu, dann funktioniert der taster ebenfalls. es zeigt mir 
die Zustände richtig an, obwohl ich den Anschluss als Ausgang deklariert 
habe.

von Amateur (Gast)


Lesenswert?

Meist ist es ein anderes Register, das für die Ausgabe und für die 
Eingabe zuständig.
Du kannst jederzeit einen Wert ausgeben und dann den Zustand des Ports 
lesen.
Schreibst Du den Wert "1" in einen Pin, schließt diesen Kurz, so kannst 
Du den Status des Anschlusses ermitteln.

Dies kann sogar zur Doppeldeutigkeit führen.
Schreibst Du z. B. 00001000 in einen Port, so bekommst Du beim Lesen 
auch diesen Wert zurückgeliefert. Liest Du aber via PINx-Befehl, so kann 
es sein, dass Du 10001000 zurück bekommst in diesem Falle weil z.B. Pin7 
ein Eingang ist und dort gerade eine eins anliegt.

von Samuel Canadi (Gast)


Lesenswert?

Das Ganze ist ganz einfach:

- Du deklarierst den Pin völlig richtig als Ausgang.
- Du schreibst nichts in den Ausgang, also ist dieser LOW.
- Du fragst den Status des Pins ab. Dieser ist LOW, weil der 
Ausgangstreiber den Pin auf Masse zieht.

- Jetzt drückst du den Taster.
- Der Taster zieht den Pin mit aller Macht auf VCC, da der 
Ausgangstreiber nicht übermäßig viel Strom bringt.
- Du liest wieder den Status des Pins ein, dieser ist jetzt HIGH, da der 
Taster einen Kurzschluss gegen VCC erzeugt.

Willst du nicht den tatsächlichen Status des Pins (PIN-Register) sondern 
den des Ausgangstreibers anschauen, so musst du das PORT-Register 
auslesen.

von DerNeue (Gast)


Lesenswert?

Samuel Canadi schrieb:
> Das Ganze ist ganz einfach:
>
> - Du deklarierst den Pin völlig richtig als Ausgang.
> - Du schreibst nichts in den Ausgang, also ist dieser LOW.
> - Du fragst den Status des Pins ab. Dieser ist LOW, weil der
> Ausgangstreiber den Pin auf Masse zieht.
>
> - Jetzt drückst du den Taster.
> - Der Taster zieht den Pin mit aller Macht auf VCC, da der
> Ausgangstreiber nicht übermäßig viel Strom bringt.
> - Du liest wieder den Status des Pins ein, dieser ist jetzt HIGH, da der
> Taster einen Kurzschluss gegen VCC erzeugt.
>
> Willst du nicht den tatsächlichen Status des Pins (PIN-Register) sondern
> den des Ausgangstreibers anschauen, so musst du das PORT-Register
> auslesen.

Wunderbar.. mir war die Arbeitsweise des Ausgangstreibers noch nicht 
ganz bewusst. Ich war immer der meinung das das PIN-Register bei einem 
als Ausgang deklariertem Anschluss nicht beschrieben wird.
Dann werd ich diesen Versuch mal lassen bevor ich mir den uC schrotte.

von DerNeue (Gast)


Lesenswert?

An der Stelle hätte ich noch eine Frage:

Welche Methode einen Taster am uC anzuschließen bevorzugt ihr?

1. Bei Betätigung wird der Pin auf Low gezogen. (Mit pull-up)
2. Bei Betätigung wird der Pin auf High gezogen.(Mit pull-up)

Und wieso? ;-)

von DerNeue (Gast)


Lesenswert?

Das zweite meinte ich natürlich mit pull-down

von npn (Gast)


Lesenswert?

DerNeue schrieb:
> Wunderbar.. mir war die Arbeitsweise des Ausgangstreibers noch nicht
> ganz bewusst. Ich war immer der meinung das das PIN-Register bei einem
> als Ausgang deklariertem Anschluss nicht beschrieben wird.
Nicht ganz.
Das PIN-Register spiegelt immer den Wert des Pins wider, egal ob Eingang 
oder Ausgang.
Das PORT-Register enthält im Falle eines Ausgangs immer den Zustand des 
Ausgangstreibers (high/low) und im Falle eines Eingangs den Zustand des 
Pullup-Widerstandes (ein/aus).
> Dann werd ich diesen Versuch mal lassen bevor ich mir den uC schrotte.
Stimmt, das wäre besser. Auf Dauer könnte der das übelnehmen :-)

von San L. (zwillingsfreunde)


Lesenswert?

DerNeue schrieb:
> 1. Bei Betätigung wird der Pin auf Low gezogen. (Mit pull-up)

Auf low ziehen. Die meisten uC's verfügen über interne Pull-Ups welche 
man Softwaremässig aktivieren kann. Somit sparrt man Platz & je nach 
Stückzahl auch Geld.

von npn (Gast)


Lesenswert?

DerNeue schrieb:
> Und wieso? ;-)

Normalerweise meist das erstere (Taster gegen GND, dazu Pullup).
Vorteil: Der Pullup ist schon im µC enthalten.

von DerNeue (Gast)


Lesenswert?

San Lue schrieb:
> DerNeue schrieb:
> 1. Bei Betätigung wird der Pin auf Low gezogen. (Mit pull-up)
>
> Auf low ziehen. Die meisten uC's verfügen über interne Pull-Ups welche
> man Softwaremässig aktivieren kann. Somit sparrt man Platz & je nach
> Stückzahl auch Geld.

npn schrieb:
> DerNeue schrieb:
> Und wieso? ;-)
>
> Normalerweise meist das erstere (Taster gegen GND, dazu Pullup).
> Vorteil: Der Pullup ist schon im µC enthalten.

Ok das klingt logisch.. gibt es denn bestimmte situationen bei denen man 
die zweite Variante nutzen sollte?

von npn (Gast)


Lesenswert?

DerNeue schrieb:
> Ok das klingt logisch.. gibt es denn bestimmte situationen bei denen man
> die zweite Variante nutzen sollte?

Zum Beispiel, wenn in einem Gerät die Taster schon verdrahtet sind und 
bereits einseitig an VCC liegen. Dann muß man allerdings in die 
Schaltung noch Pulldown-Widerstände einsetzen, weil die nicht im µC 
enthalten sind.

von DerNeue (Gast)


Lesenswert?

npn schrieb:
> DerNeue schrieb:
> Ok das klingt logisch.. gibt es denn bestimmte situationen bei denen man
> die zweite Variante nutzen sollte?
>
> Zum Beispiel, wenn in einem Gerät die Taster schon verdrahtet sind und
> bereits einseitig an VCC liegen. Dann muß man allerdings in die
> Schaltung noch Pulldown-Widerstände einsetzen, weil die nicht im µC
> enthalten sind.

Ok das passiert ja nur wenn man fertige module oder ähnliches nimmt.. 
bei einer selbst erstellten schaltung/platine sollte man also immer die 
GND variante nehmen.

von LostInMusic (Gast)


Lesenswert?

Um es mal ganz systematisch abzuhandeln, sind in folgender Tabelle alle 
zwölf möglichen Situationen aufgelistet:

1
 DDR  PORT  Taster     Pin ist verbunden mit...                            Pin-Potential
2
 ---------------------------------------------------------------------------------------
3
 0    0     offen      nichts                                              undefiniert
4
 0    0     --> GND    GND über Taster                                     GND
5
 0    0     --> VCC    VCC über Taster                                     VCC
6
7
[0    1     offen      VCC über µC-internen Pullup                         VCC]
8
[0    1     --> GND    VCC über µC-internen Pullup und GND über Taster     GND]
9
 0    1     --> VCC    VCC über µC-internen Pullup und VCC über Taster     VCC
10
11
 1    0     offen      GND über Ausgangstreiber                            GND
12
 1    0     --> GND    GND über Ausgangstreiber und GND über Taster        GND
13
 1    0     --> VCC    GND über Ausgangstreiber und VCC über Taster (*)    VCC
14
15
 1    1     offen      VCC über Ausgangstreiber                            VCC
16
 1    1     --> GND    VCC über Ausgangstreiber und GND über Taster (*)    GND
17
 1    1     --> VCC    VCC über Ausgangstreiber und VCC über Taster        VCC

(*) Achtung: Kurzschluss des Ausgangstreibers!

Die Standard-Anschlussart eines Tasters an einen µC-Pin und dessen 
Abfrage ist durch die beiden in "[ ]" gesetzten Zeilen repräsentiert: 
Der Taster wird gegen GND angeschlossen und der µC-interne 
Pullup-Widerstand aktiviert durch DDR=0 und PORT=1. Dann wird über das 
PIN-Register bei ungedrücktem Taster eine "1" eingelesen, und bei 
gedrücktem Taster eine "0".

von Paul Baumann (Gast)


Lesenswert?

@LostInMusic

Das ist ein hilfreicher Beitrag!

Zum Dank ein Ständchen:
http://www.youtube.com/watch?v=e1IkdZIdCP8

MfG Paul

von Georg (Gast)


Lesenswert?

LostInMusic schrieb:
> Um es mal ganz systematisch abzuhandeln

Der Vollständigkeit halber: Das ist eben Atmega, andere Prozessoren 
verhalten sich anders. Es gibt eine ganze Reihe von möglichen 
Beschaltungen von I/O-Pins.

Georg

von sagq35z (Gast)


Lesenswert?

DerNeue schrieb:
> Dann werd ich diesen Versuch mal lassen bevor ich mir den uC schrotte.


Deswegen empfiehlt sich hier gerade bei Experimentalboards ein 
Serienwiderstand zum GPIO hin.

Andersrum dreht man sich hier auch im Kreis :-) Diejenigen, die das
so planen, wissen um das Problem und fallen nicht so schnell drauf rein.
Aber wenn der eine die HW entwickelt und der andere die SW, dann ist das
schon schön, wenn der Softwerker nicht alle Nase lang den µC beschädigt.

von LostInMusic (Gast)


Lesenswert?

>Das ist eben Atmega,

...und auch ATtiny, oder anders gesagt: Alle µCs der AVR-8bit-Familie 
von Atmel.

>andere Prozessoren verhalten sich anders. Es gibt eine ganze Reihe von
>möglichen Beschaltungen von I/O-Pins.

Selbstverständlich :-)

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.