Hallöchen! Also ich hoffe ihr wertet es nicht als unverschämt von mir euch hier so ein langes Programm hin zu knallen aber ich weiß mir sonst nicht zu helfen... Ich wäre euch sehr dankbar wenn mir hier jemand helfen kann... Ich habe mit "Bascom" folgendes Programm geschrieben und bin am verzweifeln!! Das ganze soll eine Pokeruhr werden, die mit 7-segment Anzeigen in der Lage ist 2 Zeiten (15:00 und 5:00 Minuten) runter zu zählen. Kurze Übersicht des Programmablaufs: Timer für Taktung eingestellt Interrupts eingeschaltet Portbelegung deklariert Hauptprogramm multiplext die 7-segment anzeigen soweit noch ok ;-) PROBLEM1: Tastenentprellung --> Wird Interrupt0 (Taste_0_interrupt) ausgelöst gibts Probleme... Eigentlich soll der "P A U S" ausgeben, stattdessen leuchtet bei einer Anzeige ne "0" auf und dann läuft die Uhr einfach weiter... Könnte das vielleicht an der fehlenden "entprellung" liegen? Wenn ja... Ich habs schonmal mit dem "debounce" Befehl probiert.. Bin da aber kläglichst gescheitert... Kann mir jemand erklären wie das mit dem entprellen funktioniert? bidde bidde ^^ weiter im Programm... timer1 zählt im sekundentakt die Zeit runter soweit ok... Wenn die Zeit abgelaufen ist, soll der an Porta.7 angeschlossene Piezzo durch ein einfaches Tonmuster signalisieren, dass die Zeit abgelaufen ist... Tut er aber nich, der Sack! ;-) Warum nicht? Ich hab die "Töne" mal in nem kleinen Testprogramm getestet... Da gings.. allerdings hatte ich den "Soundbefehl" im Hauptprogramm stehen... Könnte es daran liegen? $regfile = "m8535.dat" 'Atmega8535L $crystal = 8000000 'Quarz: 8,0 MHz '******** Deklarationen ******** Const Timer1vorgabe = 49911 Dim Sekunde_einer As Byte Dim Sekunde_zehner As Byte Dim Minute_einer As Byte Dim Minute_zehner As Byte Dim Zahl(10) As Byte Config Timer1 = Timer , Prescale = 64 On Timer1 Timer1_interrupt Timer1 = Timer1vorgabe Enable Timer1 On Int0 Taste_0_interrupt Config Int0 = Falling Enable Int0 On Int1 Taste_1_interrupt Config Int1 = Falling Disable Int1 Enable Interrupts '******** Initialisierung ******** Ddra = &B11111111 Ddrc = &B11111111 Ddrb = &B11111111 Ddrd = &B00000000 Portd.2 = 1 Portd.3 = 1 Zahl(1) = &B01110111 '0 Zahl(2) = &B01000010 '1 Zahl(3) = &B00111011 '2 Zahl(4) = &B01101011 '3 Zahl(5) = &B01001110 '4 Zahl(6) = &B01101101 '5 Zahl(7) = &B01111101 '6 Zahl(8) = &B01000011 '7 Zahl(9) = &B01111111 '8 Zahl(10) = &B01101111 '9 If Portd.3 = 0 Then Sekunde_einer = 1 Sekunde_zehner = 1 Minute_einer = 6 Minute_zehner = 2 Else Sekunde_einer = 1 Sekunde_zehner = 1 Minute_einer = 6 Minute_zehner = 1 End If '******** Hauptprogramm ******** Do Porta = &B00000100 Portc = Zahl(sekunde_einer) Waitus 500 Porta = &B00001000 Portc = Zahl(sekunde_zehner) Waitus 500 Porta = &B00000010 Portc = Zahl(minute_zehner) Waitus 500 Porta = &B00000001 Portc = Zahl(minute_einer) Waitus 500 Loop '******** Unterprogramme ******** Taste_0_interrupt: 'Pause interrupt Disable Int0 Waitms 100 Do While Portd.2 = 0 Porta = &B00000100 Portc = &B01101101 Waitus 400 Porta = &B00001000 Portc = &B01110110 Waitus 400 Porta = &B00000001 Portc = &B01011111 Waitus 400 Porta = &B00000010 Portc = &B00011111 Waitus 400 Loop Wend Return Taste_1_interrupt: Return '*****Timer****** Timer1_interrupt: Timer1 = Timer1vorgabe Decr Sekunde_einer If Sekunde_einer = 0 Then Decr Sekunde_zehner Sekunde_einer = 10 If Sekunde_zehner = 0 Then Decr Minute_einer Sekunde_zehner = 6 If Minute_einer = 0 Then Decr Minute_zehner Minute_einer = 10 End If End If End If While Minute_zehner = 0 Sekunde_einer = 10 Sekunde_zehner = 6 Minute_einer = 10 Decr Sekunde_einer If Sekunde_einer = 0 Then Decr Sekunde_zehner Sekunde_einer = 10 If Sekunde_zehner = 0 Then Decr Minute_einer Sekunde_zehner = 6 End If End If While Minute_zehner = 0 Sekunde_zehner = 6 Sekunde_einer = 10 Decr Sekunde_einer If Sekunde_einer = 0 Then Decr Sekunde_zehner Sekunde_einer = 10 End If While Sekunde_zehner = 0 Sekunde_einer = 10 Decr Sekunde_einer If Sekunde_einer = 0 Then Disable Timer1 Sound Porta.7 , 600 , 50 Waitms 100 Sound Porta.7 , 100 , 50 Waitms 70 Sound Porta.7 , 100 , 50 Waitms 100 Sound Porta.7 , 600 , 50 Waitms 100 End If Wend Wend Wend Return End Und am Ende nochmal ein gaaanz, gaaanz herzliches Dankeschön für eure hilfe!! Gruß Umgucker
Zu deinem Programm selbst kann ich nichts sagen. Bascom kann ich nicht. Aber zu deinen Erklärungen davor: Taster => Interrupts. 7Seg-Ausgabe => main. Das ist genau falsch herum: Mache das vom Konzept her so: Variablen anlegen: [pseudocode]
1 | //-- für Displayausgabe --------------------
|
2 | uint8_t au8Zahl[10] = {&B01110111,&B01000010,&B00111011,&B01101011, |
3 | &B01001110,&B01101101,&B01111101,&B01000011, |
4 | &B01111111,&B01101111 }; |
5 | uint8_t au8Display[4]; // Displayinhalt |
6 | uint8_t au8SegActive[4] = {&B00000100,&B00001000, |
7 | &B00000010,&B00000001 }; |
8 | uint8_t u8ActRow; // aktuelle Ausgabe |
9 | //-- Tastenentprellung ---------------------
|
10 | uint8_t u8Debounce; // Zähler für Entprellung |
11 | uint8_t u8TasteGedr = 0; // 1=gedrückt |
In dem Timer-interrupt gibst du jetzt der Reihe nach diese vier Elemente (10h, 1h, 10min, 1min) aus. Anschließend setzt du eine Variable auf Null, wenn die Taste nicht gedrückt ist. Ist sie gedrückt, wird die variable erhöht. Ist ein Schwellwert überschritten, so gilt die taste als gedrückt. Die Auswertung erfolgt grundsätzlich NICHT im Interrupt!
1 | ISR(timerint) |
2 | {
|
3 | //-- Displayausgabe -------------------
|
4 | u8ActRow = ( (u8ActRow+1) AND 0x03 ); // 0..3 |
5 | PORTA = au8SegActive[u8ActRow]; |
6 | PORTC = au8Display [u8ActRow]; |
7 | //-- Tasterentprellung ----------------
|
8 | if ( Pin_wo_Taste_dran = GEDRÜCKT ) |
9 | {
|
10 | u8Debounce = u8Debounce + 1; |
11 | }
|
12 | else
|
13 | {
|
14 | u8Debounce = 0; |
15 | }
|
16 | //-- Taster gedrückt erkannt? ---------
|
17 | if ( u8Debounce >= 20 ) |
18 | {
|
19 | u8Debounce = u8Debounce - 10; |
20 | u8TasteGedr = 1; |
21 | }
|
22 | }
|
Somit hast du die Tastenentprellung UND die Anzeige von deinem eigentlichen Problem entkoppelt. In der Hauptschleife kannst du jetzt drauf einwirken;
1 | main() |
2 | {
|
3 | init_timer; |
4 | while(1) |
5 | {
|
6 | if ( u8TasteGedr = 1 ) |
7 | {
|
8 | u8TasteGedr = 0; |
9 | .. mach was mit Tastendruck und lösche ihn .. |
10 | }
|
11 | //-- Anzeige auf Display
|
12 | au8Display [ Stelle 0..3 ] = au8Zahl[ anzuzeigende Ziffer 0..9 ]; |
13 | |
14 | }
|
15 | }
|
Wie das in Bascom syntaktisch zu tippen ist, keine Ahnung.
Das ist viel zuviel, was da alles im Timer1-Interrupt erledigt werden soll. Besser ist das, den Timer dort nur als Erstes mit 49911 neu zu laden, dort nur einen Merker zu setzen und sofort und schnell wieder aus dem Interrupt zu verschwinden. Den Merker kannst Du dann im Hauptprogramm als Sekundentakt auswerten und ihn wieder rücksetzen, damit er im nächsten Timer1-Interrupt wieder gesetzt werden kann. Mit dem Debounce ist das doch eine feine Sache: Erstmal mußt Du ganz oben ein Unterprogramm definieren, zu dem bei Deinem Tastendruck hingehüpft wird: Declare Sub Zeit_starten In die Hauptschleife kommt dann die Abfrage des "Startpins": Debounce Pinc.0 , 0 , Zeit_starten , Sub Ganz unten in den Quelltext kommt dann sie Subroutine: Sub Zeit_starten DEIN TEXT, was bei Tastendruck passieren soll.. End Sub Dadurch eiert das Programm immer in der Hauptschleife herum, wenn dann die Taste an z.B. PinC.0 gedrückt wird, hüpft er in die Subroutine und macht dort das, was darin steht und´kommt wieder ind die Hauptschleife zurück. MfG Paul
Das klingt vernünftig... Aber das Hauptprogramm ist doch eigentlich mit dem Multiplexen beschäftigt... Wenn ich da jetzt noch die ganze "Timer Geschichte" reinpacke, wird das denn da nicht auch zu viel? Also von wegen Flimmergefahr und so.. Außerdem müsste ich noch wissen wie man einen Merker setzt und ausliest...;-) Aber schonmal vielen Dank euch Beiden!! Gruß Umgucker
Umgucker wrote: > Aber das Hauptprogramm ist doch eigentlich mit dem Multiplexen > beschäftigt... Nö, das ist völlig falsch. Das Multiplexen gehört in den Timerinterrupt, alles andere ist großer Quatsch mit Soße. Peter
Ich möchte meinen letzten Beitrag korrigieren.. Also, wie empfohlen habe ich jetzt das Multiplexen in den Timer1 interrupt gebastelt.. Ist es jetzt aber nicht so, dass der nach anlegen der Versorgungsspannung beim ersten Timer1 interrupt sofort ins Interrupt Unterprogramm wechselt und da bleibt.. Also da fehlt mir noch ein Befehl zum Rücksprung ins Hauptprogramm... Timer1_interrupt: Timer1 = Timer1vorgabe Do Porta = &B00000100 Portc = Zahl(sekunde_einer) Waitus 500 Porta = &B00001000 Portc = Zahl(sekunde_zehner) Waitus 500 Porta = &B00000010 Portc = Zahl(minute_zehner) Waitus 500 Porta = &B00000001 Portc = Zahl(minute_einer) Waitus 500 Loop Return End
> Also, wie empfohlen habe ich jetzt das Multiplexen in den Timer1 > interrupt gebastelt.. Die DO LOOP Schleife in dem Interrupthandler ist ein ausgewachsener Bug. Da kommt das Programm nicht mehr raus bzw. kommt kein neuer Timerinterrupt mehr! Diese Art alle vier Stellen in einem Aufruf des Timerinterrupts auszugeben, ist IMHO ungewöhnlich. Insbesondere die vier Wartezeiten (WAITUS 500) lesen sich nicht gut. Ich würde pro Aufruf des Timerinterrupts nur eine Stelle ausgeben und mir dann für den nächsten Timerinterrupt merken, dass dann die nächste Stelle dran ist (d.h. Multiplexen). Es ist wahrscheinlich, dass dabei eine andere Frequenz des Timerinterrupts benutzt werden muss, um eine gefällige, flackerfreie Anzeige hinzubekommen. Für mehr Analyse reicht der Codeschnippsel nicht aus.
okay... Wird wohl doch noch ein weiter Weg... ;-) Aber nochmal vielen Dank für eure Hilfe! Gruß Umgucker
>Timer1_interrupt: >Timer1 = Timer1vorgabe > Do > Porta = &B00000100 > Portc = Zahl(sekunde_einer) > Waitus 500 > Porta = &B00001000 > Portc = Zahl(sekunde_zehner) > Waitus 500 > Porta = &B00000010 > Portc = Zahl(minute_zehner) > Waitus 500 > Porta = &B00000001 > Portc = Zahl(minute_einer) > Waitus 500 > Loop > Return >End Wie wäre es wenn du mal meine Antwort in Ruhe durchliest?? Könnte man verrückt werden. Da macht man sich die Mühe und Arbeit, das ausführlich zu erklären, und dann wird das einfach ignoriert! Was wollst du denn eigentlich? Eine fertige Datei, die du nur Öffnen brauchst? Die wirst du hier nicht bekommen, höchstens in Markt.
@Lippy Also: zunächst einmal habe ich hier keinerlei Hilfestellung ignoriert! Ich bin echt dankbar für eure Hilfe und nehme diese auch gerne und Dankend an! Aber: Die Programierung von Mikrokontrollern ist nicht so einfach wie eine Wegbeschreibung von hier bis zur Sparkasse und es gehört doch eine Menge Verständnis und Grundlagenwissen dazu um ein funktionierendes Programm auf die Beine zu stellen! Mit "wird wohl doch noch ein weiter Weg" meinte ich, das ich mich da nochmal hinterklemmen muss. Was nicht bedeutet, das deine Hilfe schlecht war... Seh ich auch keinen direkten zusammenhang... Sorry! Gruß Umgucker
Umgucker wrote: > Timer1_interrupt: > > Timer1 = Timer1vorgabe > > Do > Porta = &B00000100 > Portc = Zahl(sekunde_einer) > Waitus 500 > > Porta = &B00001000 > Portc = Zahl(sekunde_zehner) > Waitus 500 > > Porta = &B00000010 > Portc = Zahl(minute_zehner) > Waitus 500 > > Porta = &B00000001 > Portc = Zahl(minute_einer) > Waitus 500 > > Loop Ne so wird das nix. Du mußt den Timerinterrupt nehmen anstelle des Waitus. Nun hast Du hier aber mehrere Warte-Stellen. Dann brauchst Du einen Zähler, damit jedesmal die nächste Stelle gewartet wird. Timer1_interrupt: Timer1 = Timer1vorgabe zaehler = zaehler + 1 if zaehler = 1 Porta = &B00000100 Portc = Zahl(sekunde_einer) endif if zaehler = 2 Porta = &B00001000 Portc = Zahl(sekunde_zehner) endif if zaehler = 3 Porta = &B00000010 Portc = Zahl(minute_zehner) endif if zaehler = 4 Porta = &B00000001 Portc = Zahl(minute_einer) zaehler = 0 endif Return Damit hast Du 2 Vorteile: 1. Die Wartezeit wird nicht nutzlos verwartet, sondern gehört voll dem Main 2. Du hast immer exakt gleich lange Intervalle (kein Flackern). Peter
>Prima! Damit komm ich weiter! Vielen Dank!
Das hatte ich dir weiter oben schon beschrieben. Nur eben nicht in
Bascom, sondern als pseudocode.
Naja, um Deinen Pseudocode zu verstehen, muss man schon etwas C können. Dies ist bei BASCOM-Anfängern selten der Fall. Aus der Tastenentprellung halte ich mich raus, ich nutze den PeDa-Bulletproof-Algorithmus in verschiedenen Varianten in ASM. Anzeige-Multiplex und Tastenentprellung lege ich auch öfters mal zusammen in einen gemeinsamen Timer-Int, da ich auch mal die Segment-Leitungen für die Taster mitnutze. KH
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.