Ich versuche nun schon seit 2 Tagen einen einfachen Taster als Schalter zu benutzen. Ich habe einen ATmega8 und benutze Bascom. LEDs blinken usw. habe ich alles schon hinbekommen nur halt das mit dem Taster nicht. Kann mir mal bitte jemand den Code sagen? Ich weiss das ich entprellen muss, blos verstehe ich das nicht so ganz in Bascom. Wenn ich den Taster an Pind.2 drücke soll die LED an portd.7 angehen, wenn ich nochmal den Taster drücke soll sie wieder ausgehen. Damke schonmal.
Ich habe es nun alleine hinbekommen! Hänge aber beim nächsten problem. Möchte nun mit 2 Tastern 2 Verschiedene "Programme" Starten und stopen können. Hier mal mein Code: $regfile = M8def.dat $crystal = 3638400 Ddrd = &B11100000 Portd = &B00001100 Declare Sub An Declare Sub Aus Declare Sub Prg1 Declare Sub Prg2 Dim T1 As Bit Dim T2 As Bit Do Debounce Pind.2 , 0 , An , Sub Debounce Pind.3 , 0 , Aus , Sub Loop End If T1 = 1 Then Gosub Prg1 End If If T2 = 1 Then Gosub Prg2 End If An: Toggle T1 Aus: Toggle T2 Prg1: Portd.5 = 1 Waitms 100 Portd.5 = 0 Portd.6 = 1 Waitms 100 Portd.6 = 0 Portd.7 = 1 Waitms 100 Portd.7 = 0 Return Prg2: Portd.5 = 1 Waitms 400 Portd.5 = 0 Portd.6 = 1 Waitms 400 Portd.6 = 0 Portd.7 = 1 Waitms 400 Portd.7 = 0 Return
wo liegt denn das problem? Also ich meine wenn du einfach deine Bits abfragst und dann das jeweilige programm aufrufst. Geht das nicht?
Ne das funktioniert so nicht. Egal welchen Taster ich drücke, es läuft immer nur Programm1 ab. Es wiederholt sich auch nicht, sondern läuft nur 1x ! :(
Dein Problem dürfte sein, daß, sobald ein Programm läuft, ja nicht mehr die Loop mit den Debounces ausgeführt wird. Du mußt also sehr lange drücken. Als Lösung wüßte ich daher nur, das Entprellen und gedrückt erkennen in einem Timerinterrupt quasi im Hintergrund ausführen zu lassen. In der Codesammlung ist dazu ein Beispiel in C oder Assembler für bis zu 8 Tasten, d.h. der Code ist der gleiche, egal ob eine Taste oder 8. Ich kenn mich mit Basic nicht aus, aber geht Dein Programm nicht von "An:" über "Aus:" direkt rein in "Prg1:" ? Und ist nicht das "If T1 = 1 Then" nach dem "Do...Loop" unerreichbarer Code ? Peter
Hallo Peter, ich bin leider noch so ziemlich am Anfang was Uc angeht, deswegen verstehe ich nicht so ganz was du da geschreiben hast. Gibts hier jemand der auch mit Bascom codet und mir sagen kann wo der Fehler liegt? mfg roman
Hi, der Code ist nicht richtig aufgebaut nach deinen Anforderungen. Peter hat schon recht mit den tasten in einen Timer abzufragen. Aber fuer Anfaenger sollte das Polling der Tasten einfacher sein. An: Toggle T1 -- hier fehlt ein return die Hauptschleife sollte dann so aufgebaut sein: Do Debounce Pind.2 , 0 , An , Sub Debounce Pind.3 , 0 , Aus , Sub If T1 = 1 Then Gosub Prg1 End If If T2 = 1 Then gosub Prg2 End If Loop End prg1: ....... return prg2: ...... return Gruß, Dirk
Hi Roman, programmiere schon lange in Bascom. "Debounce" ist schon lange her, hatte aber nie Erfolg damit, daher weg damit. Ich mache es immer wie folgt: 1) Wichtig ist die Deklaration z.b: Const Pressed = 0 ' kommt später Config Portd = Input ' Port D ist Eingang Btn_up Alias Pind.0 ' Portd.0 gibt Mist ;-) WICHTIG !!!!! 2) Abfragen, ob Taste gedrückt If Btn_up = Pressed Then 3) ein bischen warten zum Entprellen Waitms 200 ' Vielleicht geht auch weniger als 200, vielleicht auch ein Debounce! 4) Aktion auslösen z.b. led togglen Toggle LED end if So geht es, viel Glück! lg Ralf
Und so vertrödelt der MC wieder seine Rechenzeit in Zeitschleifen, anstatt sich in dieser Zeit anderen Aufgaben zu widmen... Ist es denn so schlimm, in einem Timer-Interrupt alle 4...20ms den Port einzulesen, den Wert mit dem vorhergehenden zu vergleichen und Änderungen zu übernehmen (nachdem sie 2mal oder besser 4mal hintereinander stabil aufgetreten sind)? Es ist schon schlimm genug, dass immer wieder mit Warteschleifen programmiert wird, aber noch schlimmer ist, dass das Programmieren von (ellenlangen) Warteschleifen immer wieder als "gutes Beispiel" angepriesen wird. ...
@Hannes, viele Wege führen nach Rom! Sorry, aber meine Interruptroutinen haben was Besseres zu tun, als Taster abzufragen, kannst natürlich gerne so machen. Denke mal, dass in ner Schleife für Anfänger so einfacher geht. Warum sich noch Ärger mit nem Interrupt einhandeln? "Debounce" wird auch warten, bis der Portpin sich nicht mehr ändert. Hätte auch besser gefunden, wenn ein konkretes Beispiel beigefügt hättest, damit Roman damit was anfangen kann. Und wenn du meinst, daß der MC seine Zeit vertrödelt, wenn er auf Eingaben wartet, dann ist mir das rätselhaft. Es gibt z.b. Messaufgaben, die erst dann gestartet werden sollen, wenn eine Taste gedrückt wurde. Sehe auch wenig Sinn, wenn in einer komplexen Schleife trotzdem alle 4ms die Interruptroutine nach Tasteneingaben abfragt. Wie gesagt: kannst natürlich gerne so machen, Hauptsache es funzt. Ich hatte dieses Forum mal so Verstanden, dass man sich bei konkreten Problemen Anregungen einholen kann, über die man natürlich auch diskutieren kann. Leider driften oft die Themen ab oder es wird Haarspalterei betrieben. Schau dir mal einige Threads an, dann weisst was ich meine. Schönes Wochenende lg Ralf :-)
@Ralf: > Sorry, aber meine Interruptroutinen haben was Besseres zu tun, als > Taster abzufragen, kannst natürlich gerne so machen. Das wird nicht in einem eigens für die Taster reserviertem Interrupt gemacht, sondern in einem Timer-Interrupt der weitere Aufgaben der Programmsteuerung hat (Blinken, Verzögerungen, LCD-Synchronisierung usw...) und in fast jedem Programm sowiso benötigt wird. Die Abfrage und Entprellung von bis zu 8 Tastern benötigt ganze 12 Takte in der ISR und stellt dem Hauptprogramm (oder welchem Task auch immer) für jede Taster ein (entprelltes) Zustandsbit zur Verfügung und zusätzlich ein Flag (je Taster), das anzeigt, dass ein Taster erneut betätigt wurde und dieser Tastendruck noch nicht abgearbeitet wurde. Und das alles ohne Warteschleifen, bequemer geht es nicht... > Denke mal, dass in ner Schleife für Anfänger so einfacher geht. Ja, wenn man dem "Anfänger" auch dazusagt, dass man es so nicht machen sollte. Denn wer sich einmal an das Verheizen von Prozessortakten gewöhnt hat, kommt nur schwer wieder von diesem Programmierstil weg. Es gibt genügend Beispiele hier im Forum, wo ein (übertakteter) Mega128 mit BASCOM seine (wenige) Arbeit nicht schafft. > Hätte auch besser gefunden, wenn ein konkretes Beispiel beigefügt > hättest, damit Roman damit was anfangen kann. Auf dieses Beispiel hat Peter Dannegger (der Urheber dieser Routine) bereits verwiesen (Codesammlung). Wenn es aber sein muss, dann gibt es das Beispiel eben hier nochmal. Es ist allerdings in Assembler. Die folgenden Codezeilen sind Bestandteil der Timer-ISR, die noch andere Aufgaben hat. TIM1_COMPA: ;ISR Timer1-Interrupt (alle 10ms) in srsk,sreg ;SREG sichern (Exklusivregister) push xh ;benutzte Register push xl ;sichern in xl,ocr1al ;Weckzeit in xh,ocr1ah ;holen, subi xl,low(-tim1zu) ;Intervall sbci xh,high(-tim1zu) ;dazu, out ocr1ah,xh ;und wieder out ocr1al,xl ;in den Timer ;xl und xh können jetzt innerhalb dieser ISR frei benutzt werden Tastenabfrage: ;Entprellroutine geklaut bei Peter Dannegger... in xl,tap ;Tastenport einlesen (gedrückt=L) com xl ;invertieren (gedrückt=H) eor xl,tas ;nur Änderungen werden H and tz0,xl ;Prellzähler unveränderter Tasten löschen (Bit0) and tz1,xl ;Prellzähler unveränderter Tasten löschen (Bit1) com tz0 ;L-Bit zählen 0,2,->1, 1,3,->0 eor tz1,tz0 ;H-Bit zählen 0,2,->tz1 toggeln and xl,tz0 ;Änderungen nur dann erhalten, wenn im Prellzähler and xl,tz1 ;beide Bits gesetzt sind (Zählerstand 3) eor tas,xl ;erhaltene Änderungen toggeln alten (gültigen) Tastenstatus and xl,tas ;nur (neu) gedrückte Tastenbits bleiben erhalten or tfl,xl ;und zugehörige Bits setzen (gelöscht wird nach Abarbeitung) ;in "tas" steht jetzt der gültige Tastenzustand, ;in "tfl" die Flags der neu gedrückten, noch nicht abgearbeiteten Tasten... ;xl ist jetzt wieder frei für weitere temporäre Zwecke in der ISR ;... ;Weitere Aufgaben der ISR... ;... tim1_ovf_ende: pop xl ;benutzte Register pop xh ;wiederherstellen out sreg,srsk ;SREG wiederherstellen reti ;fertig... > Sehe auch wenig Sinn, wenn in einer komplexen Schleife trotzdem > alle 4ms die Interruptroutine nach Tasteneingaben abfragt. Ich schon, wobei ich mich nicht an den 4ms festhalte. Ich nutze den Abstand, der für die restliche Interruptarbeit günstig ist. Wird z.B. (für Messungen) eine "Uhr" mit Hundertstel Sekunden benötigt, dann ist der Abstand 10ms. Brauche ich den Timer-Int für eine mehrkanalige Software-PWM, dann wird der Zeitabstand halt soweit wie möglich reduziert, so dass zwischen den ISRs noch genügend Zeit für die Funktionen des Hauptprogramms bleibt, aber eben nicht mehr als nötig. Es gibt eben (unter anderem) 2 Arten von Programmierstil. Der eine wartet in einer Warteschleife, wenn eine Aktion nicht sofort (sondern etwas später) ausgeführt werden soll. Der andere springt sofort zur Mainloop zurück und schaut nach, ob es nicht noch andere Arbeit gibt, die man zwischendurch erledigen kann. Was soll daran falsch sein? > Ich hatte dieses Forum mal so Verstanden, dass man sich bei > konkreten > Problemen Anregungen einholen kann, über die man natürlich auch > diskutieren kann. > Leider driften oft die Themen ab oder es wird Haarspalterei > betrieben. > Schau dir mal einige Threads an, dann weisst was ich meine. Da hast du das Forum richtig verstanden. Ich sehe meinen Beitrag auch nicht als Flamwar oder Haarspalterei, sonern als einen Hinweis, dass man vorteilhafter programmieren kann. Vielleicht auch darauf, dass nicht auf den Beitrag mit der Lösung reagiert wurde. ...
@ Togger Wenn ichs mit waitms 200 mache blinkt die LED ja so lange bis ich die taste loslasse, weil ja jede 200ms neu getoggelt wird. @ Dirk Ich hab nun die 2 vergessenen Returns hinzugefügt mit dem Ergebnis das es schon fast funktioniert. Blos muss ich beim Ausschalten den Taster immer so lange gedrückt halten, bis das ganze Programm einmal durchgelaufen ist.
"Blos muss ich beim Ausschalten den Taster immer so lange gedrückt halten, bis das ganze Programm einmal durchgelaufen ist." Genau das hatte ich doch schon gesagt. Interrupts sind gar nicht so schlimm. Und wenn man sie erstmal kapiert hat, erleichtern sie das Programmieren ungemein. Peter
Wäre denn mal jemand so lieb, meinen Code zu vervollständigen/Verbessern? Dann habe ich wenigstens mal ein Konkretes beispiel was ich auch verstehe. Danke schonmal.
do if pind.0=1 and portb.0=0 then portb.0=1 'LED an end if waitms 100 if pind.0=1 and portb.0=1 then portb.0=0 'LED aus end if loop
Hallo, hab einen Atmega32-Grundschaltung aufgebaut und an folgenden Ports je eine LED angeschlossen: PD5 PD6 PD7 Zwei Taster habe ich an PD und PD3 angeschloßen. Nun wollte ich folgenden Code mal ausprobieren, aber es funktioniert nicht richtig:
1 | $regfile = "m32def.dat" |
2 | $framesize = 32 |
3 | $swstack = 32 |
4 | $hwstack = 32 |
5 | $crystal = 1000000 |
6 | |
7 | Ddrd = &B11100000 |
8 | Portd = &B00001100 |
9 | |
10 | Declare Sub An |
11 | Declare Sub Aus |
12 | Declare Sub Prg1 |
13 | Declare Sub Prg2 |
14 | |
15 | Dim T1 As Bit |
16 | Dim T2 As Bit |
17 | |
18 | |
19 | Do |
20 | |
21 | Debounce Pind.2 , 0 , An , Sub |
22 | Debounce Pind.3 , 0 , Aus , Sub |
23 | |
24 | |
25 | Loop |
26 | End |
27 | |
28 | If T1 = 1 Then |
29 | Gosub Prg1 |
30 | |
31 | End If |
32 | |
33 | If T2 = 1 Then |
34 | Gosub Prg2 |
35 | |
36 | End If |
37 | |
38 | An: |
39 | Toggle T1 |
40 | |
41 | Aus: |
42 | Toggle T2 |
43 | |
44 | |
45 | Prg1: |
46 | |
47 | Portd.5 = 1 |
48 | Waitms 100 |
49 | Portd.5 = 0 |
50 | Portd.6 = 1 |
51 | Waitms 100 |
52 | Portd.6 = 0 |
53 | Portd.7 = 1 |
54 | Waitms 100 |
55 | Portd.7 = 0 |
56 | |
57 | Return |
58 | |
59 | Prg2: |
60 | Portd.5 = 1 |
61 | Waitms 400 |
62 | Portd.5 = 0 |
63 | Portd.6 = 1 |
64 | Waitms 400 |
65 | Portd.6 = 0 |
66 | Portd.7 = 1 |
67 | Waitms 400 |
68 | Portd.7 = 0 |
69 | |
70 | Return |
Es leuchten alle drei LEDs auf und wenn ich den Taster an PD2 betätige, dann läuft Prg1 einmal durch und die LEDs leuchten wieder. Daselbe spiel mit dem Taster PD3, da läuft auch Prg:1 einmal durch... Also eigentlich kein Unterschied bei den Tastern. Woran könnte das liegen? Oder besser gesagt, was mach ich falsch?
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.