hallo zusammen. ich bin gerade dabei meinen µc(at90s8535) so zu programmieren, dass er über diverse tasten befehle ausführt. eine taste hat zudem noch die aufgabe, in ein menue zu springen (kanalwahl). hier möchte ich dann mein display so haben, dass ich noch 2 taster habe, mit denen ich den kanal nach oben oder nach unten drücke und eine taste, um ok zu drücken und den kanal zu wählen. wie kann ich das display so ansteuern, dass dieses sofort auf meinen tastendrück reagiert und die neue situation angezeigt wird?? zudem schreibt mein display die ausgaben in die zeilen 1-3-2-4. wie muss ich dann das display ansprechen, um die richtige reihenfolge zu bekommen?? anbei noch der quellcode, der noch nicht wirklich ausgereift ist: void Kanalwahl(void) { char not_exit; not_exit = 1; //Kanal noch nicht eingestellt lcd_clrscr(); lcd_puts("Befehl2: Kanalwahl "); //pfeile und so anzeigen in zweiter Zeile while(!(&PIND,PD2)) //warten, bis alle Taster wieder losgelassen while (not_exit) //warten auf tastatureingabe und auswertung { if(debounce(&PIND,PD2)) //irgendein Taster wurde gedrueckt { switch(!(PORTA)&0x3F) //maskieren und invertieren Ports { case 1: //Down Taste gedrueckt if(debounce(&PINA,PA1)) { if(aktueller_kanal == 0) //kanaele von 0 bis 2 einstellbar aktueller_kanal = 2; else aktueller_kanal--; //kanal runterzaehlen } //display aktualisieren break; case 2: // Up Taste gedrückt if(debounce(&PINA,PA2)) { if (aktueller_kanal >= 2) //kanaele von 0 bis 2 einstellbar aktueller_kanal = 0; else aktueller_kanal; } //display aktualisieren break; case 4: //Ok gedrueckt if(debounce(&PINA,PA3)) { not_exit = 0; } break; default: //falsche taste, oder mehrere auf einmal gedrueckt lcd_clrscr(); lcd_puts("Bitte nur eine Taste drücken"); } } } }
Mit lcd_gotoxy(Spalte,Zeile) kannst du den Cursor auf eine beliebige Stelle des Displays setzen und dann ausgeben, was da stehen soll. Die Reihenfolge kann man eventuell in der lcd.h geradebiegen oder du definierst dir: #define ZEILE1 1 #define ZEILE2 3 #define ZEILE3 2 #define ZEILE4 4 und schreibst dann immer lcd_gotoxy(Spalte,ZEILE1) usw.
Woher kommen die Routinen für das LC-Display? Selber geschrieben? Von irgendwo übernommen? Hast du die (Anfangs)Adressen der Zeilen richtig definiert? Ein bisschen mehr Info, bzw Code wäre sicherlich hilfreich...
VODOO!! da war doch gerade noch ein Folgebeitrag vom OP? Und jetzt ist der weg... darauf hätte sich eigentlich mein Beitrag bezogen... Heinzelmännchen am Werk? ;-)
sorry, der lcd code is von peter fleury, der ja hinglänglich im forum bekannt ist. die einzelnen zeilen habe ich jetzt auch angesprochen wie uwe mir noch mal nahe gelegt hat. jetzt geht es mir eigentlich nur noch om das ständige aktuallisieren des displays? was wäre da am besten? etwa nen timer der das ganze immer wieder neu abfragt? was wäre das die beste lösung? habt ihr da ansätze?
Wie war das mit dem Überschreiben der 2ten Zeile? Ist das nun weg? Zum Aktualisieren gibt es 2 (3) Möglichkeiten... - du aktualisierst die Anzeige halt dann wenn sich auch wirklich was ändert - wenn das zu oft hintereinander passiert dann nimmst du dir einen Timer und aktualisierst das Dingens alle (weissichnicht)ms oder einen Mischbetrieb - falls einmal Müll drinstehen sollte wird das mit der regelmässigen Aktualisierung bereinigt und auf bestimmte Änderungen reagierst du eben unmittelbar
> jetzt geht es mir eigentlich nur noch om das > ständige aktuallisieren des displays? Ich mach das bei Menüs immer beim Rücksprung aus den Menüroutine. Alle Menüroutinen springen zu einer Routine, die den Menütext und ggf die Parameter anzeigt. Da ich kein C kann, kann ich Dir leider kein Beispiel in C liefern. Falls Dir ein ASM-Beispiel helfen könnte, dann schau mal hier: Beitrag "Re: Datensatzname für Z-Pointer per Variable übergeben?" ...
@hannes bei mir is das genau anders herum. wäre natürlich ne feine sache, wenn das in c wäre da, ich gerade in den anfängen des programmierens bin und außer c und java noch mit keiner weiteren programmiersprache gearbeitet habe. @ vorbeigeschlendert das überschreiben hat sich erledigt, heinzelmännchen hat den fehler erkannt und gebannt. das schwebt mirt auch im kopf herum, dass ich das lcd dann aktuallisiere, wenn sich wirklich was ändert, aber ich raff noch nicht ganz, wie ich das anstellen soll. muss ich dazu meine tasten mit einbeziehen? stehe gearade auf dem schlauch!
Ich raff dein Problem noch nicht. Deine Funktion da oben sieht doch nicht schlecht aus. An die Stellen die mit // Display aktualisieren markiert sind, machst du einen lcd_gotoxy und schreibst die korrekte Zahl hin. Die Fehlermeldung da weiter unten (Bitte nur eine Taste drücken) würde ich komplett weglassen, bringt nur das Display durcheinander.
1 | int main(void){ |
2 | // mach irgendetwas
|
3 | |
4 | if (update_lcd || (timer_update_lcd > UPDATEINTERVALL)){ |
5 | // hier dir Routinen zur Displayaktualisierung
|
6 | update_lcd(); |
7 | }
|
8 | |
9 | // mach irgendetwas anderes
|
10 | }
|
so oder so ähnlich... du änderst update_lcd wenn sich bestimmte Werte ändern oder dein Update-Intervall ansteht - du einen Ticker mitlaufen mit dem du verschieden Geschichten triggerst zB die Tastenabfrage, denn du nimmst dann ja sicher die von Peter (Beitrag "Tasten entprellen - Bulletproof") - besser, schöner, sicherer
@ karl heinz ich würde gerne mein display so anpassen, dass es bei den casefällen immer den aktuellen wert bzw. stand angibt. d.h. wenn ich einnen taster drücke, dass das lcd mir sofort den neuen wert anzeigt. also in meinem fall zwischen kanal 0 bis 2 herumspirngt.
Ja und? Wo liegt das Problem? Schreib die Zahl aufs LCD und dann steht sie dort. Ich seh dein Problem nicht. Oder hast du das Problem, dass du nicht weist wie man eine Zahl ausgibt? char[5] buffer; while( ... ) if( .... ) ... itoa( aktueller_kanal, buffer, 10 ); lcd_gotoxy( Spalte_in_der_die_Zahl_hinsoll, Zeile_in_die_die_Zahl_hinsoll ); lcd_puts( buffer );
Da deine Kanalzahlen nur einstellig sind, ist itoa eigentlich auch Overkill. In diesem Fall könntest du, zb while( ... ) if( .... ) ... lcd_gotoxy( Spalte_in_der_die_Zahl_hinsoll, Zeile_in_die_die_Zahl_hinsoll ); lcd_putc( aktueller_kanal + '0' ); Ich hab jetzt nicht mehr im Kopf ob die Funktion wirklich lcd_putc heist. Gemeint ist die Funktion, die ein einzelnes Zeichen ausgibt.
mein prob ist. das x in lcd_puts("Kanal x gewaehlt") aktuell zu halten, sprich meine aktuelle zahl da rein zu schreiben. case 1: //Down Taste gedrueckt if(debounce(&PINA,PA1)) { if(aktueller_kanal == 0) //kanaele nur von 0 bis 2 einstellbar aktueller_kanal = 2; else aktueller_kanal--; //kanal runterzaehlen } lcd_gotoxy(0,2); lcd_puts("Kanal x gewaehlt"); //display aktualisieren break;
Dann sollest du dir schleunigst eine C-Buch besorgen! (Kein Scherz. Das ist Lektion 3 oder 4 in einem 200 Seiten Buch) In deinem Fall, solange aktueller_Kanal nur die Werte 0 bis 2 annehmen kann, würde gehen: char buffer[20]; /* lang genug für den kompletten Text */ ..... strcpy( buffer, "Kanal x gewaehlt" ); buffer[6] = aktueller_kanal + '0'; lcd_gotoxy( ... ) lcd_puts( buffer ); eine einfachere Variante wäre: char buffer[] = "Kanal x gewaehlt"; ..... /* ersetzte das 'x' im buffer-Text durch die richtige Ziffer */ buffer[6] = aktueller_kanal + '0'; lcd_gotoxy( ... ) lcd_puts( buffer );
Da würde doch auch gehen: lcd_gotoxy(Position der Kanalnummer); lcd_put(aktueller_kanal+ '0'); sofern es möglich ist, einzelne Buchstaben auszugeben.
Aber eigentlich: Wenn ich mirs recht überlege, ist das auch noch Overkill: Schreib die Zahl wie ein Posting weiter vorne schon mal gezeigt einfach auf das LCD. Du musst dir nur die Zeile und die Spalte raussuchen, sodass die Zahl das 'x' aus dem Text ""Kanal x gewaehlt" überschreibt. Also: Der Text "Kanal x augewählt" steht schon lange dort. Den hast du zb ganz am Anfang der Funktion hingeschrieben. Vielleicht so, dass der Text in Spalte 1, Zeile 3 beginnt. Dann musst du die tatsächlie Zahl an Spalte 7, Zeile 3 hinschreiben, und die eine Stelle überschreibt damit genau das x dass vorher dort gestanden ist.
nun habe ich mir das nach ein paar tage noch mal alles in ruhe durchgelesen. und ich habe es immer noch nicht geschluckt. vllt. ist das für euch zu einfach, aber ich habe noch nie zuvor nen lcd angesteuert gehabt. also noch mal mein prob: wenn ich eine taste drücke, dann soll es mir den tastedruck zählen und dann auf dem display erscheinen. wenn ich das prog. laufen lasse, dann läuft das prog. bis zum kanalwahl fehlerfrei, dort angekommen, zeigt er mir die gegebenen sachen auf dem display an. wenn ich dann eine taste drücke, bekomme ich die buchstaben c oder w statt zahlen auf dem display angezeigt, was es normalerweise nicht sollte. hier noch mal der code: case 0x02: //Down Taste gedrueckt if(debounce(&PINA,PA1)) { char aktueller_kanal=~PINA&0x02; if(aktueller_kanal == 0) //kanaele nur von 0 bis 2 einstellbar aktueller_kanal = 2; else aktueller_kanal--; //kanal runterzaehlen } lcd_gotoxy(17,1); lcd_putc("aktueller_kanal-'1'"); //display aktualisieren break; case 0x04: // Up Taste gedrückt if(debounce(&PINA,PA2)) { char aktueller_kanal=~PINA&0x04; if (aktueller_kanal >= 2) //kanaele nur von 0 bis 2 einstellbar aktueller_kanal = 0; else aktueller_kanal++; } lcd_gotoxy(17,1); lcd_putc("aktueller_kanal+'0'"); //Displaisplay aktualisieren break; case 0x08: //Ok gedrueckt if(debounce(&PINA,PA3)) { not_exit = 0; } break; kann es vllt. daran liegen, dass ich den aktuellen_kanal am anfang auf eins setzte und dann eben hier im code, den aktuellen_kanal via char meinem taster zuordne??
In deinem Code sind mehrere Probleme. Zunächst mal: case 0x02: //Down Taste gedrueckt if(debounce(&PINA,PA1)) { char aktueller_kanal=~PINA&0x02; ... } break; case 0x04: // Up Taste gedrückt if(debounce(&PINA,PA2)) { char aktueller_kanal=~PINA&0x04; ... Die Variable aktueller_kanal vom Fall 0x02 ist nicht dieselbe Variable wie aktueller_kanal im Fall 0x04. Das sind zwei unterschiedliche Variablen die nur 'zufällig' gleich heissen. In C hat jede Variable eine Lebensdauer. Wenn ich mal globale Variablen ausser acht lassen kann, dann beginnt die Lebensdauer beim { des Blocks in dem sie definiert ist und sie endet beim } das heist die Variable aktueller_kanal existiert nur in dem Block, der beim if (debounce( &PINA,PA2) ) { beginnt und der beim } lcd_gotoxy(17,1); lcd_putc("aktueller_kanal-'1'"); //display aktualisieren endet. Insbesondere hat dieser Block natürlich nichts mit dem ähnlichen Block zu tun, der im case 0x04 steht. Die Variable aktueller_kanal dort ist eine andere Variable. Wenn du also haben willst, dass beide Blöcke mit derselben Variable aktueller_kanal arbeiten, dann musst du die Variable dort herausziehen und quasi eine Ebene drüber definieren: void Kanalwahl(void) { char not_exit; char aktueller_kanal; not_exit = 1; //Kanal noch nicht eingestellt ... case 0x02: if(debounce(&PINA,PA1)) { aktueller_kanal=~PINA&0x02; if(aktueller_kanal == 0) //kanaele nur von 0 bis 2 selbiges natürlich auch im Fall 0x04. Jetzt gibt es nur noch eine Variable namens aktueller_kanal und beide Blöcke, der in 0x02 und der in 0x04 arbeiten auf dieser Variablen. lcd_putc("aktueller_kanal-'1'"); //display aktualisieren Hier hast du einfach drauflos geraten. Das Problem war, dass dir ursprünglich eine Variable aktueller_kanal benutzt hast und der Compiler die nicht kannte. Klar: So wars ursprünglich: if(debounce(&PINA,PA1)) (*) { char aktueller_kanal=~PINA&0x02; if(aktueller_kanal == 0) //kanaele nur von 0 bis 2 einstellbar aktueller_kanal = 2; else aktueller_kanal--; //kanal runterzaehlen (*) } lcd_gotoxy(17,1); lcd_putc("aktueller_kanal-'1'"); //display aktualisieren break; Die Lebensdauer der Variablen aktueller_kanal beginnt bei der mit einem (*) markierten Zeile, dort beginnt der Block und endet bei der zweiten mit einem (*) markierten Zeile, dort endet der Block. Ausserhalb diese Blocks gibt es schlicht und ergreifend keine Variable mit diesem Namen. Daher konntest du auch nicht einfach schreiben lcd_putc( aktueller_kanal ); Denn in dem Block, in dem der lcd_putc steht, existiert keine Variable aktueller_kanal. Die ist einen Block tiefer verschachtelt. lcd_putc möchte als Argument ein einzelnes Zeichen haben. Du hast aber einen String. Ein String ist eine Zeichenfolge, die, wenn man sie direkt im Source Code schreibt, in " " eingeschlossen wird. Ein String kann in einem char-Array gespeichert werden. Ein einzelnes Zeichen hingegegen wird mit ' ' eingeschlossen und wird in einem char gespeichert. Was willst du? Du möchtest den Inhalt von aktueller_kanal ausgeben. Also müsste das heissen: lcd_putc( aktueller_kanal ); Soweit, so gut. Nur geht das so nicht. In aktueller Kanal steht entweder 0 oder 1 drinnen. lcd_putc hat aber noch eine Restriktion: Es will ASCII Zeichen haben! Um am Display eine 0 erscheinen zu lassen, musst du den Code für '0' ausgeben und der lautet nun mal nicht 0. Das kann man aber leicht beheben: Du brauchst nur zu aktueller_kanal den Code für '0' dazuzählen und kriegst damit für die Zahlen 0 bis 9 automatisch den richtigen ASCII Code. lcd_putc( aktueller_kanal + '0' );
also als erstes mal vielen dank an Karl heinz Buchegger, der beitrag ist sehr gut erklärt. mir ist einiges klar geworden und ich habe auch wieder was gelernt. habe die oben angegebenen sachen abgearbeitet und siehe da, des funktioniert. Ich bin begeistert! so macht programmieren lernen spaß. was allerdings noch nicht ganz richtig ist, ist: > Soweit, so gut. Nur geht das so nicht. In aktueller Kanal > steht entweder 0 oder 1 drinnen. habe da auch schon mit lcd_putc(aktueller_kanal+'1') etc. herumgespielt. eingentlich soll das prog. immer zwischen 0 und 2 herumspringen. also 012012 und anders herum. wenn dazu noch ne antwort käme, dann wäre ich restlos begeistert!
da habe ich glatt noch mal ne frage: wäre es nicht geschickter, ne for schleife zu machen? also: for(aktueller_kanal=0;aktueller_kanal<=2;aktueller_kanal--)... oder nimmt ich das mit dem aktuellen code nichts?
Was bringt dir eine for-Schleife. Du möchtest ja nicht, dass der Rechner von sich aus ständig die Kanalnummer durchzählt. Obwohl das hätte auch seinen Reiz und man würde eine Taste einsparen: Der Rechner lässt ständig 0, 1, 2, 0, 1, 2, ... durchlaufen und wenn die Zahl erscheint die du haben möchtest, drückst du als Benutzer auf eine Taste. Wenn man das schnell genug durchlaufen liese, hätte das dann was von Glückspiel an sich. War natürlich nicht ernst gemeint. > eingentlich soll das prog. immer zwischen 0 und 2 herumspringen. > also 012012 und anders herum Dann musst du das auch so programmieren. Spiel mal Computer und geh mal im Geiste deinen Code durch: > if (aktueller_kanal >= 2) //kanaele von 0 bis 2 einstellbar > aktueller_kanal = 0; > else > aktueller_kanal; Wir nahmen mal an aktueller Kanal habe den Wert 0 und ich als Benutzer drücke jetzt die Taste, so dass obiges ausgeführt wird. Du bist der Computer und machst genau das (und nur das) was da steht. Also: > if (aktueller_kanal >= 2) //kanaele von 0 bis 2 einstellbar Aha. Gefragt ist also der Wert von aktueller_kanal. Den haben wir schon mal festgelegt, der sei 0. Als nächstes frägst du dich ob dieser Wert, also die 0, größer oder gleich 2 ist. Nun 0 ist nicht größer oder gleich 2, also gehts beim else weiter: > else > aktueller_kanal; Aha. Da wird aktueller_kanal hergenommen und ... nichts weiter. Mit aktueller_kanal passiert nichts mehr und damit ist das fertig. Anschliessend machst du jetzt nur noch die Ausgabe und das wars dann auch. Wenn ich also die Taste 'Up' drücke, ändert sich aktueller_kanal gar nicht, wenn es 0 ist :-( Offensichtlich muss das heissen: else aktueller_kanal++; Also noch mal ein paar Schritte zurück: aktueller_kanal ist getestet worden, 0 ist nicht >= 2, wir sind beim else und es passiert: else aktueller_kanal++; aktueller_kanal wird also um 1 erhöht. Aus der bisher gespeicherten 0 wird also eine 1. Dann kommt der ganze Rest mit Anzeigen und so und das Pgm wartet auf den nächsten Tastendruck. Ich, als Benutzer drücke wieder 'Up' und es wird wieder der gleiche Programmteil betreten: > if (aktueller_kanal >= 2) //kanaele von 0 bis 2 einstellbar aktueller_kanal enthält jetzt den Wert 1, den nehmen wir mal und testen die Bedingung: 1 >= 2 Nun 1 ist sicher nicht größer oder gleich 2, also wird wieder der else genommen: else aktueller_kanal++; aktueller_kanal wird also wieder um 1 erhöht. Aus der bisherigen 1 wird eine 2. Nach Anzeigen wartet das Pgm wieder und als fieser Benutzer drücke ich wieder 'Up'. Mal schauen was jetzt passiert: > if (aktueller_kanal >= 2) //kanaele von 0 bis 2 einstellbar Gefragt ist also der Wert von aktueller_kanal. Das wissen wir noch, der war jetzt 2. Die Frage ist also: Ist 2 >= 2? Ja das ist der Fall: 2 ist gleich 2 und daher auch 'größer oder gleich'. In diesem Fall wird also nicht der else Zweig vom if genommen, sondern: > aktueller_kanal = 0; aktueller_kanal wird also auf 0 gesetzt. Das kennen wir aber schon. Da haben wir angefangen. In Summe bleibt also: Bei jeweils einem Druck auf 'Up' hat aktueller_kanal nacheinander die Werte 0, 1, und 2 angenommen. Danach gings wieder mit 0 weiter, etc. Den ganzen Vorgang den ich jetzt so ausführlich geschildert habe, nennt man 'Debuggen'. Ein Bug (engl. Käfer) ist ein logischer Fehler in einem Program und De-buggen ist daher das entfernen dieses Fehlers. Du wirst noch viel Zeit im Laufe deiner Programmierkarriere mit debuggen verbringen.
sorry, meinen anfangstcode hatte ich schon überarbeitet und daher nicht gesehen, dass bei else aktueller_kanal das ++ gefehlt hat. und natürlich bin ich mir bewusst, dass ich viel zeit mit dem debuggen verbringen werde und gerade auch mache. was du mir sehr ausführlich und anschaulich gezeigt hast, hatte ich eben schon behoben. aber gerade, wenn man in den anfängen des chip-programmierens ist, hat man eben so seine schwierigkeiten, wofür dieses forum bestens geeignet ist, um diese zu beheben! ( so genügend honig um den mund geschmiert, back to business): für mich als "pc" ist mein code auch logisch, und desswegen frage ich mich, warum auf dem lcd nur eben zwischen 0 und 1 gesprungen wird und nicht bis zwei. (bei meiner up taste). bei der down tate springt er eben nur von 1 nach 2 und das in der schleife! hier der aktuelle code für die : case 0x04: // Up Taste gedrückt if(debounce(&PINA,PA2)) { aktueller_kanal=~PINA&0x04; if (aktueller_kanal >= 2) //kanaele nur von 0 bis 2 einstellbar aktueller_kanal = 0; else aktueller_kanal++; } lcd_gotoxy(17,1); lcd_putc(aktueller_kanal+'0'); //Displaisplay aktualisieren break; ich habe auch mit der if(aktueller_kanal>=2) herumgespielt, aber mein display sieht das nicht ein!
> if(debounce(&PINA,PA2)) > { > aktueller_kanal=~PINA&0x04; Was ist die Idee dahinter, der Variablen aktueller_kanal den Zustand der Taste zuzuweisen? :-)
naja, ich möchte, dass er bei tastendruck zählt! shame on me. alles klar. das war nen denkfehler! danke dir!
> naja, ich möchte, dass er bei tastendruck zählt!
Schon. Aber der Tastendruck ist ja nicht der Zähler
selbst. Der Tastendruck verändert den Zähler.
Wenn eine Variable nicht so funktioniert wie du das
willst, musst du dir jede einzelne Verwendung der
Variable, egal in welchem Zusammenhang ansehen und
überlegen ob das so stimmt, bzw. ob das so überhaupt
Sinn macht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.