Hallo an alle!! Ich bin gerade bei der Implementierung der Eingabe bei benem Belichtungsgerättimer. Ich hab 3 Taster zu Verfügung: Start, Cursor, Set. Mit Start strate ich und schalte das Relay ein. Mit Set erhöhe ich den Timerwert an der aktuellen Cursorposition. Mit Cursor schalte ich zur nächsten Cursorposition. Doch so weit bin ich noch gar nicht mit dem Implementieren gg Als Anhang hab ich meinen aktuellen Softwarestand. Das Problem ist so. Ich hab eine Interruptroutine. Alle 1s wird der time Wert decrmentiert wenn diese Timerfunktion aktiviert ist. Alle 5ms frage ich derzeit mit meiner TAsterabfrage einen Taster ab. Wenn der Taster gedrückt ist, soll die Zeit wieder auf 10min (= 600s) zurückgestellt werden. Doch wenn ich wenn ich auf den Taster drücke, und gedrückt bleibe, zählt er kurz nach unten und und zeigt dann 10.00 an, die er dann im 1s takt wieder dekremntiert. Wenn ich den Taster los lasse, dann zeigt er mir am Display auf einmal 8,34 an die dann bis 8,33 dekremntiert werden. Danach fängt er wieder bei 10 Minuten an zu dekrementieren. Wenn ich in der Phase an der 8,34 - 8,33 den Taster drücke und gedrückt halte, fängt er bei ca 12,50 an sehr sehr schnell zu dekremntiern bis 10 min. Ab dann dekrementiert er wieder im 1sec Takt. Wenn ich den ATster wieder los lasse, bin ich wieder bei 8,34 und so gehts weiter. Ich hab echt keinen Plan mehr was da los ist :( Ich hoffe es kann mir wer helfen Gruß Robert
Wenn ich mir dein Programm mal oberflächlich anschaue, fällt mir auf: volatile uint8_t taster_pressed[3] = {NO_TASTER}; Das Array ist mit einer Größe von 3 definiert. if(taster_is_set(PINB, PB4, 4) == 1) Beachte den letzten Parameter im Aufruf: eine 4 int taster_is_set(uint8_t port, uint8_t pin, uint8_t tasterflag) Was passiert mit tasterflag in dieser Funktion: if(taster_pressed[tasterflag] Oha: tasterflag == 4, aber das Array taster_pressed hat nur 3 Einträge. Du fragst Dinge ab, die gar nicht zu taster_pressed gehören. Selbiges hier: debounce[tasterflag]--; Das Array debounce ist so definiert: volatile uint8_t debounce[3] = {DEBOUNCEWERT}; Also auch wieder nur 3 Elemente. Nur Gott alleine und gcc wissen, welche Variablen du dir bei einer Zuweisung an debounce[4] zerschiest.
Hallo Karl Danke für den Hinweiß. Das funktioniert jetz so halbwegs. NUr mit der Tasterabfragerotine klappt es leider noch nicht wie es soll. :( Die Taster sind auf GND geschalten und die interen Pullups des ATTiny 26 sind aktiv. Mit
1 | if(taster_is_set(PINB, PB4, 2) == 5) |
2 | time += 10; |
frage ich den Taster ab. Die Abfrageroutine habe ich jetzt noch ein wenig geändert.
1 | int taster_is_set(uint8_t port, uint8_t pin, uint8_t tasterflag) |
2 | {
|
3 | if(taster_pressed[tasterflag] == TASTER_PRESSED && bit_is_set(port, |
4 | pin)) |
5 | {
|
6 | taster_pressed[tasterflag] = NO_TASTER; |
7 | return 1; |
8 | }
|
9 | |
10 | if(bit_is_clear(tasterstatus, tasterflag) && bit_is_clear(port, pin) |
11 | && taster_pressed[tasterflag] == NO_TASTER && debounce[tasterflag] != |
12 | 0) |
13 | {
|
14 | tasterstatus |= (1 << tasterflag); |
15 | debounce[tasterflag]--; |
16 | return 2; |
17 | }
|
18 | |
19 | if(bit_is_set(tasterstatus, tasterflag) && bit_is_clear(port, pin) && |
20 | taster_pressed[tasterflag] == NO_TASTER && debounce[tasterflag] != 0) |
21 | {
|
22 | debounce[tasterflag]--; |
23 | return 3; |
24 | }
|
25 | |
26 | if(bit_is_set(tasterstatus, tasterflag) && bit_is_set(port, pin) && |
27 | taster_pressed[tasterflag] == NO_TASTER && debounce[tasterflag] != 0) |
28 | {
|
29 | tasterstatus &= ~(1 << tasterflag); |
30 | debounce[tasterflag] = DEBOUNCEWERT; |
31 | return 4; |
32 | }
|
33 | |
34 | if(debounce[tasterflag] == 0 && taster_pressed[tasterflag] == |
35 | NO_TASTER && bit_is_set(port,pin)) |
36 | {
|
37 | taster_pressed[tasterflag] = TASTER_PRESSED; |
38 | return 5; |
39 | }
|
40 | return 0; |
41 | }
|
In einer ISR (Alle 5ms ein Interrupt) führe frage ich das ganze ab. Doch leider wenn ich das kompiliere und flashe, zählt er autmatisch immer die 10 dazu (Ohne Tastendruck). wenn ich auf den TAster drücke, bleibt der Counter stehen. Doch nur warum ist denn das so?? HAb jetzt schon seit 2 Stunden an der Funktion herumgespielt, finde aber nicht die Lösung. Ich hoffe es kann mir wer helfen Danke im Voraus Gruß Robert
Für mich sieht das nur höllisch kompliziert aus. Ich würde das Ganze einfach mit ner Statemaschine machen. Ein Beispiel dafür findest Du hier, wobei noch zwischen kurz und lang Drücken unterschieden wird: http://www.mikrocontroller.net/forum/read-4-405548.html#new Die Haupt-States sind für 2 Tasten + kurz/lang immer in 5-er Abständen, bei 3 Tasten müßten sie dann um 7 auseinander liegen. Da unter AVR-GCC Statemachines eh 16-Bittig sind, könnte man auch 256 Haupt-States + 6 Tastenevents (0..6) nehmen, wenns umfangreicher wird. Peter
> Für mich sieht das nur höllisch kompliziert aus. Sehe ich auch so. > Ich hoffe es kann mir wer helfen Warum spielst du das ganze nicht mal im Debugger durch?
Hallo an alle Ja das ist wirklich ein bisschen kompliziert ;) ICh hab nun einmal deine Tastenroutine genommen Peter. Doch leider funktioniert noch nicht alles ganz zuverlässig. Am Auslesen des EEproms happerts noch einbisschen. Und was mir noch aufgefallen ist, wenn ich KEY0 gedrückt halte, dann zählt er viel langsamer die Variable time herunter als wenn ich KEY1 gedrückt halte und er nach oben zählt. Warum ist denn das so?? Ich hoffe es kann mir helfen Gruß Robert
Ich würd noch mehr aus dem Interrupt rausnehmen. Du hast allein schon 12 Divisionen drin und nur 1ms Zeit (Divisionen sind das teuerste). Du machst viel zu viel, viel zu oft. Sachen, die nicht oft gemacht werden müssen, lieber im Main. Wenn Du mal mein Programm ansiehst, ich setze nur ein 1-Sekunden-Flag und zähle dann im Main die Zeit. Es könnte sogar sein, daß dann im Main Sachen noch öfter gemacht werden, aber dort hast du alle Zeit der Welt dazu, d.h. es wird nichts behindert. Peter
Hallo Peter Ich hab mal eine Frage zu Ansi C:
1 | if( --sec_timer == 0 ){ |
2 | one_second = 1; |
3 | sec_timer = INTTIME; |
4 | if( --corrector == 0 ){ // correction n / 256 |
5 | sec_timer = (XTAL - 255UL * 8 * INTTIME + 4) / 8; |
6 | }
|
7 | }
|
BEim dekremntien im if Statement, wird da geprüft ob sec_timer - 1 == 0 oder dekremntiert er und prüft dann. Beim nächsten mal dekremntiert er wieder um eins und prüft dann?? Was würdest du aus der ISR rausschmeissen?? Gruß Robert
So hab nun die ganzen time2display() Funktionen in die main verlagert. Eigentlich läuft alles jetzt sehr zuverlässig. Einen Schönheitsfehler hat das Programm aber noch. Das Inkrementieren bei gedrückter Taste geht viel schneller als das Dekrementieren. Woran kann das liegen??? Gruß Robert
j = ++i; // j ist identisch zu i + 1 j = i++; // j ist identisch zu i In beiden Fällen ist aber nach der kompletten Anweisung: i = i + 1 Wann diese Änderung an i allerdings tatsächlich durchgeführt wird, ist undefiniert. Sie muss erst bei 'Abarbeitung des ;' durchgeführt worden sein. (In C-speak: ; markiert einen Sequenz-Punkt, engl. sequence point. Und erst wenn dieser erreicht wird, muss dieser Nebeneffekt des Erhöhens abgeschlossen sein.) ++i : erhöhe i, das Ergebnis mit dem weitergerechnet wird ist i + 1 i++ : erhöhe i, das Ergebnis mit dem weitergerechnet wird ist i. Sinngemäs gilt gleiches für --
Danke. Jetzt funktionioniert fast alles. Ein Problem hab ich noch. Das inkrementieren geht viel schneller als das dekrementieren. Warum ist das so??? Gruß Robert
Das kann ich dir nicht sagen. So beim drüberlesen ist mir eigentlich nichts aufgefallen. Da wirst du wohl oder übel selbst mit einem Debugger reinschauen müssen was da passiert.
Meinst du den Debugger von AvrStudio??? Das funktioniert bei mir leider nicht. Das versteh ich nicht. Projekt kann ich ein neues erstellen, aber beim kompilieren hängt er sich auf. Er hängt sich auch auf, wenn ich ein erstellt Projekt öffne. Was ist den da los?? (Hab WinXP Prof + SP1). Wie funktioniert eigenlich der Debugger?? Gibts da ein Tutorial? Gruß Robert
> Das funktioniert bei mir leider nicht. Das ist schlecht. Das solltest du unbedingt in den Griff kriegen. Du verzichtest sonst auf ein mächtiges Werkzeug. > Was ist den da los?? Hast auch sicher die letzten Versionen + Avr-Studio Service Packs installiert? > Wie funktioniert eigenlich der Debugger?? Dein Programm läuft unter der Kontrolle des Debuggers. Du kannst das Programm Schritt für Schritt durchgehen lassen oder du kannst Breakpoints setzen (der Programmablauf wird dann angehalten, wenn diese Anweisung abgearbeitet wird), du kannst Variablen anschauen, neue Werte zuweisen, du kannst den Speicher direkt überwachen, die kannst Port-Stati life anschauen (und auch ändern), siehst wie der Timer hochzählt usw. Die Bedienung ist eigentlich ziemlich einfach: Ist alles in einem Menü zusammengefasst, bzw. die I/O Ansicht ist als Tree organisiert. Wie gesagt: Du verzichtest auf ein mächtiges Werkzeug. Auf einem PC war das Fehlen eines Debuggers zu verschmerzen, da konnte man sich mit printf() behelfen, aber auf einem µC geht das meist nicht.
So ich hab es jetzt hin bekommen. Ich hab mir noch das SP3 heruntergeladen und installiert :) Ein bisschen verstehe ich das schon mit dem Debugger. Wie die I/O Register und die Timer Register gesetzt werden sehe ich schon. Jedoch das hilft mir ja nichts. Die Werte der von mir angelegten Variablen she ich jar nicht. Wie kann ich das sinnvoll beobachten was da passiert?? Gruß Robert
Mittels F10 oder F11 gehst du immer einen Schritt weiter. F10: Ist der Schritt ein Funktionsaufruf so wird die Funktion ausgeführt, und der Debugger meldet sich wieder wenn die Funktion returned F11: Ist der Schritt ein Funktionsaufruf, denn erfolgt der Schritt in die Funktion hinein und du kannst auch durch die Funktion reinschreiten F9: Setzt einen Breakpoint in die Zeile, in die der Cursor ist. Wenn du das Programm für sich laufen lässt, so meldet sich der Debugger wieder, wenn diese Zeile erreicht wird. Das ist besonders bei ISR interessant: Sobald aus irgendeinem Grund die ISR aufgerufen wird, wird der Breakpoint ausgelöst. Auch dann wenn du eigentlich an einer ganz anderen Stelle mittels F10 oder F11 durchstepst. Um den Inhalt einer Variablen zu sehen, fahr einfach mit der Maus auf den Variablennamen (egal wo). Im Tooltip wird dir dann der Wert der Variablen angezeigt. Bei Strukturen oder wenn du eine Variable öfter anschauen willst, ist es oft besser so zu verfahren: Maus auf den Variablenname. Rechte Maustaste. Im Kontextmenue den Punkt 'Add Watch' auswählen. Im AVR-Studio sollte unten ein Fenster sein, dass den Titel 'Watch' trägt. Dort taucht jetzt die Variable mitsamt ihrem Wert auf. Steppst du weiter durch den Code, so wird dieses Fenster mit den sich verändernden Werten der Variable upgedated. Soweit das Wichtigste in Kürze.
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.