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.