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
voidlcd_init(void){
2
// verwendete Pins auf Ausgang schalten
3
uint8_tpins=(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
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.
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"
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.
>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.
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.
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.
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.
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.
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? ;-)
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 :-)
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.
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?
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.
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.
[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".
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
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.
>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 :-)