Binär-Uhr mit Multiplexing und Dimmung
Hier hab ich mal ein wenig mit Multiplexing und Dimmung gleichzeitig
gespielt. Es ist zum Zeigen des Prinzips gedacht.
Damit alles etwas flüssiger aussieht habe ich den Wait auf 100µs gesetzt.
Das ganze sieht also Zählermäßig folgendermaßen aus ...
Schleifendurchlauf --> /16 (PWM-Rampe) --> /3 (Multiplexing)
Schleifendurchlauf --> /1500 (Verzögerung) --> Sekunden --> /16 (Dimmschritte) --> /2 (Hoch/Runter) --> Dimm-Durchlauf
Wobei die Uhr immer noch absolut zu schnell geht damit man nicht ewig auf
die Stunden warten muß.
CodeBox BASCOM
' #################################################
' ##### Programmentwicklung auf einem ATmega8 #####
' #################################################
' (c) 20.08.2010 by Dino
'
' Mega8-HowTo Nr010 Multiplexing und Dimmung
'
' Wir bauen uns eine kleine sehr einfache Binaer-Uhr
' Prozessor ATmega8 - Definitionsdatei fuer internen uC-Aufbau
$regfile = "m8def.dat"
' 8,000MHz interner Takt
$crystal = 8000000
' 16,000MHz Quarztakt
'$crystal = 16000000
' Groesse des Hardwarestacks fuer Ruecksprungadressen (SUBs/ISRs/...)
$hwstack = 40
' Groesse des Softwarestacks fuer Adressen von Uebergabeparameter an SUBs
$swstack = 32
' Speichergroesse fuer Uebergabeparameter an Unterprogramme, lokale Variablen
' und temporaere Werte
$framesize = 60
' Wenn man die Variablen selber sauber setzt kann man sich den Code von
' BASCOM fuer eine Speicherreinigung sparen.
$noramclear
' ################################
' ##### DEFINITION DER PORTS #####
' ################################
'
' PB0 ---->-- Test-LED 5mm rot
' PB1 ------- nix
' PB2 ------- nix
'
' PB3 -- MOSI |
' PB4 -- MISO | ISP-Port
' PB5 -- SCK |
'
' PB6 -- XTAL1 | Systemquarz
' PB7 -- XTAL2 | 16,000MHz
'
' ===== PortB =================================================================
' I=7= I=6= I=5= I=4= I=3= I=2= I=1= O=0= => 00000001 => DDRB (In/Out)
' XTAL2 XTAL1 ---- ---- ---- ---- ---- LED => 00000000 => PORTB (PullUp/init)
' x x | | | | | |
'
Ddrb = &B0000_0001
Portb = &B0000_0000
'
'
'
' PC0 ------- nix
' PC1 ------- nix
' PC2 ------- nix
' PC3 ------- nix
' PC4 ------- nix
' PC5 ------- nix
' PC6 -- RESET | ISP-Port
'
' ===== PortC =================================================================
' I=7= I=6= I=5= I=4= I=3= O=2= O=1= O=0= => 00000000 => DDRC (In/Out)
' ---- Reset ---- ---- ---- Row3 Row2 Row1 => 00000000 => PORTC (PullUp/init)
' x x | | | | | |
'
Ddrc = &B0000_0111
Portc = &B0000_0100
'
'
'
' PD0 ---->-- LED0 3mm gelb
' PD1 ---->-- LED1 3mm gelb
' PD2 ---->-- LED2 3mm gelb
' PD3 ---->-- LED3 3mm gelb
' PD4 ---->-- LED4 3mm gelb
' PD5 ---->-- LED5 3mm gelb
' PD6 ---->-- LED6 3mm gelb
' PD7 ---->-- LED7 3mm gelb
'
' ===== PortD =================================================================
' O=7= O=6= O=5= O=4= O=3= O=2= O=1= O=0= => 11111111 => DDRD (In/Out)
' LED7 LED6 LED5 LED4 LED3 LED2 LED1 LED0 => 00000000 => PORTD (PullUp/init)
' | | | | | | | |
'
Ddrd = &B1111_1111
Portd = &B0000_0000
'
'
' ======= Aufbau der LED-Matrix ================
'
' PC0 (Sekunden)
' |
' | PC1 (Minuten)
' | |
' | | PC2 (Stunden)
' | | | 1k
' o------------->|--o--###---PD0 Bit0
' | | | |
' | o---------->|--o
' | | | |
' | | o------->|--o
' | | | 1k
' o------------->|--o--###---PD1 Bit1
' | | | |
' | o---------->|--o
' | | | |
' | | o------->|--o
' | | | LEDs
' : : :
' Die Stelle wird durch eine 1 (Vcc) am entsprechenden Bit von PortC eingeschaltet
' Die Bits der Stelle werden durch eine 0 (GND) beim PortD eingeschaltet. Da die Bits
' in einem Byte des Sekunden/inuten/Stundenzaehlers genau anders herum arbeiten
' also 1= Eingeschaltet muß zur Ausgabe am Port invertiert werden.
' ###############################################
' ##### Variablendeklaration ####################
' ###############################################
' Variable Stelle als Byte anlegen - fuer die Umschaltung beim Multiplexing
Dim Stelle As Byte
' und initialisieren (Anfangswert setzen)
Stelle = 1
' Variable fuer Sekunden (0..59)
Dim Sekunden As Byte
Sekunden = 0
' Variable fuer Minuten (0..59)
Dim Minuten As Byte
Minuten = 0
' Variable fuer Stunden (0..23)
Dim Stunden As Byte
Stunden = 0
' Verzoegerungszaehler - Nach x Schleifendurchlaeufen soll Sekunde +1
' Mit Hilfe dieses Zaehler kann man die "Uhr" vom Multiplexing entkoppeln
Dim Verzoegerung As Word
Verzoegerung = 0
' Variable zum Zwischenspeichern von allem moeglichen
Dim Temp As Byte
Temp = 0
Dim Hell As Byte
Hell = 15
Dim Rampe As Byte
Rampe = 0
Dim Updn As Bit
Updn = 0
' ###############################################
' ##### Hauptschleife Start #####################
' ###############################################
Do
Waitus 100 ' 0,1ms warten
' ======== Zeitverarbeitung ===========
' Der Verzoegerungszaehler
' Nach 20 Durchlaeufen der Hauptschleife soll die Sekunde eins hochgezaehlt werden
' Wer wirkliche Sekunden haben moechte ...
' Bei "Waitms 10" muessten 100 Durchlaeufe in etwa eine Sekunde ergeben. Also >99
' Damit man aber auf eine Aenderung der Stunden nicht ewig warten muß hab ich es
' ein wenig beschleunigt (5 fach)
Verzoegerung = Verzoegerung + 1
If Verzoegerung > 1500 Then
Verzoegerung = 0
Sekunden = Sekunden + 1
' Hier wird ein wenig mit der Helligkeit gespielt
' Jeder "Sekundentakt" wird ein Schritt herauf oder herabgedimmt.
' Die Anzeige pulst also mit einem Rhytmus von 32 Sekundentakten
If Updn = 1 Then ' 1 = Hochdimmen
Incr Hell ' Helligkeit um 1/16 heller
If Hell >= 15 Then ' Volle Helligkeit erreicht
Hell = 15 ' Sicherheitshalber Maximalwert setzen (für Fehlerfall)
Updn = Not Updn ' Umschalten von Hoch- auf Runterdimmen
End If
Else ' 0 = Runterdimmen
Decr Hell ' Helligkeit um 1/16 dunkler
If Hell < 1 Then
Hell = 0 ' Sicherheitshalber Minimalwert setzen (für Fehlerfall)
Updn = Not Updn ' Umschalten von Runter- auf Hochdimmen
End If
End If
End If
' Wenn der Sekundenzaehler ueber 59 geht sollen Minuten +1 und die Sekunden wieder auf 0
If Sekunden > 59 Then
Sekunden = 0
Minuten = Minuten + 1
End If
' Wenn der Minutenzaehler ueber 59 geht sollen Stunden +1 und die Minuten wieder auf 0
If Minuten > 59 Then
Minuten = 0
Stunden = Stunden + 1
End If
' Wenn der Stundenzaehler ueber 23 geht soll er wieder auf 0
If Stunden > 23 Then
Stunden = 0
End If
' ======== Das Dimming ======================
' der Rampenzaehler fuer das Soft-PWM
' er geht von 0..15 . Also 0,1,2,..,14,15,0,1,...
' Damit eine Stelle richtig gedimmt werden kann muss sie
' natuerlich synchron zur Dimm-Rampe umgeschaltet werden.
' Darum wird erst nach beendeter Rampe die naechste Stelle eingeschaltet.
Rampe = Rampe + 1
If Rampe > 15 Then
Rampe = 0
Stelle = Stelle + 1 ' Eine Stelle weitergehen (+1)
End If
' ======== Das Multiplexing =================
' Nach Vollendung einer PWM-Rampe kommt die naechste Stelle dran
If Stelle > 3 Then ' Wir haben nur 3 Stellen (Stunden, Minuten, Sekunden)
Stelle = 1 ' also zurueck auf die erste Stelle
End If
' Die erste Stelle ausgeben (Sekunden)
If Stelle = 1 Then
Temp = Not Sekunden ' Die Bits fuer die Sekunden invertieren damit die richtigen LEDs an sind
Portd = Temp ' und ausgeben
If Hell > Rampe Then
Portc = &B0000_0001 ' und natuerlich die Stelle fuer die Sekunden anschalten
Else
Portc = &B0000_0000 ' oder wegen dimmung abschalten
End If
End If
' Das selbe fuer die Minuten
If Stelle = 2 Then
Temp = Not Minuten
Portd = Temp
If Hell > Rampe Then
Portc = &B0000_0010
Else
Portc = &B0000_0000
End If
End If
' und nochmal fuer die Stunden
If Stelle = 3 Then
Temp = Not Stunden
Portd = Temp
If Hell > Rampe Then
Portc = &B0000_0100
Else
Portc = &B0000_0000
End If
End If
Loop
' ###############################################
' ##### Hauptschleife Ende ######################
' ###############################################
' ###############################################
' ##### Programm Ende ###########################
' ###############################################
End
und zum Abschluß noch einmal der Quellcode.
Anhang anzeigen Mega8-HowTo_Nr010_LED-MuxDim.bas
Was zu beweisen war ... man kann auch ohne Interrupts und Timer schon
ne Menge machen wenn man es geschickt anstellt. Genaue Zeiten für ne
Uhr wird man zwar nicht hinbekommen aber für einige Spielereien reicht es
aus.
Gruß
Dino