| Weitere Artikel aus dem Elo-Magazin |
Die Ping-Pong-Uhr
von Wolfram Herzog
Die Platine aus dem Franzis PING-PONG hat ein überaus gut durchdachtes Design. Neben einer ISP Schnittstelle sind auch die unbenutzten I/O-Leitungen des MEGA8 und die Anschlüsse für den Anschluss eines Quarzes verfügbar. Dadurch ist diese Platine für eine Vielzahl anderer Projekte universell einzusetzen. Hier folgt die Beschreibung zum Bau einer Quarz-Uhr auf der Basis der Ping-Pong-Platine.
Zunächst muss der Mikrocontroller einen Quarz bekommen. Dazu wird auf der Platine an die Anschlüsse B6 und B7 ein 32-kHz-Uhrenquarz gelötet. Um die Uhr einstellen zu können, sind dann noch zwei Taster nötig. Diese werden zum einen an die Anschlüsse C4 und C5 zum anderen gemeinsam an K1 (GND) angeschlossen. Damit ist die Hardware fertig. Da der Stromverbrauch doch recht hoch ist, sollte ein 5-V-Netzteil zum Einsatz kommen. Die Batterien sind sonst recht schnell erschöpft.
Ganzen Artikel lesen...

Das verwendete Programm wurde in BASCOM erstellt und zeigt einmal mehr die Mächtigkeit dieser Entwicklungsumgebung. Die gesamte Uhrensteuerung erfolgt mit der BASCOM Softclock. Dies ist ein Befehl, der mit nur zwei Zeilen Code eine komplette, timergesteuerte Uhr inklusive Datum implementiert. Damit diese Softclock funktioniert, muss aber ein Uhrenquarz am AVR angeschlossen sein und dieser durch Setzen der Fuse CKOPT aktiviert sein. Der Quarz taktet dann den Timer2 welcher zur Steuerung der Softclock benutzt wird.
Zur Ansteuerung wurde der Beispielcode aus dem Artikel „BASCOM Start" als Grundlage benutzt. Während in der originalen Software der Timer2 das Multiplexing der LEDs steuert, wurde dies nun Timer0 übertragen, um Timer2 für die Softclock verfügbar zu haben. Ein wenig Kopfzerbrechen bereitete die Ansteuerung der Taster. Erst nach einigen Versuchen wurde klar, dass die originale LED Routine alle Pins von PortC zyklisch beschreibt und daher eine Abfrage der Taster nicht korrekt funktionierte. Es wurde nämlich immer die gerade geschriebenen Werte der Pins gelesen. Die Routine wurde daher so geändert dass nur noch die niederwertigsten vier Bits geschrieben werden, und nun war auch die Abfrage der Taster problemlos möglich.
Das Programmlisting wurde im Hinblick auf die erzeugte Codegröße optimiert, damit die 4-KB-Grenze der kostenlosen Version von BASCOM nicht überschritten wird. Daher wurden alle wiederholten Funktionen konsequent in Unterprogramme ausgelagert. Das Listing ist ausführlich kommentiert und sollte daher leicht nachzuvollziehen sein.
Bei laufender Zeitanzeige kann mit dem Taster C4 die Uhr gestellt werden. Durch mehrfaches Drücken können nacheinander die einzelnen Zahlen der Uhrzeit angezeigt und dann durch die Taste C5 der gewünschte Wert eingestellt werden. Wird bei laufender Zeitanzeige die Taste C5 gedrückt, kann die Laufgeschwindigkeit verstellt werden.
Download: Bascom-Quelltext und Hexfile
'*********************************************
'Scrolling Clock für FRANZIS PINGPONG Platine
'
'Timer0 für Scrolling
'Timer2 für Softclock
'
'1.2.4 Unterdrückung führende Null bei Stunden
'1.5.0 Zeichensatz neu definiert
'
'Taster an PC4 und PC5 zum Stellen der Uhr
'Uhrenquarz 32 KHz an B6 und B7 löten
'
'24-1-2010 Wolfram Herzog
'Version 1.5.5
'*********************************************
$crystal = 8000000
$regfile = "m8def.dat"
$hwstack = 64
$swstack = 64
$framesize = 64
Dim Leds(13) As Word 'LED Darstellung Datenarray aus 13 Worten (weg Index)
Dim Zeichtab(50) As Word 'Zeichentabelle zum kopieren
Dim Zeichen(60) As Word 'Zeichen zur Darstellung
Dim N As Word 'Schieben der Pixel
Dim Zeit As String * 8 'Zeitstring
Dim Zeitdata(9) As Byte At Zeit Overlay
Dim Speed As Word 'Bestimmt scrollgeschwindigkeit
Dim B As Byte
Dim C As Byte
Dim Ci As Byte
Dim Xi As Byte
Dim Al As Byte 'Schleifenzähler für LED Darstellung
Dim Bl As Byte
'* Variblen für String Management
Dim I As Byte 'Index für Array Zugriff
Dim Iz As Byte 'Index Zeichenarray
Dim Zt As Byte
Dim K As Word 'byte? 'K = Keyboard
Dim Z As Byte
Dim Ta As String * 1 'Index des Timearray
'* Index Variablen für Uhr Stellen
Dim Si As Byte
Dim Siz As Byte
Declare Sub Initialisierung
Declare Function Zeitzahl(zeit As String , I As Byte) As Byte
'** Softclock konfigurieren **
Config Date = Mdy , Separator = - ' ANSI-Format
Config Clock = Soft 'benutzt timer2
Time$ = "12:34:56" ' Uhr setzen
Config Debounce = 50
Speed = 150 'Mittlere Scrollgeschwindigkeit
Initialisierung 'Ports und Interrupts initialisieren
Gosub Inizeichtab
'**** Schleife zum Ansteuern aller LED'S *****************
Do
For Bl = 0 To 44 'Zähler für Zeichenarray
For Al = 0 To 11 'Zähler für LED Arrray
Xi = Bl + Al
If Xi > 44 Then Xi = Xi - 44
K = Zeichen(xi)
N = K
Rotate N , Left 'Pixel nach links um Text in Mitte zu bekommen
Leds(al + 1) = N 'offset +1 wegen Array beginnt mit Element 1
Next Al
Zeit = Time$ 'Zeitvariable muß regelmäßig ausgelesen werden
Gosub Machpixel 'update des Pixelfeldes
If Pinc.4 = 0 Then Gosub Stellen 'Taste gedrückt?
If Pinc.5 = 0 Then Gosub Setspeed
Waitms Speed 'Scrollgeschwindigkeit
Next Bl
Loop
End '############ END ##################
'********** Scrollgeschwindigkeit einstellen ****************
Setspeed:
Speed = Speed - 10
If Speed = 20 Then Speed = 250
Return
'*********************** Stellen der Uhr ******************
' Bedienung mit Taster an PC4 und PC5
Stellen: 'Uhrzeit stellen
For B = 1 To 12 'LED Puffer löschen
Leds(b) = 0
Next B
Stellstart:
'--------------------------
Leds(1) = &B0000000011 'Indicator anzeigen
Si = 1 'Zeichenpositiom im String
Gosub Redraw
Warten1:
Debounce Pinc.4 , 0 , Weiter1
Debounce Pinc.5 , 0 , Plus1
Goto Warten1
Plus1:
Incr Zeitdata(1)
If Zeitdata(1) = "3" Then Zeitdata(1) = "0"
Waitms 100
Goto Stellstart
'----------------------------
Weiter1:
Leds(1) = &B0000001100
Si = 2 'Zeichenposition im String
Gosub Redraw
Warten2:
Debounce Pinc.4 , 0 , Weiter2
Debounce Pinc.5 , 0 , Plus2
Goto Warten2
Plus2:
If Zeitdata(1) = "2" Then
Incr Zeitdata(2)
If Zeitdata(2) = "4" Then Zeitdata(2) = "0"
Else
Incr Zeitdata(2)
If Zeitdata(2) = ":" Then Zeitdata(2) = "0" 'Nach 9 kommt : in ASCII
End If
Waitms 100
Goto Weiter1
'----------------------------
Weiter2:
Leds(1) = &B0000110000
Si = 4 'Zeichenposition im String
Gosub Redraw
Warten3:
Debounce Pinc.4 , 0 , Weiter4 '4
Debounce Pinc.5 , 0 , Plus3
Goto Warten3
Plus3:
Incr Zeitdata(4)
If Zeitdata(4) = "6" Then Zeitdata(4) = "0"
Waitms 100
Goto Weiter2
'------------------------
Weiter4:
Leds(1) = &B0011000000
Si = 5 'Zeichenposition im String
Gosub Redraw
Warten4:
Debounce Pinc.4 , 0 , Weiter5
Debounce Pinc.5 , 0 , Plus4
Goto Warten4
Plus4:
Incr Zeitdata(5)
If Zeitdata(5) = ":" Then Zeitdata(5) = "0"
Waitms 100
Goto Weiter4
'--------------------------
Weiter5:
Leds(1) = &B0110000000
Si = 7 'Zeichenposition im String
Gosub Redraw
Warten5:
Debounce Pinc.4 , 0 , Weiter6
Debounce Pinc.5 , 0 , Plus5
Goto Warten5
Plus5:
Incr Zeitdata(7)
If Zeitdata(7) = "6" Then Zeitdata(7) = "0"
Waitms 100
Goto Weiter5
'---------------------------
Weiter6:
Leds(1) = &B1100000000
Si = 8 'Zeichenposition im String
Gosub Redraw
Warten6:
Debounce Pinc.4 , 0 , Stellende
Debounce Pinc.5 , 0 , Plus6
Goto Warten6
Plus6:
Incr Zeitdata(7)
If Zeitdata(7) = ":" Then Zeitdata(7) = "0"
Waitms 100
Goto Weiter6
'---------------------------
Stellende:
'Gosub Inizeichtab
Time$ = Zeit 'Time$ neu setzen
Return
'****************** Redraw *****************************
' Koipiert das Zeichen beim Stellen direkt in LEDS Buffer
Redraw:
Leds(2) = 0
Siz = 2
Z = Zeitzahl(zeit , Si) 'Z ergibt den Index für Zeichentabelle
For Ci = 1 To 5
Incr Siz
Zt = Ci + Z
Leds(siz) = Zeichtab(zt - 1)
Next Ci
Return
'************************ ZEIT String auswerten *************************
' Erzeugt die Pixel im ZEICHEN Array
Machpixel:
I = 1 'Index String
Iz = 1 'Index zeichenzähler initialisieren
Ta = Mid(zeit , I , 1) 'Byte 1 aus Timearray wird in TA koipert
B = Val(ta) 'ASCII-String wird in Byte Wert umgerechnet
If B = 0 Then 'Unterdrücken der führenden Null
For Ci = 1 To 5
Zeichen(iz) = 0
Incr Iz
Next Ci
Else
Z = B * 5 'Z ergibt den Index für Zeichentabelle
For Ci = 1 To 5
Zt = Ci + Z
Zeichen(iz) = Zeichtab(zt - 1)
Incr Iz
Next Ci
End If
Incr Iz 'Zeichentabellenindex erhöhen
Incr I 'String zähler erhöhen
Z = Zeitzahl(zeit , I) 'Z ergibt den Index für Zeichentabelle
Gosub Zeitzeichen
Gosub Trenner
Z = Zeitzahl(zeit , I) 'Z ergibt den Index für Zeichentabelle
Gosub Zeitzeichen
Incr I
Incr Iz
Z = Zeitzahl(zeit , I) 'Z ergibt den Index für Zeichentabelle
Gosub Zeitzeichen
Gosub Trenner
Z = Zeitzahl(zeit , I) 'Z ergibt den Index für Zeichentabelle
Gosub Zeitzeichen
Incr I
Incr Iz
Z = Zeitzahl(zeit , I) 'Z ergibt den Index für Zeichentabelle
Gosub Zeitzeichen
Return
'********************* Zeitzahl ************************************
' Ausrechnen welcher Index auf ZEICHTAB geht
Function Zeitzahl(zeit As String , I As Byte) As Byte
Ta = Mid(zeit , I , 1) 'Byte 1 aus Timearray wird in TA koipert
B = Val(ta) 'ASCII-String wird in Byte Wert umgerechnet
Zeitzahl = B * 5 'Z ergibt den Index für Zeichentabelle
End Function
'******************** Zeitzeichen *********************************
' Pixel in Zeichen Matrix eintragen
Zeitzeichen:
For Ci = 1 To 5
Incr Iz
Zt = Ci + Z
Zeichen(iz) = Zeichtab(zt - 1)
Next Ci
Return
'****************** Trennzeichen erzeugen *************************
Trenner:
Incr Iz
Zeichen(iz) = &H00
Incr Iz
Zeichen(iz) = &B01100110
Incr Iz
Zeichen(iz) = &H00
Incr I
Incr I
Return
'**** Zeichentabelle initialisieren ****
Inizeichtab:
For B = 0 To 49 'Konstante Pixel in Variable Zeichtab umkopieren
C = Lookup(b , Pixels)
Zeichtab(b) = C
Next B
Return
'****************** Service-Unterprogramme *********************
Sub Initialisierung
Config Portc = 15 'PORTC als AD-Eingang
Config Portb = Output
Config Portd = 255
Config Pinc.4 = Input 'Pins für Taster
Config Pinc.5 = Input
Portc.4 = 1 'interne Pull up aktivieren
Portc.5 = 1
Config Timer0 = Timer , Prescale = 8 'Wegen Softclock auf Timer0 umgestellt
On Ovf0 Tim0_isr
Enable Timer0
Enable Interrupts
Start Timer0
' Config Int0 = Low Level 'Falling
' On Int0 Int_isr
End Sub
'Int_isr:
': Disable Int0
'Return
'******************************* Interrupt - Display ****************************
Dim Vy As Byte
Dim Col As Byte
Dim Portdout As Byte
Dim Portcout As Byte
Tim0_isr:
'800 µs
'Timer0 = 56
Col = Col + 1
If Col = 13 Then Col = 1
Vy = Col + 0
Portd = 0
Portb = 0
Portc = 0
If Col = 1 Then Portb.4 = 0 Else Portb.4 = 1
Portb.3 = 1 'cl
Portb.3 = 0
Portb.2 = 1 'Str
Portb.2 = 0
Portdout = Low(leds(vy))
Portcout = Portdout And 15
Portdout = Portdout And 240
Portd = Portdout
Portc.0 = Portcout.0 'Nibble einzeln ausgeben
Portc.1 = Portcout.1
Portc.2 = Portcout.2
Portc.3 = Portcout.3
Portc.4 = 1 'müssen wegen Tastenabfrage auf 1 gesetzt sein
Portc.5 = 1
Portb = High(leds(vy))
'Waitms 500
Return
'******** Daten Zeichentabelle 5*8 Pixel **************************
Pixels:
'Matrix 5 * 8 Zeichen
Data 126 , 129 , 129 , 129 , 126 '; 0
Data 0 , 0 , 130 , 255 , 128 '; 1
Data 194 , 161 , 145 , 145 , 142 '; 2
Data 66 , 129 , 137 , 137 , 118 '; 3
Data 24 , 20 , 18 , 255 , 16 '; 4
Data 79 , 137 , 137 , 137 , 113 '; 5
Data 124 , 138 , 137 , 137 , 113 '; 6
Data 1 , 241 , 9 , 5 , 3 '; 7
Data 118 , 137 , 137 , 137 , 118 '; 8
Data 6 , 137 , 137 , 73 , 62 '; 9













