PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Simple Tasterabfrage funktioniert nicht (PullUp-Widerstand)



JellbieO
15.11.2008, 11:21
Hey Leute!
Wünsch euch erstmal `n schönes Wochenende an dieser Stelle.

Das doofe ist nur bei mir fiel es bisher noch nciht wirklich gut aus :(
Ich habe bis heute Nacht um 02:00Uhr daran gesessen und bekomme es einfach nicht zum laufen.

Warscheinlich wird es irgendwo nur ein denkfehler sein aber ich komm einfach nicht drauf.

Wir, also unsere Gruppe, haben an einem (selbstgebauten) ControllerBoard folgende Taster:

-> PC 4 bis PC 7

Diese haben wir mit Masse angeschlossen, bedeutet wenn man einen Taster drückt, kommt Masse an dem einzelnen PIN an.

Für eine simple Tasterabfrage muss man ja nun also die PULL-UP Widerstände einschalten und natürlich auf EINGANG schalten.

Vielleicht ist es relevant, vielleicht nicht ich weiß es nicht
Wir nutzen den ATMega644P und betreiben das ganze mit einem 16Mhz Quarz.







#include <avr/io.h>
#include <inttypes.h>
#define F_CPU = 16000000UL
#include <util/delay.h> // Benutzen eine aktuelle AVR-LIB

/* Einfache Funktion zum Entprellen eines Tasters */
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
{
if ( ! (*port & (1 << pin)) )
{
/* Pin wurde auf Masse gezogen, 100ms warten */
_delay_ms(50); // max. 262.1 ms / F_CPU in MHz
_delay_ms(50);
if ( *port & (1 << pin) )
{
/* Anwender Zeit zum Loslassen des Tasters geben */
_delay_ms(50);
_delay_ms(50);
return 1;
}
}
return 0;
}



int main(void)
{
DDRB = (1 << DDB0); // Für die LED's die beim drücken eigentlich angehen sollten
DDRC &= ~( 1 << PC4 ); /* PIN PB0 auf Eingang (Taster) */
PORTC |= ( 1 << PC4 ); /* Pullup-Widerstand aktivieren */

if (debounce(&PINC, PC4))fe
{

PORTB |= (1 << 0); // Schaltet 2 LED's ein...
}
}


Wir hatten eigentlich vor das ganze per Interrupt zu machen.
Wenn also der Taster gedrückt wurde soll im Hauptprogramm eigentlich nur noch geprüft werden...
if(taster==1){...}else if{...}
Das Hauptprogramm soll ja zügig weiterlaufen...

aber wenn wir daran schon scheitern? :(

Vielleicht hat ja wer ein Beispiel parat, bin für jede Hilfe dankbar!

Grüße aus Bookholzberg

BurningWave
15.11.2008, 12:05
Wenn ich einen Taster abfragen will, mache ich es so:


void main()
{
DDRX |= (1 << PXx); //internen PullUp aktivieren
while(1)
{
if(!(PINX & (1 << PXx))) //abfragen
{ //wenn gedrückt
...
_delay_ms(200); //entprellen
}
}
}


Das funktioniert ohne Probleme.

mfg

McJenso
15.11.2008, 12:12
Hallo,

auf den ersten Blick ist offensichtlich, dass keine Schleife in der main() vorhanden ist. Das Programm wird einmal durchlaufen und dann? Dann passiert nix mehr.

Dann bitte original Code per copy und past einfügen. Es ist ärgerlich, wenn einfache Schreibfehler vom eigentlichen Problem ablenken.

Gruß

Jens

radbruch
15.11.2008, 12:13
Hallo

Ich bin auch noch Tastenneuling, mein erster Versuch sieht so aus:

uint8_t lcd_getkeys(void)
{
uint8_t keys=0;
el; // Auf keinen Fall Daten zum Display schicken
DDRC &= ~SL1; // D4-D7 und RS auf Eingang mit PullUp schalten
PORTC|=SL1;
DDRC &= ~SL2;
PORTC|=SL3;
DDRC &= ~SL3;
PORTC|=SL2;
DDRB &= ~SL4;
PORTB|=SL4;
DDRB &= ~SL5;
PORTB|=SL5;

if(PINC & SL1) keys |= 8; // einzelne Taster einlesen
if(PINC & SL2) keys |= 4;
if(PINC & SL3) keys |= 16;
if(PINB & SL4) keys |= 2;
if(PINB & SL5) keys |= 1;

DDRC |= 0x70; // LED1-3 wieder auf Ausgang und low
PORTC &= ~0x70;
DDRB |= 0x83; // LED4-6 wieder auf Ausgang und low
PORTB &= ~0x83;
rsh; // RS wieder auf Daten schreiben setzen
return(~keys & 0b11111); // Bit gesetzt= Taster gedrückt (bit0-4)
}

Die 5 Taster werden als Bit0 bis Bit4 im Rückgabewert zurückgegeben.

Der Test auf eine gedrückte Taste:
if(lcd_getkeys()) ...

Entprellen:
taste=lcd_getkeys();
if(taste && (taste == lcd_getkeys()))...

Vielleicht hilft dir das weiter.

Gruß

mic

JellbieO
15.11.2008, 12:14
mhmmm hab folgendes nun mal ausprobiert...


#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#define F_CPU = 16000000UL


int main()
{
DDRC |= (1 << PC4); //internen PullUp aktivieren
while(1)
{
if(!(PINC & (1 << PC4))) //abfragen
{ //wenn gedrückt
DDRB = (1 << DDB0);
PORTB |= (1 << 0); // Schaltet 2 LED's ein...
_delay_ms(200); //entprellen
}
}
return 0;
}

funktioniert aber immernoch net... werde mal gleich andere Kabel anlöten und schaun was passiert wenn ich andere Ports wähle...

BurningWave
15.11.2008, 12:20
DDRB = (1 << DDB0);
PORTB |= (1 << 0); // Schaltet 2 LED's ein...


Ich glaube der Fehler liegt in diesen 2 Zeilen. Sie müssten so lauten:


DDRB |= (1 << PB0);
PORTB |= (1 << PB0);

JellbieO
15.11.2008, 12:24
DDRB = (1 << DDB0);
PORTB |= (1 << 0); // Schaltet 2 LED's ein...


Ich glaube der Fehler liegt in diesen 2 Zeilen. Sie müssten so lauten:


DDRB |= (1 << PB0);
PORTB |= (1 << PB0);
daran hat es leider nicht gelegen... hatte das auch einmal nur so in der Main stehen und die LED's leuchteten...

radbruch
15.11.2008, 12:26
Die defines aus iomxx4.h:

#define DDRB _SFR_IO8(0x04)
#define DDB7 7
#define DDB6 6
#define DDB5 5
#define DDB4 4
#define DDB3 3
#define DDB2 2
#define DDB1 1
#define DDB0 0

#define PORTB _SFR_IO8(0x05)
#define PB7 7
#define PB6 6
#define PB5 5
#define PB4 4
#define PB3 3
#define PB2 2
#define PB1 1
#define PB0 0

Sowohl DDB0 als auch PB0 werden durch 0 ersetzt, beides bedeutet dann:

DDRB = (1<<0);
PORTB |= (1<<0);

oder kurz

DDRB = 1;
PORTB |= 1;

Ähm, btw:

DDRC |= (1 << PC4); //internen PullUp aktivieren

Hier wird nicht der PullUp aktiviert sondern auf Ausgang geschaltet!

BurningWave
15.11.2008, 12:31
Hast du auch alles richtig angeschlossen? Funktioniert der µC, die LEDs, die Taste?

JellbieO
15.11.2008, 12:35
so....


#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#define F_CPU = 16000000UL


int main()
{
DDRC |= (1 << PC4); //internen PullUp aktivieren
while(1)
{
if(!(PINC & (1 << PC4))) //abfragen
{ //wenn gedrückt
DDRB = (1 << DDB0);
PORTB |= (1 << 0); // Schaltet 2 LED's ein...
_delay_ms(200); //entprellen
}
}
return 0;
}


bewirkt gerade bei mir das meine LED leuchtet ABER ohne eine Taste zu drücken... müsste doch heißen das ich bereits Masse auf dem Pin habe versteh das ich richtig? PULL-UP Widerstand ist ja an

radbruch
15.11.2008, 12:39
DDRC |= (1 << PC4); //internen PullUp aktivieren

Da muss doch PORTC stehen, oder?

BurningWave
15.11.2008, 12:39
Lass das Programm nach der Tastenabfrage ca. 1 Sekunde warten und schalte dann nach der Abfrage die LEDs wieder aus. Schau mal ob sie dauerhaft leuchten.

JellbieO
15.11.2008, 12:51
#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#define F_CPU = 16000000UL


int main()
{
while(1)
{
DDRB = (1 << DDB0);
if(!(PINC & (1 << PC5))) //abfragen
{ //wenn gedrückt

PORTB |= (1 << PB0); // Schaltet 2 LED's EIN
_delay_ms(200); //entprellen
}
else
{
PORTB &= ~(1 << PB0); // Schaltet 2 LED's AUS.
}
}
return 0;
}


Mit dem Beispiel gehts... jetzt reagiert er bloß auf zwei Taster statt auf einem...

Mal sehen ob`s vll am Kabelgewusel liegt ;)

radbruch
15.11.2008, 12:54
Prima, wo ist denn nun der PullUp abgeblieben?

DDRC &= ~((1<<PC7) | (1<<PC6) | (1<<PC5) | (1<<PC4) ); // Pins auf Eingang
PORTC |= (1<<PC7) | (1<<PC6) | (1<<PC5) | (1<<PC4) ; // PullUps einschalten

JellbieO
15.11.2008, 13:33
Es läuft nun!! THX @ All!

Irgendwie schon komisch weil ich mir sicher bin ich das ich dié PULL-UPs vorhin hab eingeschaltet... nur halt exkat anders herum

PORTC |= (1<<PC4) | (1<<PC5) | ... aber das ist doch völlig irrelevant oder etwa nicht??

BurningWave
15.11.2008, 13:54
Irgendwie schon komisch weil ich mir sicher bin ich das ich dié PULL-UPs vorhin hab eingeschaltet... nur halt exkat anders herum

PORTC |= (1<<PC4) | (1<<PC5) | ... aber das ist doch völlig irrelevant oder etwa nicht??


Eigentlich schon.

radbruch
15.11.2008, 15:12
PORTC |= (1<<PC4) | (1<<PC5) | ... aber das ist doch völlig irrelevant oder etwa nicht??
Das ist egal in welcher Reihenfolge es angegeben wird, der Kompiler ersetzt es sowieso durch 0b11110000 oder einfach 240.

Übrigens würde ich zwischen Taster und GND noch einen Widerstand schalten um zu verhindern dass bei falscher Ansteuerung des Pins derselbige abraucht wenn eine Taste gedrückt wird! Er sollte mindestens so groß sein das maximal ca. 20mA fließen (also etwa >220) und gleichzeitig aber so klein das die Spannung am Spannungsteiler zwischen PullUp (>10k) und Schutzwiderstand am Pin noch sicher als Low erkannt wird. Bei meiner Anwendung oben verwende ich 820 Ohm.

Wie sieht denn nun die funktionierende Version des Programms aus?