Hallo Zusammen,
dies ist mein erster Post hier im Forum, in dem ich mich mit meinem ersten Projekt, bei dem ich Hilfe benötige, vorstellen möchte.
Hab mich vor 3-4 Jahren schon mit Microcontrollern beschäftigt. Das Ganze war dann aber ein wenig eingeschlafen...
Jetzt möchte ich aber vorankommen
Hab vor einiger Zeit ein paar Numitron Anzeigeröhren (IV-9) aus sowjetischer Produktion abstauben können, mit der Absicht daraus eine Uhr zu bauen.
Das sind interessante Glühfadenröhren dei mit 5V Versorgungsspannung auskommen. Sehr retro
Hab mich dann mal an einen Schaltplan gemacht, und eine Platine dazu geätzt und aufgebaut.
Vom Konzept her werden 6 Röhren über Micrel Treiber (mit Latch) versorgt, die vom Atmega8 angesteuert werden. Für die Zeit sorgt ein I2C Baustein (pcf8583).
Die output enables der Treiber werden über HW PWM geschaltet, so dass man die gesamte Helligkeit darüber regeln kann. DerAtmega läuft auf 8Mhz mit internem Oscillator.
Es funktioniert soweit alles gut. Ich kann die Zeit anzeigen lassen, Helligkeit regeln und die Dezimalpunkte im Sekundentakt blinken lassen.
Ich würde allerdings ganz gerne noch ein paar Spielereien einbauen wie verschiedene Animationstypen (überblenden, ein-/ausdimmen der Zahlen, rein rausschieben), wechselnde Datumsanzeige etc.
Dazu brauche ich ein Auswahlmenü. Und das ist auch die Stelle an der ich nicht so recht weiterkomme. Ich hab es versucht mit subs mit eigenen Do Loop Schleifen, aber die Returns scheinen nicht immer zu funktionieren. Und irgendwie scheint mir das alles nicht sehr elegant was ich da bisher versucht habe.
Wie programmiere ich am optimalsten so ein Auswahlmenü????
Vielen Dank für eure Hilfe!
Hier mal der komplette bisherige Code:
dies ist mein erster Post hier im Forum, in dem ich mich mit meinem ersten Projekt, bei dem ich Hilfe benötige, vorstellen möchte.
Hab mich vor 3-4 Jahren schon mit Microcontrollern beschäftigt. Das Ganze war dann aber ein wenig eingeschlafen...
Jetzt möchte ich aber vorankommen
Hab vor einiger Zeit ein paar Numitron Anzeigeröhren (IV-9) aus sowjetischer Produktion abstauben können, mit der Absicht daraus eine Uhr zu bauen.
Das sind interessante Glühfadenröhren dei mit 5V Versorgungsspannung auskommen. Sehr retro
Hab mich dann mal an einen Schaltplan gemacht, und eine Platine dazu geätzt und aufgebaut.
Vom Konzept her werden 6 Röhren über Micrel Treiber (mit Latch) versorgt, die vom Atmega8 angesteuert werden. Für die Zeit sorgt ein I2C Baustein (pcf8583).
Die output enables der Treiber werden über HW PWM geschaltet, so dass man die gesamte Helligkeit darüber regeln kann. DerAtmega läuft auf 8Mhz mit internem Oscillator.
Es funktioniert soweit alles gut. Ich kann die Zeit anzeigen lassen, Helligkeit regeln und die Dezimalpunkte im Sekundentakt blinken lassen.
Ich würde allerdings ganz gerne noch ein paar Spielereien einbauen wie verschiedene Animationstypen (überblenden, ein-/ausdimmen der Zahlen, rein rausschieben), wechselnde Datumsanzeige etc.
Dazu brauche ich ein Auswahlmenü. Und das ist auch die Stelle an der ich nicht so recht weiterkomme. Ich hab es versucht mit subs mit eigenen Do Loop Schleifen, aber die Returns scheinen nicht immer zu funktionieren. Und irgendwie scheint mir das alles nicht sehr elegant was ich da bisher versucht habe.
Wie programmiere ich am optimalsten so ein Auswahlmenü????
Vielen Dank für eure Hilfe!
Hier mal der komplette bisherige Code:
Code:
' --a-- a: Portd.2
' f ! ! b b: Portd.1
' ! ! c: Portd.0
' --g-- d: Portc.1
' e ! ! c e: Portc.5
' ! ! f: Portc.4
' --d-- * g: Portc.3
' DP: Portc.2
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 100
$swstack = 100
$framesize = 100
Config Portb.1 = Output 'OE
Config Portd.5 = Output 'STROBE1
Config Portd.6 = Output 'STROBE2
Config Portd.7 = Output 'STROBE3
Config Portb.0 = Output 'STROBE4
Config Portb.2 = Output 'STROBE5
Config Portb.3 = Output 'STROBE6
Config Portd.2 = Output 'IN1
Config Portd.1 = Output 'IN2
Config Portd.0 = Output 'IN3
Config Portc.1 = Output 'IN4
Config Portc.5 = Output 'IN5
Config Portc.4 = Output 'IN6
Config Portc.3 = Output 'IN7
Config Portc.2 = Output 'IN8
'einzelziffern Strobe als Alias zum besseren Handling, Z1 ist rechts / OE = Output Enable
Z1 Alias Portd.5
Z2 Alias Portd.6
Z3 Alias Portd.7
Z4 Alias Portb.0
Z5 Alias Portb.2
Z6 Alias Portb.3
Oe Alias Portb.1
'Eingaenge setzen
Taster1 Alias Pind.3
Config Pind.3 = Input
Portd.3 = 1
Taster2 Alias Pind.4
Config Pind.4 = Input
Portd.4 = 1
'Variablendeklaration
Dim Segbyte As Byte 'für die Anzeigebytes (segmentdaten)
Dim I As Byte 'for next zählervariable
Dim X As Byte 'temp variable
Dim Stelle As Byte 'Variable für Interruptroutine (welche Stelle soll gelactcht werden)
Dim Helligkeit As Byte 'pwm variable
Dim Hundertstel As Byte
Dim Sekunden As Byte
Dim Minuten As Byte
Dim Stunden As Byte
Dim Tag As Byte
Dim Monat As Byte
Dim Jahr As Byte
Dim Z1er As Byte 'einzelne Anzeigeelemente
Dim Z2er As Byte
Dim Z3er As Byte
Dim Z4er As Byte
Dim Z5er As Byte
Dim Z6er As Byte
Dim Ziffern(6) As Byte At Z1er Overlay 'array auf obige
Dim Blinker(6) As Byte 'welche stelle soll geblikt werden
Dim Blinker_puls As Byte 'laufvariable für blinkerimpuls
Dim Menu As Byte 'menuepunktzaehler
Dim Menu_sub As Byte 'untermenue zaehler
Dim Blink_dp_flag As Bit 'sollen dezimalpunkte im sek takt blinken?
Dim Animation_type As Byte
Dim Key_time As Byte 'zählt wie lange die taste gedrückt ist
Dim Taster1_msg As Byte 'taster zustand (1 = kurz, 2= lang, 3=repeat)
Const Key_lang = 100 'langclick ca 1 s
Const Key_kurz = 5 ' normal click alles ab 50 ms
'Const Key_repeat = 150 'wiederholen ab 1,5s
Dim Pwm_count As Byte
Dim Pwm_solla As Byte
'Timer und Interrupts konfigurieren
'******************************************************************************
' Timer fuer Multiplex
Config Timer0 = Timer , Prescale = 64
On Timer0 Anzeige
Const Timervorgabe_0 = 214
Enable Timer0
'Timer fuer PWM
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Prescale = 1
Helligkeit Alias Compare1a
Helligkeit = 128
'Sub-Deklaration
'******************************************************************************
Declare Sub Write_port(x As Byte) ' teilt das Byte x auf die Ports auf (IN1-8)
'I2C konfigurieren
'******************************************************************************
Config Sda = Portb.7
Config Scl = Portb.6
'Initialisierung, anzeige Dunkel
'******************************************************************************
Segbyte = 0
Call Write_port(segbyte)
Blink_dp_flag = 1
Enable Interrupts
'******************************************************************************
'Hauptabschleife
'******************************************************************************
Main:
Do
Gosub Gettime
Gosub Convert
If Taster2 = 0 Then
If Helligkeit < 255 Then Incr Helligkeit
Waitms 5
End If
If Taster1 = 0 Then
If Helligkeit > 0 Then Decr Helligkeit
Waitms 5
End If
If Taster1 = 0 And Taster2 = 0 Then Gosub Menu
Loop
'******************************************************************************
'******************************************************************************
'I2c Routinen
'******************************************************************************
'------------------------------------------------------------------------------
Gettime:
I2cstart ' generate start
I2cwbyte &HA0 ' write addres of PCF8583
I2cwbyte 1 ' select second register
I2cstart ' generate repeated start
I2cwbyte &HA1 ' write address for reading info
I2crbyte X , Ack
Hundertstel = Makedec(x)
I2crbyte X , Ack ' read seconds
Sekunden = Makedec(x)
I2crbyte X , Ack ' read minuts
Minuten = Makedec(x)
I2crbyte X , Ack ' read hours
Stunden = Makedec(x)
I2crbyte X , Ack ' read year and days
Tag = Makedec(x)
I2crbyte X , Nack ' read weekday and month
Monat = Makedec(x)
I2cstop ' generate stop
I2cstart ' generate start
I2cwbyte &HA0 ' write addres of PCF8583
I2cwbyte 16 ' select 16. register
I2cstart ' generate repeated start
I2cwbyte &HA1 ' write address for reading info
I2crbyte X , Nack ' lese Jahr aus RAM Byte 17
Jahr = Makedec(x)
I2cstop
Return
'------------------------------------------------------------------------------
Settime:
I2cstart ' generate start
I2cwbyte &HA0 ' write address
I2cwbyte 0 ' select control register
I2cwbyte 8 ' set year and day bit for masking
I2cstop ' generate stop
I2cstart ' generate start
I2cwbyte &HA0 ' write mode
I2cwbyte 2 ' select seconds Register
X = Makebcd(sekunden) ' seconds
I2cwbyte X ' write seconds
X = Makebcd(minuten) ' minuts
I2cwbyte X ' write minuts
X = Makebcd(stunden) ' hours
I2cwbyte X ' write hours
I2cstop ' generate stop
Return
'------------------------------------------------------------------------------
Setdate:
I2cstart ' generate start
I2cwbyte &HA0 ' write address
I2cwbyte 0 ' select control register
I2cwbyte 8 '=&B00001000 : set year and day bit for masking
I2cstop ' generate stop
I2cstart ' generate start
I2cwbyte &HA0 ' write mode
I2cwbyte 5 ' select day Register
X = Makebcd(tag) ' days
I2cwbyte X ' write days
X = Makebcd(monat) ' months
I2cwbyte X ' write months
I2cstop ' generate stop
I2cstart ' generate start
I2cwbyte &HA0 ' write mode
I2cwbyte 16 ' select first Register RAM
X = Makebcd(jahr) ' months
I2cwbyte X ' write months
I2cstop
'******************************************************************************
'Menuefunktionen
'******************************************************************************
'------------------------------------------------------------------------------
'Auswahlmenue
'------------------------------------------------------------------------------
Menu:
Menu = 1
Blink_dp_flag = 0
Taster1_msg = 0
Waitms 250
Do
For I = 1 To 5
Ziffern(i) = 11
Next
If Taster2 = 0 Then
Incr Menu
Waitms 250
If Menu = 6 Then Menu = 1
End If
Gosub Back
If Taster1_msg = 2 Then
Taster1_msg = 0
For I = 1 To 6
Ziffern(i) = 14
Next
wait 2
Return
End If
If Taster1 = 0 And Taster2 = 0 Then Return
Select Case Menu
Case 1 : Z6er = 1
If Taster1_msg = 1 Then Gosub Time_set
Case 2 : Z6er = 2
If Taster1_msg = 1 Then Gosub Date_set
Case 3 : Z6er = 3
If Taster1_msg = 1 Then Gosub Animation_set
Case 4 : Z6er = 4
If Taster1_msg = 1 Then Gosub Blink_set
Case 5 : Z6er = 5
If Taster1_msg = 1 Then Gosub Wechsel_set
End Select
Waitms 10
Loop
'-------------------------------------------------------------------------------
'Menue Uhrzeit einstellen
'-------------------------------------------------------------------------------
Time_set:
Menu_sub = 1
Taster1_msg = 0
Gosub Gettime
Sekunden = 0
Gosub Convert
Waitms 250
Do
If Taster2 = 0 Then
Incr Menu_sub
Waitms 250
If Menu_sub = 3 Then Menu_sub = 1
If Taster1 = 0 Then
Gosub Blinker_aus
Return
End If
End If
If Taster1_msg = 2 Then
Taster1_msg = 0
Gosub Settime
Gosub Blinker_aus
Gosub Disp_set
Return
End If
Gosub Back
Select Case Menu_sub
Case 1 : Blinker(6) = 1
Blinker(5) = 1
Blinker(4) = 0
Blinker(3) = 0
If Taster1_msg = 1 Then
Taster1_msg = 0
Incr Stunden
Waitms 10
If Stunden = 24 Then Stunden = 0
Gosub Convert
End If
Case 2 : Blinker(4) = 1
Blinker(3) = 1
Blinker(6) = 0
Blinker(5) = 0
If Taster1_msg = 1 Then
Taster1_msg = 0
Incr Minuten
Waitms 10
If Minuten = 60 Then Minuten = 0
Gosub Convert
End If
End Select
Incr Blinker_puls 'blinkimpulszähler
If Blinker_puls = 255 Then Blinker_puls = 0
Waitms 10
Loop
'-------------------------------------------------------------------------------
'Menue Datum einstellen
'-------------------------------------------------------------------------------
Date_set:
Return
'-------------------------------------------------------------------------------
'Menue Animationstyp
'-------------------------------------------------------------------------------
Animation_set:
Menu_sub = 0
Taster1_msg = 0
For I = 1 To 6
Ziffern(i) = 11
Next
Waitms 500
Z6er = 3
Do
Gosub Back
If Taster1_msg = 2 Then
Taster1_msg = 0
Gosub Disp_set
Return
End If
If Taster2 = 0 Then
Incr Menu_sub
If Menu_sub = 4 Then Menu_sub = 0
Waitms 250
End If
Select Case Menu_sub
Case 0 : Animation_type = 0 'animation aus
Z1er = 15
Z2er = 15
Z3er = 0
Case 1 : Animation_type = 1 'animation nach unten rausschieben
Z1er = 11
Z2er = 1
Z3er = 11
Case 2 : Animation_type = 2 'ein-/ausblenden
Z2er = 2
Case 3 : Animation_type = 3 'überblenden
Z2er = 3
End Select
Waitms 10
Loop
'-------------------------------------------------------------------------------
'Menue für DP Blinkeinstellung
'-------------------------------------------------------------------------------
Blink_set:
Return
'-------------------------------------------------------------------------------
'Menue ob Datum und Uhrzeit sich abwechseln sollen
'-------------------------------------------------------------------------------
Wechsel_set:
Return
'-------------------------------------------------------------------------------
'Abfrage ob Taster 1 lange gedrückt
'-------------------------------------------------------------------------------
Back:
If Taster1 = 0 Then ' Taste gedrückt ?
Incr Key_time ' Tastendruckzeit hochzählen
If Key_time = Key_lang Then ' Taste lange = 100 = 1s gedrückt ?
Taster1_msg = 2 ' Ja, Mitteilung schicken
End If
Else ' Wird dieser Teil erreicht, so ist/wurde die Taste losgelassen
If Key_time >= Key_kurz And Key_time < Key_lang Then ' Länger als 5 = 50ms und kürzer als Taste lange 100 = 1s gedrückt ?
Taster1_msg = 1 ' Ja, Mitteilung schicken
End If
Key_time = 0 ' Tastenzähler zurücksetzen, alles kleiner oder gleich 50ms wird zwecks Entprellung ignoriert
End If
Return
'-------------------------------------------------------------------------------
'Anzeige "SET" als Bestätigung
'-------------------------------------------------------------------------------
Disp_set:
For I = 1 To 6
Ziffern(i) = 14
Next
Z1er = 13
Z2er = 12
Z3er = 5
Wait 2
Return
'-------------------------------------------------------------------------------
'hier werden die Blinkbytes alle auf ausgestellt
'-------------------------------------------------------------------------------
Blinker_aus:
For I = 1 To 6
Blinker(i) = 0
Next
Return
'******************************************************************************
'Hier wird das Anzeigebyte auf die richtigen Ausgaenge geroutet
'******************************************************************************
Sub Write_port(x As Byte)
Portd.2 = X.0 'IN1
Portd.1 = X.1 'IN2
Portd.0 = X.2 'IN3
Portc.1 = X.3 'IN4
Portc.5 = X.4 'IN5
Portc.4 = X.5 'IN6
Portc.3 = X.6 'IN7
Portc.2 = X.7 'IN8
End Sub
'Dezimalzahlen auf einzelne Stellen aufsplitten und in Anzeigebytes konvertieren
'******************************************************************************
Convert:
Z2er = Sekunden / 10
Z1er = Sekunden Mod 10
Z4er = Minuten / 10
Z3er = Minuten Mod 10
Z6er = Stunden / 10
Z5er = Stunden Mod 10
Return
'Interrupt-Routine
'******************************************************************************
Anzeige:
Timer0 = Timervorgabe_0
Incr Pwm_count
If Pwm_count = 25 Then Pwm_count = 0
Incr Stelle
If Stelle = 7 Then Stelle = 1
If Blinker_puls < 128 And Blinker(stelle) = 1 Then
Segbyte = 0
Else
Segbyte = Lookup(ziffern(stelle) , Segmentmuster)
End If
'Pwm_solla = 12
'If Stelle = 1 Then
' If Pwm_solla < Pwm_count Then Segbyte = 0 Else Segbyte = Lookup(z1er , Segmentmuster)
'End If
If Blink_dp_flag = 1 Then
If Z1er.0 = 1 And Stelle = 3 Then Segbyte = Segbyte Or &B10000000
If Z1er.0 = 1 And Stelle = 5 Then Segbyte = Segbyte Or &B10000000
End If
Call Write_port(segbyte)
Select Case Stelle 'Ziffer ansteuern (1 bis 6) segbyte wird gelatcht
Case 1 : Z1 = 1
Z1 = 0
Case 2 : Z2 = 1
Z2 = 0
Case 3 : Z3 = 1
Z3 = 0
Case 4 : Z4 = 1
Z4 = 0
Case 5 : Z5 = 1
Z5 = 0
Case 6 : Z6 = 1
Z6 = 0
End Select
Return
End
'Segmentdaten
'******************************************************************************
' --a-- a: Portd.2
' f ! ! b b: Portd.1
' ! ! c: Portd.0
' --g-- d: Portc.1
' e ! ! c e: Portc.5
' ! ! f: Portc.4
' --d-- * g: Portc.3
' DP: Portc.2
Segmentmuster:
'dpgfedcba
Data &B00111111 '0
Data &B00000110 '1
Data &B01011011 '2
Data &B01001111 '3
Data &B01100110 '4
Data &B01101101 '5
Data &B01111101 '6
Data &B00000111 '7
Data &B01111111 '8
Data &B01101111 '9
Data &B10000000 '10 # dp
Data &B01000000 '11 # -
Data &B01111001 '12 # E
Data &B01111000 '13 # t
Data &B00000000 '14 # dunkel
Data &B01110001 '15 # F
'dpgfedcba