Hallo zusammen!
Ich bin noch sehr jung und habe erst vor kurzem mit dem microcontroller
programieren angefangen.
Ich benutze die Programiersprache c.
Wenn man einen Taster drücke soll eine LED leuchten und wenn man ihn
ein zweites mal drückt soll sie wieder ausgehen.
Ich bedanke mich im Voraus !
Die Aufgabenstellung, so einfach sie auch klingt, ist erstaunlicherweise
gar nicht so einfach zu lösen.
D.h. Prinzipiell ist es leicht zu lösen, aber der Realität geschuldete
Nebenbedingungen machen es schwierig.
UM festzustellen, ob eine Taste (einmalig) gedrückt wurde, genügt es,
die entsprechende Schaltflanke zu detektieren. Dies macht man, in dem
man einen vorher-nachher Vergleich durchführt. D.h. eine Taste wurde
niedergedrückt, wenn sie vorher nicht gedrückt war, jetzt aber schon
1
Taste_Vorher = Tastenzustaqnd jetzt;
2
3
while( 1 )
4
{
5
Taste_Jetzt = Tastenzustand jetzt;
6
7
if( Taste_Jetzt != Taste_Vorher )
8
{
9
// die Taste wurde verändert. Aber: wurde sie gedrückt
10
// oder wurde sie losgelassen?
11
12
if( Taste_Jetzt == gedrückt )
13
mach deine Aktion
14
15
Taste_Vorher = Taste_Jetzt;
16
17
// <********
18
19
}
20
}
Soweit das Prinzip. Die Realität macht einem da jetzt allerdings einen
Strich durch die Rechnung, in dem Tasten als mechanisches Bauteil
prellen. Und an diesem Punkt kann die ganze Geschichte dann aufwändig
werden.
Entprellung
Man kann sich bei seinen ersten Versuchen mit Delays über die Runden
retten um die Prellzeit an der markierten Stelle 'auszusitzen', aber auf
Dauer führt kein Weg an einer ordentlichen Entprellung vorbei.
Wenn das dein erstes Zusammentraffen mit LED und Tasten ist, dann
verändere deine Aufgabenstellung. Diese Aufgabe ist für dich dann
momentan noch zu schwer.
hallo !
danke für die schnellen antworten
ich habe vorgesten mit dem programieren eines uc's angefangen
und kenn mich kaum aus
ich hab mir bei conrad ein starterpacket gekauft... die Taster auf der
platiene sind schon entprellt
gestern hab ich es schon zusammengebracht eine taste einzulesen.
wenn man die taste drück leuchtet eine LED, wenn man sie wieder loslässt
geht sie wieder aus.
Was ich damit sagen will.
ich bin einfach noch sehr schlecht im programmieren und kapier fast
nichts
Karl Heinz Buchegger schrieb:> // die Taste wurde verändert. Aber: wurde sie gedrückt
Richtig, der fehlte noch
if(taste!=gedrueckt&&gedrueckt) PORTB^=2;
egbert schrieb:> Hä? Sind wir hier bei www.hausaufgabenhilfe.de?
Ich finde solche Kommentare doof. Und ich finde, dass auch die
Unerfahrensten Fragen stellen dürfen sollten, ohne komische Kommentare
als Antwort zu erhalten. Sorry, fürs Offtopic!
LG, Timo
Daniel Lauß schrieb:> gestern hab ich es schon zusammengebracht eine taste einzulesen.> wenn man die taste drück leuchtet eine LED, wenn man sie wieder loslässt> geht sie wieder aus.
Das bedeutet, dass du verstanden hast, wie die Ein- und Ausgänge
konfiguriert und geschaltet werden?
Dann poste am besten mal deinen Code. Dann kann man damit
weiterarbeiten. Du solltest eventuell auch mal einen Blick ins
AVR-GCC-Tutorial werfen. Das hat mir sehr oft geholfen.
Daniel schrieb:> if (PINB&(1<<PB0))
Dort testest du ja, ob der Taster gedrückt ist. Wenn das so ist, wird
die LED eingeschaltet, anderenfalls ausgeschaltet.
Du möchtest aber nicht, dass sie wieder ausgeschaltet wird. Was musst du
an deinem Programm ändern, damit die LED eingeschaltet bleibt?
Jap. Jetzt wird die LED eingeschaltet und bleibt so lange eingeschaltet,
bis du den Controller resettest.
Jetzt soll die LED ausgeschaltet werden, wenn der Taster gedrückt wird.
Wie würdest du das machen?
Ich hab mich ein wenig vertan, weil du den Taster anders angeschlossen
hast, als ich das für gewöhnlich tue.
Silvan König schrieb:> Dort testest du ja, ob der Taster gedrückt ist. Wenn das so ist, wird> die LED eingeschaltet, anderenfalls ausgeschaltet.
Meine Aussage zu deinem ursprünglichen Code muss ich wie folgt
korrigieren:
Dort testest du ja, ob der Taster nicht gedrückt ist. Wenn das so ist,
wird die LEDausgeschaltet, anderenfalls eingeschaltet.
Silvan König schrieb:> if (PINB&(1<<PB0)) //wenn Taster nicht gedrückt
Du musst die Bedingung "PINB&(1<<PB0)" invertieren. Dann wird "wahr" zu
"falsch" und umgekehrt. Das funktioniert mit dem Ausrufezeichen:
> Du möchtest aber nicht, dass sie wieder ausgeschaltet wird. Was musst du> an deinem Programm ändern, damit die LED eingeschaltet bleibt?
Ohne Entprellung wird es nicht funktionieren.
> könnte das funktionieren ???
Nein, weil die Entprellung fehlt.
Das machte in meinem Programm das _delay_ms(10)
while(1)
{
if (!(PINB&(PB0)))
{
PORTC=PORTC |~(1<<PC0);
}
if(PINB&(1<<PB0))
{
PORTC=0x00;
}
}
}
müsste eigendlilch funktionieren oder ... wo hast du in deinem programm
den delay genau hingesetzt???
Daniel schrieb:> while(1)> {>> if (!(PINB&(PB0)))> {> PORTC=PORTC |~(1<<PC0);> }>> if(PINB&(1<<PB0))> {> PORTC=0x00;> }>>> }> }> müsste eigendlilch funktionieren oder ... wo hast du in deinem programm> den delay genau hingesetzt???
Allenfalls "oder".
Du versuchst hier irgendwelche Sachen, ohne zu wissen, was das überhaupt
soll. Das Prinzip einer Tastenauswertung ist, daß man den vorherigen
Zustand der Taste berücksichtigt. Denn der Controller fegt mit
unvorstellbarer Geschwindigkeit durch die while-Schleife und stellt
fest, daß ein Port einen bestimmten Pegel hat. Daß da ein Taster dran
ist, interessiert ihn nicht. Der weiss gar nicht, was das ist.
Wird der Taster gedrückt, stellt er ungefähr 587000 mal fest, daß der
Pegel 0 ist. Oder noch öfter. Bis der Taster wieder losgelassen wird.
In dieser Zeit soll aber nicht 587000 mal etwas gemacht werden, sondern
nur einmal. Ein einziges Mal. Deswegen muss sich das Programm den
Zustand vor und nach der Betätigung des Tasters merken. Also "Nicht
gedrückt". Meinetwegen auch "pressed". Jetzt also "Not pressed". Damit
der Compiler das auch versteht: !pressed. Und entsprechend "gedrückt".
Also brauchst du eine Varable, die sich das merkt.
Wird der Taster gedrückt und das Programm stellt das fest, macht es was.
Nämlich die LED umschalten. Beim nächsten Durchlauf der while-Scheife
tut es das wieder, also 587000 mal. Wenn du loslässt ist die Led aus.
Wie vorher auch. Du musst es also hinkriegen, daß die Scheife nicht
587000 mal sondern 587001 mal durchlaufen wird, dann ist die Led an und
beim nächsten Drücken schaltest du sie so wieder aus.
Du kannst dir natürlich auch merken, daß die Schleife mit betätigtem
Taster einmal durchlaufen wurde. Und wenn sie schon durchlaufen wurde,
machst du gar nichts. Dann ist es egal, wie lange der Taster gedrückt
bleibt und die Schleife durchlaufen wird.
Wird der Taster losgelassen, setzt du die "gedrückt-Variable" wieder
zurück. Fürs nächste Mal. Sonst würde es ja nur einmal funktionieren.
Wenn das Ein- Ausschalten zu langweilig wird, zählst bei jedem Drücken
eine Variable um 1 hoch. Damit kannst du dann mit ein bisschen
Auswertemimik beim 1. Tastendruck Led1, beim 2. Led2, beim 3. ...
Läuft alles nach dem selben Prinzip. Was ist jetzt und was war vorher?
War es vorher anders, mach ich was, war vorher das selbe, tu ich nichts.
Denn das kommt als nächstes. Und dann wird dir das Drücken zu blöd und
das Lauflicht soll von selbst laufen. Und mit Tastendruck wird die
Laufrichtung umgeschaltet.
Aber mach erstmal das An/Aus.
mfg.
bin auch ein Anfänger - hab die zum Leuchten gebracht - aaber nicht zum
Blinken(
Beitrag "LED Blinker mit Taster ansteuern."
also wenn einer helfen kann bin ich sehr dankbar
}
}
ich versteh nicht ganz warum es noch immer nicht funktioniert abgesehen
davon das die taster nicht entprellt sind.
if (!taste_nicht_gedrueckt && tastenzustand==taste_auf)
egal ob ich das Rufzeichen hier weg nehme oder dazu gebe oder den
tastenzustand ändere ... die LED bleibt immer eingeschaltet .... was
mache ich falsch???
Ich bedanke mich im Voraus!
MFG
Daniel Lauß schrieb:> ich versteh nicht ganz warum es noch immer nicht funktioniert abgesehen> davon das die taster nicht entprellt sind.
Wenn die Taster nicht entprellt sind, kann das nicht funktionieren!
_delay_ms(30); Wo ist eigentlich egal. Praktischerweise am Ende der
Schleife.
>if (!taste_nicht_gedrueckt && tastenzustand==taste_auf)
Setz mal Klammern, damit zusammenkommt, was zusammen gehört.
if (!taste_nicht_gedrueckt && (tastenzustand==taste_auf))
mfg.
ich habe die paar sachen mal geänder, aber jetzt tut sich leider gar
nichts mehr ... ich bitte um Hilfe.
Was mache ich nur falsch???
ich bedanke mich im Voraus!
MFG
Daniel Lauß schrieb:> if (LED_on)>> LED_off;> }>> if (LED_off)> {> LED_on;> }
Diese Abfragen funktionieren nicht.
LED_on / LED_off werden ersetzt durch das, was du definiert hast.
Also steht da:
if(PORTC |= 0xff)
bzw.
if(PORTC &= 0x00)
Das erste ist true, das zweite false. Vergiss das ganz schnell. Das
willst du gar nicht wissen.
In diesem Fall, wo es um den ganzen Port geht, was natürlich auch Unsinn
ist, aber lassen wir das mal beiseite, fragst du einfach das
Portregister ab.
if(PORTC == 0xFF)
{
LED_on;
}
und dann!!!!!
else
{
LED_off;
}
Wenn du stattdessen mit if(!PORTC) oder if(PORTC == 0) abfragst ist das
wieder true, denn den Port hast du ja gerade eingeschaltet und dann
schaltest du ihn wieder ab.
mfg.
Danke für die Antwort Herr Eckmann.
Leider funktioniert es noch immer nicht.
Schon langsam verzweifle ich mit diesem Programm.
Ein komischer Fehler ist mir auf gefallen wen ich hier:
1
if(PINC&(1<<PB0))
2
{//diese klammer nicht entferne kommt der Fehler: "expected declaration or statement at end of input"
3
4
5
6
LED_off;
7
}
Wenn ich sie entferne kommt der fehler nicht mehr.
Daniel Lauß schrieb:> Ein komischer Fehler ist mir auf gefallen wen ich hier:if (PINC> &(1<<PB0))> {//diese klammer nicht entferne kommt der Fehler: "expected> declaration or statement at end of input">>>> LED_off;> }> Wenn ich sie entferne kommt der fehler nicht mehr.
Kontrolliere mal die Klammer-Paare.
Und die jeweils zusammengehörenden schön einrücken.
Daniel Lauß schrieb:> #define LED_on PINC | (1<<PB0)
mit diesem Makro kannst du die LED nicht einschalten,
noch Mal:
welches C-Buch oder Tutorial hast du schon durchgearbeitet?
nur mal so schrieb:> Du solltest unbedingt Kommentare in den Quelltext einfügen.
Volle Zustimmung!
Und auch das unnötige Leerzeilen schinden unterlassen. Das behindert
sehr den Lesefluß.
Vermutlich weißt Du selber nicht mehr, was Du viele Leerzeilen weiter
oben mal gemacht hast. Es ist bereits aus dem Blickfeld und der Kontext
geht Dir verloren.
Maximal eine Leerzeile nur an besonderen Stellen.
Daniel Lauß schrieb:> }> }
2 Klammern auf der gleichen Einrückung ist das absolute No-Go!
nur mal so schrieb:> Du solltest unbedingt Kommentare in den Quelltext einfügen. Durch das> viele hin und her hast bereits die Übersicht verloren.
Erstens das.
Dann: Zieh den Code nicht so in die Länge, indem du haufenweise
Leerzeilen einfügst. Das bringt keine Übersicht. Das verstreut nur die
Dinge in der Anzeige.
Weiters: Einrückungen!
Gerade für Anfänger ist es wichtig, den Code korrekt einzurücken, weil
die Einrückung die logische Struktur des Codes zeigt.
Ich bin zwar eigentlich ein Freund davon, sich mittels Funktionen oder
Makros den Code leichter verständlich zu machen. Allerdings birgt das
auch eine Falle. Makros sind reine Textersetzungen. Und um zu wissen,
was da passiert, muss man im Kopf die Makro Ersetzung machen um dann zu
sehen, was beim Makro nicht passt.
In Deinem Fall bedeutet das zb, das das hier
1
if(!taste_nicht_gedrueckt
eben NICHT das macht, was dort steht, bzw. was du erwartest.
Solange du noch am Anfang deiner C-Karriere stehst, solltest du da
vorsichtig sein. Insbesondere sollst du hier bei Makros
1
#define taste_nicht_gedrueckt PINB &(1<<PB0)
Klammern rund um die Ersetzung machen!
Denn bei dir lautet die Ersetzung von
1
if(!taste_nicht_gedrueckt
dann eben
1
if(!PINB&(1<<PB0)...
und das ist ganz etwas anderes als beabsichtigt. Denn das ! bindet
stärker als das &. D.h. da entsteht das hier
1
if((!PINB)&(1<<PB0)...
und das ist genau NICHT das, was du eigentlich wolltest.
Du wolltest
1
if(!(PINB&(1<<PB0))...
d.h dein Makro sollte dafür so aussehen
1
#define taste_nicht_gedrueckt ( PINB &(1<<PB0) )
damit dann bei der Testersetzung auch das richtige entsteht. Das alles
sind Kleinigkeiten in der C-Programmierung, die dir extrem das Leben
schwer machen können. Gerade als Anfänger ist es nicht so leicht, das
alles zu überblicken und ins Kalkül zu ziehen. Daher würde ich dafür
plädieren, dass du dir erst mal KEINE derartigen Funktions-Makros
machst, solange du noch nicht abschätzen kannst, was du dir damit
einhandelst. Benutze Makros ausschliesslich dafür, dass du 'magischen
Konstanten' einen Namen gibst. Mehr aber auch nicht.
Im übrigen haben sowohl MaWin als auch ich schon weiter oben vernünftige
Lösungen gepostet. Ich hab dir sogar die zugrundeliegende Idee dahinter
detailliert aufgeschlüsselt. Warum orientierst du dich nicht daran?
(Ich schreib das jetzt absichtlich etwas ausführlicher. Mit etwas mehr
C-Erfahrung schreibt man das dann etwas kompakter.
1
#include<avr/io.h>
2
#include<util/delay.h>
3
4
#define TASTE_GEDRUECKT 0
5
#define TASTE_NICHT_GEDRUECKT 1
6
7
intmain(void)
8
{
9
uint8_ttasteVorher;
10
uint8_ttasteJetzt;
11
12
DDRB=0x00;
13
PORTB=0xff;
14
DDRC=0xff;
15
16
// aktuell vorliegenden Tastenzustand ermitteln
17
if(PINB&(1<<PB0))
18
tasteVorher=TASTE_GEDRUECKT;
19
else
20
tasteVorher=TASTE_NICHT_GEDRUECKT;
21
22
23
while(1)
24
{
25
// aktuell vorliegenden Tastenzustand ermitteln
26
if(PINB&(1<<PB0))
27
tasteJetzt=TASTE_GEDRUECKT;
28
else
29
tasteJetzt=TASTE_NICHT_GEDRUECKT;
30
31
32
// hat sich an der Taste etwas verändert ?
33
if(tasteVorher!=tasteJetzt)
34
{
35
// Ja, hat es. Was ist passiert? Ist die Taste jetzt gedrückt?
36
// wenn ja, dann war die Veränderung das Niederdrücken der Taste
37
if(tasteJetzt==TASTE_GEDRUECKT)
38
{
39
// Benutzer hat gerade niedergedrückt. LED umschalten
gut, du denkst mit,
dann vertausch einfach TASTE_NICHT_GEDRUECKT und TASTE_GEDRUECKT
ein kleiner Schönheitsfehler im Text von Karlheinz:
die Variablen sollten initialisiert werden
jaa ich hab das dan auch gleich gemacht funktioniert wunderbar.
Danke an alle die mir geholfen haben bzw es versucht haben.
Ich hoffe wenn ich wieder mal eine frage habe dass mir wieder geholfen
wird :)
MFG