Hi,
ich rätsel seit gestern an einem Problem, welches das funktionieren
meiner Tasten verhindert. Habe einen Mega8 bei welchem je ein Taster an
PD5, PD6 und PD7 hängt. An PB0, PB1 und PB2 hängt je eine LED. Die LED's
leuchten auch schon schön wenn ich sie mit nem Delay an und ausmachen
lass, aber der Code (siehe unten) mit meinen Tasten funzt nicht so
richtig, eigentlich macht der gar nix! Auf nen Tastendruck passiert rein
gar nix. Habe schon die externen Widerstände mal abgelötet und die
internen aktiviert, ohne Erfolg. Es ist außer den 3 Tasten und 3 LED's
auch nix weiter dran, also weder LCD noch SPI!
Seltsam ist auch, dass nach aufspielen der Software auf den Mega8 nur
die LED an PB0 leutet, die anderen sind aus. Verkabelung passt
eigentlich, die Taster sind Active-Low und auch korrekt verkabelt,
Durchgang haben die auch, wenn man se drückt...
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include<inttypes.h>
4
#include<stdint.h>
5
#ifndef F_CPU
6
#define F_CPU 4000000UL
7
#endif
8
9
/* Einfache Funktion zum Entprellen eines Tasters */
100ms reichen nicht zum Loslassen, ein Mensch drückt etwa 300..1000ms
lang.
Tastenbetätigungen muß man außerdem in der Mainloop auswerten. Es ist
ziemlich witzlos, wenn Betätigungen nur beim Power-On erlaubt sind.
Versuch einfach mal, nur eine Taste zu entprellen und eine LED damit zu
togglen, bis es auch wirklich fehlerlos funktioniert, egal wie lang oder
kurz jemand drückt.
Dann schmeiß es weg und nimm die Bulletproof Methode aus dem Tutorial.
Peter
Peter hat natürlich recht. Ausserdem sollte man folgende Reihenfolge
einhalten:
#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 4000000UL
#endif
#include <util/delay.h>
#include <inttypes.h>
#include <stdint.h>
Es ist NICHT egal WO F_CPU definiert wird.
Am besten macht man das im makefile.
Hier sollte man auch noch was ändern:
> if (debounce(&PIND, PD5)) { // Falls Taster an PIN PD5 gedrueckt..> PORTB = PINB ^ ( 1 << PB0 ); }
PORTB = PORTB ^ ( 1 << PB0 ); }
Wenn man PINB liest haut man sich evtl. die Einstellung für
bereits aktivierte Pullups auf PORTB weg.
>Wenn man PINB liest haut man sich evtl. die Einstellung für>bereits aktivierte Pullups auf PORTB weg.
Kannst du das mal genauer erklären? Vielleicht mit Verweis auf eine
entsprechende Stelle im Datenblatt?
Oliver
der bisher der Meinung war, das PINB genau dafür da ist, den Portzustand
auszulesen.
> der bisher der Meinung war, das PINB genau dafür da ist, den> Portzustand auszulesen.
PINB ist dazu da, die Eingänge zu lesen. Du hast hier aber Ausgänge.
Solange du alle Leitungen von PORTB als Ausgang benutzt, müßte auch mit
PINB funktionieren. Da liest der Port dann eben seinen eignen Wert
wieder zurück. Bei Eingängen können sich die Werte in PORTB und in PINB
auch unterscheiden. Wenn PB4 z.B. als Eingang mit Pull-Up definiert ist
(PB4 in PORTB = 1) und da gerade low-Pegel anliegt, liest du von PINB4
eine 0 zurück. So wird durch deine Zeile PB4 gelöscht und der Pull-Up
ausgeschaltet. Wenn du stattdessen PORTB liest, wird wirklich nur PB0
beeinflußt.
OliverSo wrote:
> der bisher der Meinung war, das PINB genau dafür da ist, den Portzustand> auszulesen.
Genau. PINx liefert den aktuellen Zustand am Pin. Der kann aber auch von
außen beeinflusst werden. Was Du aber willst, ist, die
Port-Ausgangsstufe umschalten. Und der aktuelle Zustand der
Ausgangsstufe steht nunmal in PORTx und nicht in PINx. Wenn der Pin ein
Ausgang ist, sollte zwar normalerweise der Zustand der Ausgangsstufe
auch dem Zustand am Pin entsprechen, es sei denn, es liegt ein
Kurzschluss vor oder es hängt eine Last mit nennenswert verzögerter
Sprungantwort direkt am Pin (stark kapazitive Last). Beide Fälle sollte
man allerdings tunlichst vermeiden, so dass es bei einem als Ausgang
konfigurierten Pin i.d.R. keinen Unterschied machen sollte, ob man PORTx
oder PINx einliest. Allerdings sollte man sich das nicht angewöhnen,
denn wenn ein Pin als Eingang konfiguriert ist, dann macht es i.d.R.
schon einen Unterschied...
Merke: PINx ist dann (und nur dann) zu lesen, wenn tatsächlich der
aktuelle Zustand am Pin (der auch von außen beeinflussbar ist)
eingelesen werden soll. Ist ein Pin als Ausgang konfiguriert, macht es
i.d.R. keinen Sinn, PINx zu lesen.
Rolf Magnus wrote:
> Ich würde es gar schreiben als:>>
1
>PORTB^=(1<<PB0);
2
>
>>> der bisher der Meinung war, das PINB genau dafür da ist, den>> Portzustand auszulesen.>> PINB ist dazu da, die Eingänge zu lesen. Du hast hier aber Ausgänge.> Solange du alle Leitungen von PORTB als Ausgang benutzt, müßte auch mit> PINB funktionieren. Da liest der Port dann eben seinen eignen Wert> wieder zurück. Bei Eingängen können sich die Werte in PORTB und in PINB> auch unterscheiden.
@Orikson
Auch bei Ausgängen kann das sein, wenn am Ausgang ein Kurzschluss
vorliegt.
Über PORTx wird der Ausgang auf 1 geschaltet.
Liest man den Wert vom PORTx Register zurück erhält man auch
diese 1 wieder.
Liest man den Wert aber über das PINx Register zurück, erhält
man eine 0
Also:
Wenn der Portpin auf Ausgang geschaltet ist, kriegt man
beim Lesen von
PORTx den Wert den man zuletzt geschrieben hat
PINx den Wert den der Ausgangspin tatsächlich hat.
Und das auch nur mit einer kleinen Verzögerung
nach dem Setzten des Pins durch Schreiben auf das
PORTx Register.
Das gilt aber nur, wenn der Pin auf Ausgang geschaltet ist!
Mein Frage bezog sich eigentlich nur auf den Satz:
>Wenn man PINB liest haut man sich evtl. die Einstellung für>bereits aktivierte Pullups auf PORTB weg.
Das ist trotzdem Quark. PINx kann man lesen, so oft man will, an den
Pullups ändert sich dabei gar nichts.
Das in der Zeile
1
PORTB=PINB^(1<<PB0);
PORTB gelesen werden sollte, ist natürlich richtig, das hatte ich dabei
aber völlig übersehen.
Oliver
> Das ist trotzdem Quark. PINx kann man lesen, so oft man will, an den> Pullups ändert sich dabei gar nichts.
Durch das Lesen selbst nicht, aber durch das Schreiben des dort
gelesenen Werts nach PORTB.