Hay habe mal vor einiger Zeit mich heir erkundigt wegen einem 4*4 keypad
und dessen abfrage, dieses keypad hat 16 tasten 4 eingänge und 4
ausgänge.
Habe hier mal ein Beispiel mit 2*2 Tasten gemacht wobei die PORT und PIN
belegung hier irelevant sind.
also:
x1-|----|-
x2-|----|-
y1 y2
so habe ich jetzt 4 schalter, habe versucht x1 und 2 also PORTC 0x01 &
0x02
über eine while schleife immer abwechselnd auf HIGH zu setzen.
Sobald y1 oder 2 ein signal bekommt soll die schleife stoppen und einen
Wert auf den integer Ergebnis addieren.
hier ist mal der code :)
hoffe er klappt so wie ich es mir vorgestellt habe.
MFG und besten Dank für jeden Ratschlag :)
int main()
{
int ergebnis;
while((PINB == 0x01) || (PINB == 0x02))
{
PORTc = 0x01;
_delay_ms(2);
PORTC = 0x02;
_delay_ms(2);
}
if ((PINB == 0x01) && (PORTC == 0x01))
{
ergebnis+= 1;
main();
}
if ((PINB == 0x01) && (PORTC == 0x02))
{
ergebnis+= 10;
main();
}
if ((PINB == 0x02) && (PORTC == 0x01))
{
ergebnis+= 100;
mein();
}
if ((PINB == 0x02) && (PORTC == 0x02))
{
ergebnis+= 1000;
main();
}
return 0;
Dabei schmiert dir erst mal glatt dein Controller ab, da du rekursiv
deine main(); aufrufst, du musst dein programm komplett
umstrukturieiren, so macht as nicht so viel sinn.
Du musst immer abwechseln deine Spalten addressieren und die
entsprechenden Zeilen dazu lesen. Sowas in der art hast du denke ich
versucht, aber so funktioniert das nicht.
naja das mit dem main(); kann man weglassen, war ein denkfehler.
kann man das dann so machen?
Ich meine ist die schreibweise richtig?
zuerst wird ja eine while schleife ausgeführt bis ein Pin ein Signal
empfängt.
dann prüft der in welcher komination der Pin ein signal empfängt hierbei
wußte ich nicht wie ich es richtig schreibe.
also:
if ((PINB == 0x01) && (PORTC == 0x01))
oder
if ((PINB = 0x01) && (PORTC = 0x01))
oder
if ((PINB & 0x01) && (PORTC & 0x01))
und dann addiert er dementsprechen einen Wert auf den integer ergebnis
jan schrieb:> PORTc = 0x01;> _delay_ms(2);> PORTC = 0x02;> _delay_ms(2);
Das ist der falsche Ansatz. Du toggelst zwar abwechselnd Pin0 und Pin1,
aber die Schleifenbedingung wird nur einmal geprüft, nämlich wenn Pin1
auf high ist.
Deshalb:
while(1)
{
PORTC = 0x01;
If(PINB & (1 << 0) ...
If(PINB & ( 1<< 1) ...
PORTC = 0x02;
If(PINB & (1 << 0) ...
If(PINB & ( 1<< 1) ...
}
Warum so
>>If(PINB & (1 << 0) ...
und nicht so
>>if (PINB == 0x01) ?
Bei der zweiten Abfrage passiert nichts, wenn beide Tasten gedrückt
sind.
mfg.
ah okay danke :)
so nun stell dir bitte vor das ich 3 schleifen brauche:)
einmal für die 100er stelle die 2. für 10er und 3. für die einser
stelle.
da ich gerne Zahlen bis 255 eingeben würde.
wie muss ich die while schleife deklarieren das ich nach der ersten
eingabe zur nächsten while schleife wander.
würde es so gehen
while((eingabe >= 1) || (x >= 1))
wobei wenn ich 0 eingebe der intenger x um 1 addiert wird, und dieser
für die eigentlihe Rechnung uninteressant ist.
:)
Schonmal besten dank du hast mir sehr geholfen :)
jan schrieb:> ah okay danke :)> so nun stell dir bitte vor das ich 3 schleifen brauche:)> einmal für die 100er stelle die 2. für 10er und 3. für die einser> stelle.> da ich gerne Zahlen bis 255 eingeben würde.
Der ganze Ansatz ist nicht sehr geeignet.
In einem vernünftigen Ansatz brauchst du gar keine Schleife zur
Tastenerkennung.
Was du haben willst, ist eine Funktion, die du aufrufst und die dir
mitteilt, ob jetzt gerade eine Taste gedrückt ist und wenn ja, welche.
Der ganze Ansatz mit Schleifen zur Tastenerkennung ist nicht tragfähig.
Und verwenden willst du das zb so
1
intmain()
2
{
3
....
4
5
while(1){
6
7
do{
8
taste=get_keyboard();
9
}while(taste==-1)// -1 ist der Code, den get_keyboard liefert
10
// wenn keine Taste gedrückt ist
11
12
// taste enthält jetzt den Code für den ersten Tastendruck
13
// warte darauf, dass die Taste losgelassen wird
14
15
while(get_keyboard()!=-1)
16
;
17
}
18
}
wie muss jetzt die FUnktion get_keyboard aussehen, so dass sie -1
liefert, wenn keine Taste gedrückt ist und ansonsten einen bestimmten
Code für jede der vorhandenen Tasten?
Du musst die Erkennung der Tastendrücke und die Zuordnung zu den
einzelnen Tasten von der Verwendung der Tastendrücke trennen. Alles
andere führt ins Prorammchaos und zu Spaghetticode.
Karl heinz
danke, ich weiß das du ne menge Ahnung hast aber das ist einfach noch
eine Nr zu groß für mich ich weiß wie ich vorgehen muss aber d fehlt mir
einfach die Erfahrung in der Anwendung.
Ich weiß das ich eine schleife aufbauen muss die PORTB 0-3 abwechselnd
auf HIGH setzen muss und durch den tastendruck dann erkennen muss
welcher Port garde auf HIGH gesetzt wurde, dies im zusammenhang mit den
PINS 0-3.
Dies versuche ich garde natürlich so gut wie möglich zu lösen.
Und den Ansatz von Thomas kann ich sehr gut nachvollziehen.
Diesen würde ich auch bei deiner lösung einbeziehen
heißt:
void get_keyboard()
{while(1)
{
PORTC = 0x01;
If(PINB & (1 << 0)
{
taste = 1;
}
If(PINB & ( 1<< 1)
{
taste = 2;
}
PORTC = 0x02;
If(PINB & (1 << 0)
{
taste = 3;
}
If(PINB & ( 1<< 1)
{
taste = 4;
}
else
{
taste = -1;
}
}
ist das so halbwegs richtig?
jan schrieb:> Karl heinz> danke, ich weiß das du ne menge Ahnung hast aber das ist einfach noch> eine Nr zu groß für mich
Nicht böse sein:
Aber dann frage ich mich, warum du dich an solchen Dingen versuchst,
anstatt erst mal die Grundlagen durchzugehen und zu üben, wie man
Tastenabfragen macht und wie man einen µC programmiert.
> Ich weiß das ich eine schleife aufbauen muss
Musst du eben nicht.
Du Funktion hat NICHT die Aufgabe auf einen Tastendruck zu warten! Sie
soll nur feststellen OB eine Taste gedrückt ist und wenn ja WELCHE.
Mehr soll sie nicht tun. Auf einen Tastendruck zu warten, das macht der
Aufrufer der Funktion. Er macht dies deshalb, weil der aufrufende COde
weiß, ob es ok ist zu warten oder nicht. Aber das ist etwas was diese
Funktion nicht entscheiden kann und auch nicht entscheiden soll.
Die Funktion schaltet nur die entsprechenden PORT Bits durch, sieht sich
an, was an den PIN Bits passiert und entscheidet auf Grund dessen, was
sie da sieht, OB eine Taste gedrückt ist (Aussage 1) und wenn ja welche
(Aussage 2).
Und diese Erkentnis meldet sie mit ihrem Rückgabecode an den AUfrufer
zurück, der dann damit weiterarbeitet.
Und die erste Frage, die man sich stellen muss, lautet:
Wie meldet die Funktion was?
Eng damit zusammen hängt die Fragestellung: Wie ist das, wenn mehr als 1
Taste auf einmal gedrückt wurde? Ist das ein Fehler, sollen die
Tastendrücke auseinander gehalten werden können, darf der Benutzer das
ganz einfach nicht tun oder wie soll sowas gehandhabt werden?
Die einfachste Antwort darauf lautet: Es ist nicht definiert was dann
passieren soll. Was immer aus der Logik herauskommt ist richtig und der
Benutzer darf das ganz einfach nicht machen.
Abhängig davon überlegt man sich, wie der Returncode der Funktion
aussehen soll und dann arbeitet man die Funktion aus, so dass sie desen
Code auch erzeugt.
Quatsch ich bin nicht böse :)
Ich bin dir dankbar für jeden Tipp,
Also nun um es zu evrstehen soll ich etws in der form machen:
Alle PORTS auf HIGH wenn eine Taste gedrückt wird,
sollen alles PORTS duchgehend auf low gesetzt werden und wenn und durch
den der auch auf low geht weiß der mikrocontroler dann auch welchen
Schalter ich gedrückt habe.
Dann soll er mir einen wert ausgeben.
habe ich das richtig verstanden?
jan schrieb:> Alle PORTS auf HIGH wenn eine Taste gedrückt wird,
Nein.
Du weißt nicht, ob überhaupt eine Taste gedrückt ist oder nicht.
Genau das willst du doch rausfinden!
x1 auf Ausgang und auf High
ist y1 auf High?
Ja: Taste "links oben" ist gedrückt
ist y2 auf High?
Ja: Taste "rechts oben" ist gedrückt
x1 wieder auf Eingang und Low (damit Pullup ausgeschaltet)
x2 auf Ausgang und auf High
ist y1 auf High?
Ja: Taste "links unten" ist gedrückt
ist y2 auf High?
Ja: Taste "rechts unten" ist gedrückt
x2 wieder auf Eingang und auf Low (damit Pullup ausgeschaltet)
Da kommt keine Schleife vor.
Ah dann war ich ja schon nahe dranne also
DDRB = 0x01; // x1 auf ausgang
PORTC = 0x01; //x1 auf High
If(PINB & (1 << 0) // ist y1 auf High
{taste = 1;}
If(PINB & ( 1<< 1) // ist y2 auf High
{taste = 2;}
DDRB = 0x02; // x1 auf eingang und x2 als ausgang
PORTC = 0x02; //x2 auf high
If(PINB & (1 << 0) // ist y1 auf high
{taste = 3;}
If(PINB & ( 1<< 1) // ist y2 auf high
{taste = 4;}
else
{taste = -1;} // gebe ansonsten den wert -1 zurück
jan schrieb:> Ah dann war ich ja schon nahe dranne also> DDRB = 0x01; // x1 auf ausgang> PORTC = 0x01; //x1 auf High> If(PINB & (1 << 0) // ist y1 auf High> {taste = 1;}> If(PINB & ( 1<< 1) // ist y2 auf High> {taste = 2;}>> DDRB = 0x02; // x1 auf eingang und x2 als ausgang> PORTC = 0x02; //x2 auf high> If(PINB & (1 << 0) // ist y1 auf high> {taste = 3;}> If(PINB & ( 1<< 1) // ist y2 auf high> {taste = 4;}> else> {taste = -1;} // gebe ansonsten den wert -1 zurück
rück das doch endlich mal vernünftig ein
1
DDRB=0x01;// x1 auf ausgang
2
PORTC=0x01;//x1 auf High
3
4
If(PINB&(1<<0)// ist y1 auf High
5
taste=1;
6
7
If(PINB&(1<<1)// ist y2 auf High
8
taste=2;
9
10
DDRB=0x02;// x1 auf eingang und x2 als ausgang
11
PORTC=0x02;//x2 auf high
12
13
If(PINB&(1<<0)// ist y1 auf high
14
taste=3;
15
16
If(PINB&(1<<1)// ist y2 auf high
17
taste=4;
18
else
19
taste=-1;// gebe ansonsten den wert -1 zurück
Frage: zu welchem if gehört das letzte else und was bedeutet das jetzt
dafür, dass du taste auf -1 setzt?
Setze taste vor dem ganzen Klimbimm auf -1 und wenn du eine gedrückte
Taste erkennst (weil das entsprechende y auf high ist), dann
überschreibst du taste mit dem entsprechenden Code.
Apropos HIgh/low
Wie sorgst du eigentlich dafür, dass die Spaltenleitungen bei nicht
gedrückter Taste auf Low sind? Hast du externe Pulldown Widerstände?
so bin wieder zuhause :)
vergiss das mit dem else das war ein denkfehler von mir :)
da du sagtest das es bei nicht gedrückter taste -1 ausgeben soll.
Und ich das ganze noch verstehen musste.
Das mit den Pulldown widerständen wäre das nächste gewesen was ich
wissen wollte :)
Habe mir das tutorial ja durchgelesen mit den tastern, dort wird gesagt
das ich einen 10k widerstand pro taster benötige.
siehe
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Tasten_und_Schalter
In einem alten Thread von mir wurde mir aber gesagt ich soll blos
470ohm nehmen und die an allen 8 leitungen klemmen, diese kommen dann
direkt an den atmega8.
Eine led über taster blinken zu lassen habe ich schon geschaft, ich wiß
nur nicht wie ich es bei diesem keypad anwenden kann bzw. darf.
Tut mir wirklich leid das ich euch mit so viel unwissenheit bestrafen
muss aber ich kann besser durch praktix lernen zudem amcht es mehr spaß
habe nie etwas mit technik am Hut gehabt außer kleinere Private sachen
und muss es mir eben inkl. der Sprache C++ alles selber beibringen.
Ich danke euch nochmals für die Hilfe :)
MfG Jan
Jan schrieb:> Tut mir wirklich leid das ich euch mit so viel unwissenheit bestrafen> muss aber ich kann besser durch praktix lernen
Echt?
Dann bist du der erste von 10000, bei dem es funktioniert, die ersten
grundlegenden Schritte zu überspringen.
ach ich überspringe die doch nicht,
stell dir doch mal bitte vor du fängst in einem neuen Themenberreich an
welches dich stark interessiert,
du liest tutorials fängst mit kleineren prjekten an und versuchst dich
immer zu steigern.
Das man hier und da dann mal Wissenlücken bekommt ist vorprogrammiert
schon alleine durch die Tatsache das viele Tutorials in Fachbahnhof
geschrieben sind und man nicht wirklich alles nachvollziehen kann.
Und ich denke da ist ein Forum wirklich toll für Leute die anderen
leuten helfen.
Ich komme selber aus dem Berreich der gigitalen Gestalltung, ich kann
fast jedes Adobe Produkt blind bedienen, und helfe selber gerne in Foren
mit dem Wissen aus :).
Möchte jetzt gerne aber einen anderen Weg einschlagen und gebe wirklich
mein bestes Informationen aufzusammeln, zu verstehen und anzuwenden.
Es klappt halt nicht immer also bitte ich um ein bisschen nachsicht.
Wenn es dir/euch zu anstrengend ist mit einem Anfänger und Wissenslücken
unter die Arme zu greifen dann braucht man ja nicht antworten.
Trotzdem bin ich dankbar für jede Hilfe.
Also wie mache ich das jetzt mit den Widerständen? :)
PS: habe mir jetzt extra das Buch "Elektro T" mit dem lösungsbuch
bestellt für 48€ und naja war bis vor kurzem noch Schüler billig ist es
nicht gewesen, hofe das es mich viel weiter bringt :)
Jan Schmitz schrieb:> könnt Ihr mir sagen ob das jetzt so klappt?
Warum probierst du es nicht einfach selber und lernst aus deinen
Fehlern? Damit kommt man meistens schneller voran.
weil ich noch die passenden widerstände kaufen muss :)
Und da es noch nciht für mich geklärt ist wie ich das mit den pullups
nun mache, dachte ich schreibe ich schon mal den code und veröffentliche
ihn hier :)
ah sehe schon vergessen den den PIN 0-3 als eingang zu deklarieren.
ist bearbeitet :)
Dir ist nicht wirklich zu helfen, da Du die Arbeit Anderen überlassen
willst, was weder Dir noch andre weiter bringt. Mach Deine Hausaufgaben
und melde Dich wen Du echte Probleme hast!!!
warum will ich meine Arbeit anderen überlassen?
Den code habe ich jetzt mit hilfe selbst erstellt.
Ich brauche halt nur ne erklärung wegen den pullups mehr nicht!
wie gesagt im tutorial sind angegeben 10k siehe geposteten link,
und in nem anderen thread wurde mir gesagt das ich an jeden der 8
leitungen einen 470ohm widerstand hängen soll.
Ich würde nur gerne wissen was nun und vor allem wieso.
Da es ein einzelfall ist finde ich nicht viel in Google.
Und wenn ich es wüsste würde die keymap längst dran hängen.
Habe nur kb was kaputt zu machen 5€ für einen kontroller sind für einen
nicht verdiener sehr viel :(
Tut mir leid Herr schlaumeier!
Bisschen freundlichkeit schadet nicht ;)
Jan Schmitz schrieb:> Habe nur kb was kaputt zu machen 5€ für einen kontroller sind für einen> nicht verdiener sehr viel
Ich hab bis jetzt nur einen Controller kaputtbekommen, und das lag an
einem defekten Schaltnetzteil. Ich habe die Atmegas teilweise bis zur
Vergasung gequält und bis jetzt ist nichts passiert. Probieren geht in
diesem Falle über Studieren.. Ausprobieren, debuggen, Fehler machen,
Lernen. Ist für die meisten hier wohl der Alltag.
sind die so hartnäckig?
gut werde dann morgen zum elektroladen wandern und mir die widerstände
kaufen die ich für beide varianten benötige.
Hatte nur große angst das der durch die falschen bausteine kaputt geht.
Also wenn du PullUp vergisst kannst du nichts kaputtmachen. Denke daran
die Ausgänge nicht direkt kurzzuschliessen, den Controller nicht zu
verpolen, usw..dann darfst du dich in der Programmierung richtig
austoben (Solange du nicht mit den Fuse spielst kann da im Prinip nichts
kaputtgehen)
ah okay danke, aber was heißt die ausgänge nicht direkt kurzschließen?
dürfte ich dann das machen?
PORTB0--|==|-x-|==|--PINC2
r1 t1 r2
wobei r1 der widerstand an x1 anliegt und r2 an y2 (siehe ganz oben)
Naja das heisst, nicht den Ausgangsport auf High setzen und direkt auf
GND schalten.
Wenn du Ausgänge mit Eingängen verbindest ist das Gefahrenlos, sollte
auch ohne externe Pullups gehen (Eingänge sind hochohmig).
Jan Schmitz schrieb:> ah okay danke, aber was heißt die ausgänge nicht direkt kurzschließen?
was ist daran miss zu verstehen ????
MACH DEINE HAUSAUFGABEN !!!!
man(n) solle schon wissen was man unter einem "kurtzschluss" zu
verstehen ist, bevor man sich an einen µC setzt!
ein paar euronen in Bücher sollte man(n) auch als "nicht Verdiener"
investieren !!!
um SEINE Hausaufgaben machen zu können !
mfg
der schlaubeier
Boa ... ich weiß nicht, was so manch ein Troll in einem Forum zu suchen
hat. Und damit meine ich Beiträge, wie den von Manfred John. Intolerant
... einfach assozial ist das.
Es gibt nun mal Menschen, die nicht sonderlich gut aus Büchern lernen
können und besser damit klar kommen ihre eigenen Fragen zu stellen. In
einem Forum wird man weder dazu gezwungen einen Beitrag zu
lesen/verfolgen, noch darauf zu antworten. Also ... warum lassen solche
Trolle nicht einfach solche Threads links liegen und sparen sich die
Zeit und den Strom auch noch dumme Kommentare dazu abzugeben?
Wer helfen will tut es, wer nicht helfen will lacht mal darüber (weil er
selbst ja nie klein angefangen hat) und zieht weiter.
@Jan:
Was hier mit Kurzschluss gemeint ist: Durch einen Fehler im Programm
könnte man die Pins von X und Y beide auf Ausgang schalten. Wenn dann
noch unterschiedliche Level ausgegeben werden, dann hat man einen
Kurzschluss und einer oder beide PINs verabschieden sich.
Was die Widerstände betrifft: Für die Funktion würde es reichen, wenn am
Eingangs-Port die Pulldown-Widerstände angeschlossen sind.
Allerdings macht es aus einem anderen Grund auch Sinn die Ausgäng mit
Pulldown-Widerständen zu versehen. Die Zeilen werden ja immer nur kurz
auf Ausgang geschaltet. Das heißt aber auch, dass die gerade nicht
benutzten wie eine Antenne wirken.
Den Tipp, dass du keine Schleife brauchst finde ich auch nicht
sonderlich gelungen! Bei sich wiederholenden Tätigkeiten macht eine
Schleife schon Sinn! Also hier konkret in deiner keyboard-Funktion.
int keyboard()
{
int taste, x, outVal, offset;
outVal = 0x08;
offset = 0;
taste = -1;
for (x=0; x<4; x++)
{
DDRC = outVal;
PORTC = outVal;
outVal = outVal<<1;
if(PINB & (1 << 0))
{ taste = 1 + offset; }
if(PINB & ( 1<< 1))
{ taste = 2 + offset; }
if(PINB & ( 1<< 2))
{ taste = 3 + offset; }
if(PINB & ( 1<< 3))
{ taste = 0 + offset; }
offset += 3;
if( taste>9 )
{ taste = 0 }
}
return (taste);
}
Bitte bedenken, diese Implementierung macht (fast) genau das, was Deine
Funktion vorher gemacht hat. Ich finde es allerdings nicht besonders
clever für die nicht-Zahlen-Tasten 0 auszugeben. Die Auswertung -also
welche Tasten will ich auswerten und welche nicht- sollte das aufrufende
Programm machen. Dann lässt sich nämlich keyboard in allen Programmen
nutzen, die du in Zukunft schreibst und die ein solches Keyboard nutzen.
Das hier
ergebnis += 100 * keyboard();
ergebnis += 10 * keyboard();
ergebnis += keyboard();
Hier gibt es 2 Probleme!
1. Da die Funktion keyboard keine loop hat, die auf eine Eingabe wartet
musst Du das hier machen. Ansonsten ist die Chance hoch die -1 zu lesen
(oder 0 in Deiner alten Version).
2. da ein uC ein wenig schneller reagiert als Du, wird er hier einen
glatten Durchmarsch machen und 3 mal das selbe erkennen.
int key;
while( (key=keyboard()) == -1 ) ergebnis+=100*key;
do { waitms(2) } while( (key!=keyboard()) != -1 );
while( (key=keyboard()) == -1 ) ergebnis+=1*key;
do { waitms(2) } while( (key!=keyboard()) != -1 );
while( (key=keyboard()) == -1 ) ergebnis+=key;
do { waitms(2) } while( (key!=keyboard()) != -1 );
Macht durchaus Sinn auch das in eine Funktion zu packen .. sowas wie
keyboardWait() ....
MagIO schrieb:> Bei sich wiederholenden Tätigkeiten macht eine> Schleife schon Sinn! Also hier konkret in deiner keyboard-Funktion.
trotz scharfem hingucken sehe ich nicht, wo du in deiner Schleife deine
Schleifen-Laufvariable x verwendet hast.
Wozu war also noch mal in deiner for-schleife die Verschleifung gut
?????
MagIO schrieb:> Es gibt nun mal Menschen, die nicht sonderlich gut aus Büchern lernen> können und besser damit klar kommen ihre eigenen Fragen zu stellen.
Dann sollen sie fragen.
"Macht das mal für mich" ist keine Frage.
Und im übrigen ist die Ansicht Unsinn. Sie hat noch nie funktioniert,
funktioniert heute nicht und wird auch nie funktionieren. Ein gewisser
angelesener Grundstock an Grundlagen muss nun mal sein. Wer nach den
ersten Seiten Tutorien nicht kapiert hat, wie das mit den Pullup
Pulldown Widerständen läuft und wozu man sie braucht, hat kein
Verständnisproblem, sondern einfach zumindest die Tutorien nicht
gelesen. Warum soll man jemanden hier im Forum die ganze Sache noch
einmal lang und breit auseinandersetzen, wenn das alles ausführlichst in
den Tutorien beschrieben ist? Wenn konkrete Fragem dazu auftauchen: ok,
kein Problem. Aber "Also wie ist das mit den Pulldown" ist keine
zugelassene Frage, denn das STEHT in den Tutorien.
Und wer das Tutorium gelesen hat, weiß, dass der AVR Pullup Widerstände
eingebaut hat und er daher keine externen Pulldown kaufen muss. Er muss
halt einfach nur mit dem arbeiten, was er hat. Darauf hätt ich nämlich
schon die ganze Zeit gewartet - Auf die Frage: Wenn ich keine Pulldown
habe, wie mach ich das mit den eingebauten Pullup.
Aber diese Frage ist nicht gekommen.
""Macht das mal für mich" ist keine Frage."
Der OP ist doch direkt mit seinem eigenen Code eingestiegen! Da kann ich
kein "mach das mal für mich" erkennen!
Auch der Hinweis auf ein Tutorial ist eine valide Antwort. Und wie
gesagt ... man muss ja nicht antworten!
Mit dem Hinweis sich das Grundwissen doch per Bücher etc. anzueignen
kann man sich die ganze Schule sparen! Ist doch auch alles nur
Grundwissen! Also .. hier hast Du nen Packen Bücher ... lies mal und
komm in 10 Jahren wieder.
"Wer nach den
ersten Seiten Tutorien nicht kapiert hat, wie das mit den Pullup
Pulldown Widerständen läuft und wozu man sie braucht, hat kein
Verständnisproblem, sondern einfach zumindest die Tutorien nicht
gelesen."
Das ist genau die Engstirnigkeit, die ich angeprangert habe! Lies Du
erst mal was über Gehrin und Lernen, vielleicht kommst Du dann auch
dahinter, dass eben nicht alle Gehirne gleich ticken!
Das so ne Antwort nun von einem Moderator kommt spricht nun nicht gerade
für dieses Forum.
Ich denke es sollte Ziel eines Moderators sein im Forum eine Stimmung
aufzubauen, wo man sich gerne gegenseitig hilft und wo solche
anmach-posts nicht nötig sind.
@Wegstaben Verbuchsler:
x wird nur zum zählen benötigt. Ich hatte erst statt dem offset da
stehen
taste = 1 + x*3;
Habe dann aber die Multiplikation durch ein Aufaddieren von offset
ersetzt. Sicherlich kann man dann auch gleich offset als Schleifenzähler
benutzen und mit +=3 hochzählen. Sagen wir mal das ist eine Hausübung
;o)
MagIO schrieb:> ""Macht das mal für mich" ist keine Frage."> Der OP ist doch direkt mit seinem eigenen Code eingestiegen! Da kann ich> kein "mach das mal für mich" erkennen!
Sorry.
Hingerotzer Code ohne Sinn und Verstand kann man nicht wirklich als
Vorarbeit werten.
> Mit dem Hinweis sich das Grundwissen doch per Bücher etc. anzueignen> kann man sich die ganze Schule sparen!
Auch das zieht nicht.
Es ist nun mal ein Unterschied, ob ich einen Menschen aus Fleisch und
Blut vor mir habe, der mir die Dinge erklärt oder ob ich mit den Mitteln
eines Forums auskommen muss. Natürlich funktioniert Ersters besser. Aber
den Luxus haben wir hier nun mal nicht. Daher haben sich Leute gefunden,
die Tutorien geschrieben haben. Nur lesen und durcharbeiten müsste man
sie halt.
Wenn er das Notwendige dort nicht lesen kann, warum kann er dann genau
dasselbe auf einmal hier lesen?
> Mit dem Hinweis sich das Grundwissen doch per Bücher etc.> anzueignen kann man sich die ganze Schule sparen!
Du willst es nicht verstehen, oder?
Da ist jemand, der schafft es alleine nicht einen simplen Taster an
einem Portpin sauber abzufragen. Und den willst du durch eine
Tastenmatrix durchtragen? Wie soll das gehen?
Aber mach mal.
Ich kümmere mich in der Zwischenzeit gerne um die vielen andere Frager,
die ihre Hausaufgaben gemacht haben und bei denen man nicht bei Adam und
Eva anfangen muss, weil sie die Basics aus den Tutorien schon gelernt
haben.
Du brauchst keine Widerstände zu kaufen.
Machs wie alle, nimm die internen Pullups und lese ein, welcher Pin auf
low gezogen wird.
Hier ein Beispiel:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=519870#519870
Die Funktion ist ganz einfach.
Zuerst werden alle Zeilen auf low gesetzt und die low-Spalte gesucht.
Und dann umgekehrt, d.h. alle Spalten auf low und die low-Zeile suchen.
Das NOP ist wichtig, da die Eingänge des AVR einen Zyklus früher
gelatcht werden.
Peter
@Karl Heinz Buchegger:
Aus meiner Sicht willst Du es nicht verstehen!
"Da ist jemand, der schafft es alleine nicht einen simplen Taster an
einem Portpin sauber abzufragen. Und den willst du durch eine
Tastenmatrix durchtragen? Wie soll das gehen?"
Ganz richtig ... er hat Probleme. Aber helfen die blöden anmach-posts
weiter? NEIN! Der Anmacher verschwendet seine Zeit und der Fragesteller
wird vergrault. Zudem sinkt das Niveu des Forums mit der Zeit ins
Bodenlose.
Vergrault man die Anfänger nicht gleich, dann können die, die schon
einen Tick weiter sind den blutigen Anfängern auch weiterhelfen.
"Aber mach mal.
Ich kümmere mich in der Zwischenzeit gerne um die vielen andere Frager,
die ihre Hausaufgaben gemacht haben und bei denen man nicht bei Adam und
Eva anfangen muss, weil sie die Basics aus den Tutorien schon gelernt
haben."
Genau das sag ich doch! Kümmere Dich um die Fälle, die dich
interessieren. Die, die dir zu einfach sind oder unnütz erscheinen lass
VON ANFANG AN links liegen! Mit dem Genörgel hier ist wie gesagt
niemandem geholfen - dir nicht, dem OP nicht und dem Forum generell auch
nicht!
"Wenn er das Notwendige dort nicht lesen kann, warum kann er dann genau
dasselbe auf einmal hier lesen?"
Weil man hier konkret auf Seine Fragen antworten kann und auf die
Gedankengänge eingehen kann. Mit etwas Einfühlungsvermögen kann man
evtl. erkennen wo der Denkfehler liegt und die Antwort entsprechend
formulieren. Du hast natürlich recht ... wenn einem im Forum nur 1 zu 1
wiedergekäut wird, was im Tutorial steht dann macht es keinen
Unterschied. Wenn man aber auf den Fragenden eingeht, dann ist das wie
Unterricht.
"Es ist nun mal ein Unterschied, ob ich einen Menschen aus Fleisch und
Blut vor mir habe, der mir die Dinge erklärt oder ob ich mit den Mitteln
eines Forums auskommen muss."
Einfühlungsvermögen kann man auch im Forum an den Tag bringen! Und wie
Du ja weißt gibt es auch hervorragende Beiträge - sogar von Dir:
siehe Beitrag "Re: Index vom Maxwert eines Array ermitteln und umsortieren"
"Hingerotzer Code ohne Sinn und Verstand" ... und wieder so ne asoziale
Anmache ... wie gut, dass es Leute wie Dich gibt, die alles Wissen schon
mit der Muttermilch aufgenommen haben.
Was mich jetzt an diesem Thread wirklich am meisten stört ist, dass
solche Posts von einem Moderator kommen. Überarbeitet? Oder einfach nur
Fehl am Platz?
Natürlich kann man die Stimmung in einem Forum nicht von jetzt auf
gleich ändern. Aber dass ein Forum auch mit solchen Fragen/Threads gut
umgehen kann, das weiß ich ganz sicher, weil ich in einem solchen Forum
schon seit Jahren angemeldet bin! Nur, was will man schon erwarten wenn
nichteinmal der Moderator mit gutem Beispiel voran geht.
Wow vielen herzlichen Dank MagIO,
meiner Ansicht nach geht es hier wirklich sehr engstirnig zu, sobald ich
hier ein Programm abliefere was nicht zu 95% fertig ist wird einem
gesagt ich lass die andern für mich arbeiten.
Wobei ich ja nicht mal die Lösung such nur eben Ansätze sonst würde ich
ja nicht fragen wenn ich nicht auf die Lösung komme :/.
Naja trotzdem vielen dank an alle bisherigen Helfer :)
Ich glaube ich hätte es nicht geschaft ohne die Tipps :)
@MagIO
Daran das der einfach durchrennt habe ich nicht gedacht.
leider habe ich eine Frage zu deinem code
while( (key=keyboard()) == -1 ) ergebnis+=key;
do { waitms(2) } while( (key!=keyboard()) != -1 );
wenn key das gleiche ist wie keyboard und das es dem wert von -1
entspricht.
addiere zu dem Ergebnis den key wert.
Warum? ich meine der wert wird ja in der keyboard funktion direkt auf -1
gestellt, wieso soll dann das ergebnis direkt mit dem key wert addiert
werden?
Reicht es den nicht einfach hinter jeder keyboard funktion die do
schleife auszuführen dort wird ja gewartet bis ein neuer wert eingegeben
wird?
PS: knabber mitlerweile 20 min an deiner Lösung kann den obrigen Teil
aber immer noch nicht nach vollziehen :/
Wenn ich zuhause bin werde ich den code mal für eine konsolenanwendung
verwenden evtl. erkenne ich es ja dann :)
Und achja kennst du evtl. weitere große Foren für mikrocontroler?
Ich habe hier sehr stark das Gefühl das einsteiger die nicht sofort
alles wissen hier nicht erwünscht sind.
MfG und ebsten Dank :)
Oh ... da hab ich Dir auch einen Bug eingebaut ;o)
So sieht es besser aus:
while( (key=keyboard()) == -1 );
ergebnis+=key;
do { waitms(2) } while( keyboard() != -1 );
Sorry, da hat wohl der Kaffee noch nicht gewirkt.
Die Idee war, dass keyboard im dem Fall, dass keine Taste gedrückt ist
-1 zurückgibt. Wie oben schon von jemandem erwähnt kann das aufrufende
Programm also selbst entscheiden, ob es warten will, oder nicht.
key=keyboard() fragt also das keyboard ab und speichert den Wert in key.
Im nächsten Schritt wird der Wert aber noch gegen -1 geprüft und die
while-Schleife wird so lange wiederholt, bis eine Taste gedrückt wurde,
also key <> -1 ist.
Zu ergebnis+=key; könnte man noch sagen, dass hier bewusst nicht nochmal
keyboard() aufgerufen wird. Denn in einem von keine Ahnung wieviel
millionen Fällen kann es vorkommen, dass genau zwischen dem Aufruf
innerhalb der while-Schleife und dem Aufruf von ergebnis+=... die Taste
wieder losgelassen wird. Darum die key-variable. Es wird sichergestellt,
dass mit dem Wert gearbeitet wird, der auch zum Abbruch der Schleife
geführt hat. Wenn man das nicht so macht, dann hat man Bugs, die zwar
nur sehr selten auftauchen, dafür aber um so schwerer zu finden sind.
Die folgende Schleife soll dann eben wieder darauf warten, dass die
Taste auch wieder losgelassen wird bevor sie für die nächste
dezimal-Stelle wieder neu abgefragt wird. Wie gesagt .. im Vergleich zu
deinem Finger ist so ein uC schon verdammt schnell!
Die 2ms Wartezeit sollen einigermaßen sicherstellen, daß ein Prellen der
Taste nicht dazu führt die Schleife zu schnell zu verlassen. Aber ich
glaube zum Thema Prellen gibt es hier auch ein Tutorial.
Mit anderen Worten, um eine 3 stellig Zahl einzugeben musst du hier
Taste drücken
Taste wieder loslassen (auch wenn die 2. Stelle gleich ist)
Taste drücken
Taste wieder loslassen....
Später kann man das immer noch ändern! Also z.B. wenn die Taste >1 sec
gedrückt bleibt, dann wird sie auch für die 2. Ziffer benutzt. >2 sec ->
3.Ziffer. Aber das ist Luxus ;o)
Peter Dannegger schrieb:> Die Funktion ist ganz einfach.> Zuerst werden alle Zeilen auf low gesetzt und die low-Spalte gesucht.> Und dann umgekehrt, d.h. alle Spalten auf low und die low-Zeile suchen.> Das NOP ist wichtig, da die Eingänge des AVR einen Zyklus früher> gelatcht werden.>>> Peter
Danke aber ich habe ja nur die Spalten auf low heißt eingang, die zeilen
werden ja alle als Ausgang benutzt.
das mit dem NOP verstehe ich nicht.
Ist das okay wen ich einfach alle internen Pullups aktiviere und
aktiviert lasse? Also gleichzeitig oder gibt das Probleme?
würde dan so aussehen.
DDRB 0xF0 //PINB 0-3 als eingang setzen
PORTB 0x0F // zugehörige pullups aktivieren
MfG :)
Ah ja vielen dank jetzt habe ich kapiert hat mich wirklich das fehlende
; verwirrt ^^
das mit den 2 sec und dem entprellen habe ich schon verstanden aber
trotzdem vielen dank :)
hatte für mich halt keinen Sinn gemacht den wert -1 in key zu speichern
:)
Dann ahbe ich das ja richtig gelesen nur nciht verstanden :)
werde dann mal anfangen mit dem löten, und die keymap einbauen.
Code fertig schreiben und mich dann wieder melden,
vielen Dank!!!
Also ich kann Karl Heinz schon gut verstehen, wenn auch manches schon
beleidigend aufgefasst werden kann.
Denn wenn man einen Taster schonmal erfolgreich betrieben hat, der weiß,
weshalb man einen Dropdownwiderstand braucht und auch, warum 470 Ohm
schon recht/unnötig klein ist. 2 Minuten gegoogled:
http://www.rn-wissen.de/index.php/Pullup_Pulldown_Widerstand
Zitat: "Wenn es nur darum geht, einen Prozessor-Pin, an dem sich keine
lange Leitung befindet, auf einen definierten Pegel zu bringen, können
es auch über 10 kOhm sein.
Bei Arbeiten im Bereich der Mikrocontroller haben sich Werte von 4,7
kOhm für Pullup- bzw. 10 kOhm für Pulldown-Widerstände in den meisten
Fällen bewährt. "
Ich weiß nicht, wie man das falsch verstehen kann oder was ich anderes
sagen sollte. Wenn man durcheinander ist, weil man mal was anderes
gehört hat, dann kann man ja auch schreiben, wo man das gelesen/gefragt
hat (denn ich kann mir vorstellen, dass das nicht ohne Grund so ein
kleiner Widerstand war). Es sei denn der Antworter hatte keine Ahnung
oder hat die Frage falsch verstanden.
Wenn jemand schon ein oder mehrere Tutorials gelesen hat und meint, er
versteht es nicht, dann kann das ja schon sein, nur weiß ich nicht, wie
jemand das dann noch anders Erklären kann, zumindest bei recht simplen
Dingen wie Pullup/-downwiderständen. Sicher kann man dann nochmal
nachfragen, was er nicht versteht oder ihm eine eigene Beschreibung
nochmal schreiben, die inhaltlich identisch ist, doch dadurch lernt bzw
versteht er evtl doch die Funktion, doch wie man KONKRETE Fragen stellt
nicht. Und ich denke das ist genau das, was Karl Heinz meint. Anders
wäre es ja, wenn er fragt, warum die Ausgänge auf Eingänge umgestellt
werden (also als Beispiel). Das ist eine konkrete Frage und solche
werden hier meiner Erfahrung nach auch IMMER normal beantwortet.
Jeder hat mal angefangen, keine Frage. Aber man sollte, egal ob mit
Büchern, Unterricht, Foren oder Tutorials mit einfachen Sachen anfangen
und sich hocharbeiten. Ich will mir einen MP3-Player bauen mit
Festplatte, USB-Host und SD-Kartenleser. Dafür gibt es bestimmt nicht
mal wirklich Tutorials, hab ich auch nicht nach gesucht. Aber ich
arbeite drauf hin. Das einfachste wird denke ich die Wiedergabe per
SD-Karte sein, daher fang ich damit mal an. Um mit SD-Karten zu
kommunizieren, will ich SPI benutzen. Also ist das erste, was ich mache,
eine SD-Karte oder EEPROM mit SPI ansteuern. Dann frag ich aber auch
nicht in einem Forum, wie ich ein MP3-Player bauen kann, sondern, wieso
ein gewisses Problem beim SPI nicht funktioniert oder wie das und das in
dem und dem Tutorial gemeint ist. Es ist natürlich komplizierter ein
MP3-Player zu bauen als eine Tastaturmatrix zum laufen zu kriegen. Aber
vom Prinzip her ist es ähnlich, man arbeitet auf etwas hin und muss halt
den auch evtl nervigen Weg dahin gehen. Nämlich eine Taste mit dem
Pulldown-Widerstand zu betreiben. Dann nimmt man nen zweiten Taster.
Dort kann man schonmal gucken, wie geprüft wird, welche Taste gedrückt
ist, was passieren soll, wenn keine gedrückt ist, was passieren soll,
wenn beide gleichzeitig gedrückt werden oder was passieren soll, wenn
man eine Taste länger drückt. Dann kann man die beiden Taster über 2
Ausgänge und einem Eingang betreiben und der Rest ist nur kopieren.
@Jan: Was mir noch aufgefallen ist:
Jan Schmitz schrieb:> int main(void)> {> int i, Zahl, ergebnis = 0;> int keyboard();
Das "int keyboard();" ist der Prototyp der Funktion und gehört deshalb
nicht in die main sondern davor.
so also sobald ich diesen part reinpacke:
while( (key=keyboard()) == -1 );
ergebnis+=key;
ergebnis *= 100;
do
{
_delay_ms(2);
}
while( keyboard() != -1 );
zeigt das display mir nur balken an,
weiß jemand evtl schon wo das problem liegt?
ich suche weiter
das habe ich auch vermutet, habe aber einen kleineren code gebastelt,
heißt wenn ich irgendeine Ziffer drücke müsste er ja dann weiter machen
und mir das ergebnis bzw. in dem neuen code mir die zahl anzeigen.
tut er aber nicht,
werde später mal eine led dranhängen und schauen ob die keymap überhapt
richtig funktioniert.
Jan Schmitz schrieb:> so also sobald ich diesen part reinpacke:
Wo reinpackst?
Bricht Dir wirklich ein Zacken aus der Krone, wenn Du den Codeabschnitt
formatierst (Postingregeln) und den kompletten compilierbaren Code als
Anhang postest?
Peter
tut mir leid war vertieft.
Im grunde bleibt es der gleiche code nur das 4 Tasten aktiv sind und es
übersichtlicher ist.
wenn ich
while( (key=keyboard()) == -1 );
ergebnis+=key;
ergebnis *= 100;
do
{
_delay_ms(2);
}
while( keyboard() != -1 );
rausnehme wird mir eine 0 angezeigt wenn nicht dann sehe ich nur blöcke.
habe jetzt mal ne led drangeklemmt und werde gleich ein Test machen ob
die keymap funktionstüchtig ist.
MFG
#include <avr/io.h>
#include "lcd-routines.h"
#include <stdio.h>
#include <util/delay.h>
int keyboard();
int main(void)
{
int i, Zahl, ergebnis = -1, key;
char xxx[16];
while( (key=keyboard()) == -1 );
ergebnis+=key;
ergebnis *= 100;
do
{
_delay_ms(2);
}
while( keyboard() != -1 );
lcd_init();
lcd_setcursor(0 ,1);
lcd_string("dezimal");
lcd_setcursor(0, 2);
sprintf(xxx,"%d",ergebnis);
lcd_string(xxx);
}
int keyboard()
{
int taste = -1, x = 0;
DDRB = 0xF0;
PORTB = 0x0F;
for (x=0; x<1; x)
{
DDRC = 0x40; // x1 auf ausgang
PORTC = 0x40; //x1 auf High
if(PINB & (1 << 0))
// ist y1 auf High
{taste = 1;
x++;}
if(PINB & ( 1<< 1))// ist y2 auf High
{taste = 2;
x++;}
if(PINB & ( 1<< 2)) // ist y3 auf High
{taste = 3;
x++;}
if(PINB & ( 1<< 3)) // ist y4 auf High
{taste = 0;
x++;}
}
return (taste);
}
Jan Schmitz schrieb:> for (x=0; x<1; x)
Das ergibt so keinen Sinn, es muss meiner Meinung nach "for (x=0; x<1;
x++)" sein. Dann kannst du auch die x++; in den ifs weglassen. Was
passiert denn, wenn du keine Taste drückst? Das x zählt nich hoch und
deine For endet nie.
Und:
http://www.mikrocontroller.net/articles/Formatierung_im_Forum
-> [ c] und [/ c]
wieso endet die nie?
ich weiß in der for schleife steht nur x statt x++ das ist mir aber
bewust, da das x nicht um 1 inkrementiert werden soll wen die schleife
wiederholt wird sondern nur wenn ich eine taste drücke deswegen steht
hinter jeder tastenabfrage ein x++, wodurch die schleife dann vor dem
nächsten durchlauf beendet wird.
Du kannst dann das x komlett weglassen, also
for(x=0;x<1;)
LCDs die Balken anzeigen sind in der Regel nicht richtig initialisiert.
Ich würde an deiner stelle in kleineren Schritten vorgehen, sonst ist es
schwierig den Fehler zu finden.
1. LCD austesten ... mal nen Text ausgeben ... mal ne Schleife und den
Zählerstand ausgeben
2. keyboard() alleine testen, also einfach ausgeben, was dir die
funktion zurückliefert.
3. Jetzt erst die 3 stellige Eingabe angehen
lcd_init(); macht man üblicherweise ganz am Anfang des codes oder lagert
es gleich in eine Init-Funktion aus. Und vor allem nur einmal! Weiter
oben hab ich mal code gesehen, wo init öfters aufgerufen wurde.
Das hier ist auf jeden fall schonmal falsch:
ergebnis+=key;
ergebnis *= 100;
ergebnis+=key;
ergebnis *= 10;
ergebnis+=key;
Du multiplizierst letztendlich die erste Ziffer mit 1010.
Entweder so:
ergebnis+= key*100 // Ziffer gleich an die richtige Stelle bringen
ergebnis+= key*10
ergebnis+= key
oder
ergebnis+=key
ergebnis*=10 // Ziffer von hinten nach vorne durchschieben
ergebnis+=key
ergebnis*=10
ergebnis+=key
Aber wie gesagt ... bring erst mal dal LCD zum laufen und mache dich
damit vertraut.
Hey, also textausgabe und die bloße rechnung klappt :)
heißt ohne keymap ich gebe dem Ergebnis einen vordefinierten wert.
Berrechnung und Ausgabe klappen ohne Probleme :)
Und die grade eingebaute led reagiert auch auf den Tastendruck.
hier schonmal der bisherige code :)
Die einzigen Meldungen die ich vom compiler bekomme sind:
helloworld.c:6: warning: function declaration isn't a prototype
helloworld.c:97: warning: function declaration isn't a prototype
MfG
An welchem Port hängt denn das Display? Vielleicht kommt keyboard() dem
Display ja ins Gehege. Generell sollte man beim löschen/setzen von Pins
eher mit bit-operationen arbeiten und nicht mit bytes - also zumindest
wenn ein Port für verschiedene Dinge benutzt wird:
DDRC = 0x40; // x1 auf ausgang
PORTC = 0x40; //x1 auf High
daraus wird dann
DDRC |= 0x40
PORTC |= 0x40
Zum löschen eines bits:
PORTC &= ~0x40
Zum löschen der 4 least significant bits:
PORTC &= 0xf0
Konnte man bei AVRs nicht auch direkt auf port-bits zugreifen??? Zu
lange her.
Was ist hier wohl zuviel:
...
while( (key=keyboard()) == -1 );
ergebnis+=key;
ergebnis+= key*10;
do
...
Ein lcd_init ist immer noch zuviel.
sprintf(texxt,"%s",Result); ist auch Quatsch. Wenn Result doch eh schon
ein String ist, warum dann in einen anderen String kopieren??
ah okay code ist angepasst, man übersieht echt schnell was.
ehm nein ich denke nicht PORTPINS C und B sind vollkommen frei das
display hängt außschließlich an PD
Bin ich jetzt verwirrt? Wenn man keine Taste drückt, kommt er doch aus
der For-Schleife und somit aus der keyboard()-Funktion nicht raus? Die
schleife ist beendet, wenn x=1 ist. Wenn aber keine Taste gedrückt wird,
wird kein x++ ausgeführt und somit bleibt x auch immer 0.
Jan Schmitz schrieb:> do> {> _delay_ms(2);> }> while( keyboard() != -1 );
Hier bleibt er in der while hängen. Er beendet es, wenn keyboard -1
wiedergibt. Dies passiert nie, da die Funktion nur beendet wird, wenn
die Forschleife beendet ist und dies passiert, wenn eine Taste gedrückt
wurde.
Achso ... nochwas:
for( i = 0; i < 8; ++i )
{
if( Zahl % 2 == 0 )
Result[ 7 - i ] = '0';
else
Result[ 7 - i ] = '1';
Zahl = Zahl / 2;
}
kann man auch so schreiben
for( i=7; i>=0; i--)
{
if( Zahl & 1 )
Result[ i ] = '1';
else
Result[ i ] = '0';
Zahl>>=1
}
Zahl%2 macht ne Division um an den Rest zu kommen, die im Vergleich mit
& sehr viel langsamer ist.
Zahl/2 ist auch viel langsamer, als ein shift nach rechts.
Michael Skropski schrieb:> Bin ich jetzt verwirrt? Wenn man keine Taste drückt, kommt er doch aus> der For-Schleife und somit aus der keyboard()-Funktion nicht raus? Die> schleife ist beendet, wenn x=1 ist. Wenn aber keine Taste gedrückt wird,> wird kein x++ ausgeführt und somit bleibt x auch immer 0.>> Jan Schmitz schrieb:>> do>> {>> _delay_ms(2);>> }>> while( keyboard() != -1 );>> Hier bleibt er in der while hängen. Er beendet es, wenn keyboard -1> wiedergibt. Dies passiert nie, da die Funktion nur beendet wird, wenn> die Forschleife beendet ist und dies passiert, wenn eine Taste gedrückt> wurde.
Ich glaub die keyboard()-Funktion is so nich ganz logisch. Wenn keine
Taste gedrückt wurde, soll -1 wiedergegeben werden. Doch wenn keine
gedrückt wurde, wird die Forschleife nicht beendet (da die nur beendet
wird, wenn x >= 1 ist und das nur passiert wenn x inkrementiert wird,
was nur passiert wenn man eine Taste drückt.
Also müsste man schreiben:
for(x=0; x<1; x++)
Und da am ende das x++ ausgeführt wird und die Schleife beendet wird,
kann man sie auch gleich weglassen. Wie am Anfang schon gesagt, die
Schleife kommt beim Aufruf der keyboard()-Funktion und nicht innerhalb
der Funktion.
Edit:
Kommentier die ForSchleife einfach mal aus und probiers.
sprich so:
Die for-Schleife war ja so in meinem Vorschlag von weiter oben nicht so
vorgesehen. Eigentlich war der Tipp, dass keyboard() nicht wartet.
for( x=0; x<1; )
wartet so lange, bis eine Taste gedrückt wurde. In den if-Blöcken wird
ja immer x hochgezählt. Wenn man eine Taste drückt steht dann eben ne 1
drin und die Schleifen-Bedingung wird falsch -> Schleife beendet
Ein -1 wird es mit dieser for-Schleife nie geben und damit funktioniert
das Warten auf "Taste loslassen" nicht!
Jep, danke Michael!
Also, Jan, schau Dir nochmal die keyboard-funktion in dem Post von 08:32
an.
@ MagIO
danke habe es mal geändert :)
@Michael
er soll ja auch nicht aus der Schleife raus.
er soll die Schleife ja solange wiederholen bis ich eine Taste gedrückt
habe.
und erst weiter machen wenn ich die losgelassen habe.
Wobei ich sehe garde muss ja eigentlich die zuweisung von -1 der taste
inerhalb der schleife geschehen.
Sonst kann der wert nciht mehr geändert werden.
Jan Schmitz schrieb:> er soll die Schleife ja solange wiederholen bis ich eine Taste gedrückt> habe.
Dann macht es aber keinen Sinn darauf zu warten, dass die Taste
losgelassen wurde:
Jan Schmitz schrieb:> do> {> _delay_ms(2);> }> while( keyboard() != -1 );Jan Schmitz schrieb:> Wobei ich sehe garde muss ja eigentlich die zuweisung von -1 der taste> inerhalb der schleife geschehen.
Das nützt genauso viel, solange du erst die Funktion beendest, wenn eine
Taste gedrückt wurde. Genau das ist ja der Grund, warum in die keyboard
Funktion KEINE Schleife reingehört. Übernehm in dem Programm aus deinem
Post von 19:28 und änder die Funktion so, wie ich in meinem Post von
20:01 geschrieben habe und probier es.
Jan Schmitz schrieb:> while( (key=keyboard()) == -1 );
Hier wartest du solange, bis eine Taste gedrückt wurde. Das ist soweit
auch richtig, nur tust du das im Moment ja sowieso schon in der
Funktion. In der Funktion das For rauswerfen und alles sollte
funktionieren.
Der Grund, warum da ursprünglich eine Schleife drin war, war der, dass
damit die Umschaltung von Ausgang zu Eingang und dem nächsten Eingang
zum Ausgang automatisiert wurde. Da du das aber untereinander
geschrieben hast, was kein Problem ist, wird diese Schleife aber
überflüssig.
@MagIO
ich ahbe es mir erneut gründlich angeguckt,
2 Fragen bleiben aber
1. was genau macht der intenger offset?, ich verstehe nicht warum der
ständig um 3 addiert wird.
Und die Schleife läuft ja 3 mal durch selbst wenn ich nichts drücke,
oder wartet er einen if block ab?
Meines wissens nicht und wenn ich dann inerhalb der drei Durchgänge
nichts drücke dann ist die schleife beendet und ich hatte keine zeit
eine Eingabe zu machen oder?
Und zu der -1, ich habe jetzt taste = -1; in der keyboard schleife
reingesteckt so das der tasten wert bei jeder Schleifenwiederholung auf
-1 gesetzt wird.
Oder habe ich da was missverstanden?
MfG und vielen Dank
PS: gibts heir eine spoiler funktion im Forum?
dann kann ich immer den aktuellen code anhängen ohne das es zu lang wird
für jeden?
@michael warte bitte ich sehe erst grade das du geschrieben hast :)
so habe mal auf Rat die do while, while und for schleife entfernt.
Ich komme weiter xD
so jetzt zeigt er mit zuerst ne 0 an.
und springt sofort weiter und zeigt an:
Hex: 00
Bin: 00000000
es ist so als würde er die keyboard() überspringen.
hier mal der neue code.
PS. habe mal die
1
while(keyboard()!=-1);
vor jedem key = keyboard(); eingefügt damit er keyboard so oft
wiederholt bis er einen richtigen wert hat jetzt habe ich aber wieder
blöcke.
MfG
Jan Schmitz schrieb:> es ist so als würde er die keyboard() überspringen.
Und das tut er quasi auch. Du hast in der main die While und do_while
Schleife weggemacht, die aber richtig waren. Das einzige, was falsch
war, war die Forschleife in der Funktion.
Wenn du hier:
1
lcd_init();
2
key=keyboard();
3
ergebnis+=key*100;
das schreibst:
1
lcd_init();
2
while((key=keyboard())==-1);// solange warten, bis eine Taste gedrückt wurde
3
ergebnis+=key*100;
4
while((key=keyboard())!=-1);// solange warten, bis die Taste losgelassen wurde bzw. bis keine Taste gedrückt wurde
oder etwas übersichtlicher und evtl einfacher zu verstehen:
1
lcd_init();
2
key=-1;
3
while(key==-1){// solange warten, bis eine Taste gedrückt wurde
4
key=keyboard();
5
}
6
ergebnis+=key*100;
7
while(key!=-1);// solange warten, bis die Taste losgelassen wurde bzw. bis keine Taste gedrückt wurde
8
key=keyboard();
9
}
sollte es gehen. Und das jetzt dementstprechend bei den Anderen Stellen
auch.
Die for-Schleife in meinem Beispiel soll einfach den code kürzer machen
mit dem die 4 X-Ausgänge nacheinander geschaltet werden. Der Unterschied
ist doch, dass dann beim Einlesen von Y jeweils andere Werte in Taste
Ausgang X1 => 1. Schleifendurchlauf: 1 2 3 0
Ausgang X2 => 2. Schleifendurchlauf: 4 5 6 0
Ausgang X3 => 3. Schleifendurchlauf: 7 8 9 0
Ausgang X4 => 4. Schleifendurchlauf: 0 0 0 0
Beim 1. Schleifendurchlauf ist der Offset =0, beim 2. =3 und beim 3.=6.
Je nachdem welches if dann passt wird die varable Taste damit
entsprechend errechnet. Wie schon gesagt, um die Tastatur komplett
auswertbar zu machen sollte man auch statt 0 für die anderen Tasten
einen entsprechenden Wert zurückliefern. Hier bietet sich an alle
Zahlen-Tasten so zu belassen (werte von 0-9 und für die anderen Tasten
Werte > 9 zu liefern.
Also die Empfehlung für keyboard() wäre, dass folgende Werte
zurückgeliefert werden:
-1 => keine Taste gedrückt
0-9 => entsprechende Ziffern Taste gedrückt
10-15 => andere Taste gedrückt
Die Schleife wird 4 mal durchlaufen und schaltet bei jedem Durchgang
eine Zeile aktiv und prüft die Eingänge. Wenn keine Taste gedrückt wird
sorgt die Schleife im Hauptprogramm fürs warten.
-1 muss nur vor der Schleife initialisiert sein. Wenn mehrere Tasten
gedrückt werden, dann "gewinnt" in dieser Implementierung die Letzte.
Eine genauere Auswertung (mehrere Tasten gleichzeitig) macht den Code
nur komplizierter. Und was dann? Tasten aufsummieren? Dann doch lieber
-1 zurückgeben? Ich denke du weißt, dass man nicht 2 Tasten drücken
sollte und andere User lernen es schnell :o)
was mir aufgefallen ist ist:
ich bekomme diese blöcke nur sobald ich diese while schleifen einbaue.
ohne hat es ja alles angezeigt nur wurde eben die eingabe übersprungen.
Kann es sein das der atmega8 nicht die while schleife verarbeiten aknn
und deswegen ein "error" ausgibt?
Sehen die Balken so aus?
http://www.moddingpower.de/artikel/minilcd/balken.jpg
Dann könnte ich mir nur vorstellen, dass du noch ein Hardware-Problem
hast. Sprich einen Kurzschluss von einem der Pins, die von Keyboard
benutzt werden hin zum Reset des Displays.
Vielleicht hattest Du ja auch deswegen die vielen lcd_init Aufrufe! Aber
die lösen ja nicht das eigentliche Problem. Im Gegenteil, wenn es einen
Kurzschluss zwischen 2 Ausgängen gibt ist das auf Dauer nicht gut für
den uC!
Sooo also der schaltplan ist obern hier nochmal alles schriftlich:
1
Display-AtmegaKeymap-Atmega
2
1VSSx114PB0
3
2VDDx215PB1
4
3VOx316PB2
5
4RS6PD4x417PB3
6
5RWy128PC5
7
6EN11PD5y227PC4
8
7D0y326PC3
9
8D1y425PC2
10
9D2
11
10D3
12
11D42PD0
13
12D53PD1
14
13D64PD2
15
14D75PD3
16
15LED+
17
16LED-
Und ja genau so sehen die Blöcke aus aber eben nur wenn ich eine while
schleife reinbaue.
Ohne hat es wie gesagt alles richtig angezeigt mir eben nur den wert 0
ausgegeben weil ich ncihts eingeben konnte.
MfG und besten Dank :)
Hi
Wenn deine Tastatur wirklich so angeschlossen ist, dann geht das
> DDRC = 0x40; // x1 auf ausgang> PORTC = 0x40; //x1 auf High
ins nirgendwo ->PC6. Und die Ansteuerung für PC2 fehlt.
MfG Spess
Update:
jetzt sehe ich nicht mehr nur oben blöcke sondern auch unten :/
aber normale textausgabe bzw. die rechnung an sich mit vordefinierten
wert kalppt wunderbar auch mit der anzeige.
PS. ich meine natürlich DDRC / PORTC 0x04 und nicht 1 :)
DDRC = 0x01;
PORTC = 0x01;
ist immer noch falsch, sollte meines Erachtens 0x02 sein.
Liegt R/W vom Display auch wirklich auf GND, oder hast Du es nicht
verbunden?
MagIO schrieb:> DDRC = 0x01;> PORTC = 0x01;>> ist immer noch falsch, sollte meines Erachtens 0x02 sein.>>> Liegt R/W vom Display auch wirklich auf GND, oder hast Du es nicht> verbunden?
habe darauf schon geantowrtet :)
sind das nicht 0x04?
gesucht: PC02 also das 3. bit
also 0/1 2 4 <- oder?
ja R/W liegt an GND kann es aber gleich nochmal nach löten.
Aber wenn es nicht daran anliegt dann funktioniert es doch agr nciht
oder?
ich meine eifnache sachen ohne while schleife funktionieren ja richtig.
MfG :) Jan
Jan Schmitz schrieb:> MagIO schrieb:>> DDRC = 0x01;>> PORTC = 0x01;>>>> ist immer noch falsch, sollte meines Erachtens 0x02 sein.>>>>>> Liegt R/W vom Display auch wirklich auf GND, oder hast Du es nicht>> verbunden?>> habe darauf schon geantowrtet :)> sind das nicht 0x04?>> gesucht: PC02 also das 3. bit>> also 0/1 2 4 <- oder?
Schreibs halt einfach als
PORTC = ( 1 << PC2 );
so wie man das eben (in erster Näherung) vernünftig schreibt. Dann
erübrigt sich die ganze Diskussion.
Aber die while-Schleife (also keyboard) hat nichts mit dem Display zu
tun! Display liegt auf Port D, Keypad auf B und C. Also ist die
wahrscheinlichste Erklärung, dass du irgendwo einen Kurzschluss
reingelötet hast.
Wäre vielleicht auch ne Idee mal die PORT- und DIR-Register richtig zu
benutzen. Wenn man nämlich nicht den ganzen Port benutzt, dann sollte
man mit & und | Operationen arbeiten. Habe ich weiter oben glaube ich
schon mal erwähnt.
DDRB = DDRB & 0xF0;
// PORTB = 0x0F;
DDRC = DDRC & 0x3C | 0x20;
PORTC = 0x20;
DDRC = DDRC & 0x3C | 0x10;
PORTC = 0x10;
...
Das hilft aber nur dann, wenn die nicht benutzten Pins von Port B/C in
den Kurzschluss involviert sind und hilft auch nur bei der Diagnose -
entfernen muss man den Fehler in der HW dann trotzdem.
Sorry ... 0x3C ist natürlich genau falschrum, 0xC3 wäre richtig.
DDRC & 0xC3 löscht nur die bits, die hinter den Pins PC2-PC5 stecken.
Dann wird genau der eine Pin auf Ausgang geschaltet, der Momentan
interessant ist ( | 0x20 ).
aber wieso funktioniert es dann "fast" sobald ich das while raushaue?
ich meine die funktion aht er ja trotzdem aufgerufen.
nur halt eben nur 1 mal 0 wurde ausgegeben und wurde auch so angezeigt,
die blöcke bekomme ich nur wenn ich die while schleife in die main
funktion packe :/
Mit dem while erzeugst Du ein Rechteck-Signal auf den 4 Ausgängen, ohne
while nur mal eben einen Puls pro Ausgang und dann ist Schluss.
Der eine Puls reicht nicht um den Inhalt des Displays zu überschreiben -
das Rechteck schon.
Setz doch mal DDRC auf 0 und lass die while-Schleife. Dann wird keyboard
zwar nie zurückkommen, aber das würde bestätigen, dass zwischen Port C
und D ein Kurzschluss ist. Vermutlich von einem der 4 Ausgänge zu E vom
Display, da hier der Takt zum schreiben ins Display RAM führen könnte.
okay DDRC habe ich jetzt überal auf 0x00 gesetzt wobei PORTC bleibt es
werden die internen pullups aktiviert aber das sollte ja irelevant
sein:)
Ergebnis:
Blöcke oben und unten.
code:
So da bin ich wieder.
Habe alles auf eine neue Platine gelötet.
Und dieses mal 10 mal ordentlicher.
Ergebniss bleibt das Gleiche:
Hier mal ein Bild wie es ausieht wenn die while schleife nicht drinn ist
aber die Zahl vordefiniert ist.
Hier Dezimal 189
erst immer wenn ich das while reinpacke kommen oben und unten Blöcke.
Wenn irgendwer noch einen Einfall hat, bitte hilft mir Ihr bekommt alle
nötigen Infos.
MfG Jan
Hmm. Wenn du einen debugger hast, würd ich damit mal gucken. Ansonsten 4
LEDs mal dranhängen und hinter
ergebnis+= key*100;
ergebnis+= key*10;
ergebnis+= key;
und
Zahl = ergebnis;
jeweils eine LED anmachen. Dann kannst du gucken, ob dein Programm
überhaupt zur Ausgabe kommt.
Was mir auch noch aufgefallen ist, ist das du unten ein if-else hast, wo
du prüfst, ob die zahl zu groß ist. Im Else ist unten ein Return und
beim If nicht. Beides ist bei µC meist nicht sinnvoll. Mir fällt
jedenfalls keine Anwendung ein, wo der µC das Programm abarbeitet und
der Program Counter dann in einen evtl nicht programmierten/definierten
Programmspeicherbereich geht.
Also nach "lcd_init();" ein "while(1){", nach dem else dann die "}" und
das return aus dem else raus.
Wenn du das geändert hast zeig nochmal deinen Code, aber bitte häng den
als Datei an, sonst wird dieser Thread hier elendlang ;)
wo jetzt?
das return 0 ist am ende der main(), habe es aber weggemacht, war in der
Zeit zu viel mit konsolenanwendungen beschäftigt :)
und wo genau meinst du soll ich die while schleife einfügen?
MfG und danke :)
PS: so ahbe es geändetr aber weiterhin sehe ich nur Blöcke.
Habe den neuen code mal hochgeladen :)
kann es evtl. auch am uc liegen?