Da im Forum immer nur Fragmente zu finden sind, wenn es um die Datumsfunktion geht, stell ich hier mein meinen vollständigen Code für einen PCF8583 rein.
Es wird Datum und Uhrzeit in einer Zeile auf einem 4x20 LCD ausgegeben.
Mit 2 Tastern wird Wochentag+Uhrzeit+Datum verstellt.
Speicherbedarf: weniger als 2 kB
Code:
'BASCOM 1.11.8.1
'Uhrzeit und Datum mit Timer PCF8583
'Stützbatterie an PCF8583 für Stromausfall erforderlich
'
'Bedienung mit 2 Tastern an Pind.4 und Pind.5 gegen Masse und internen Pullups
'Ausgabe auf LCD 4x20 Zeichen in der obersten Zeile
'Mo*23:15:02*29.04.06
'Ausgabe entspricht genau 20 Zeichen
'Taster 1 wählt die Position zum Stellen der Uhr aus (Blinkt)
'Taster 2 zählt hoch
$regfile = "m32def.dat" 'AVR Mega 32
$framesize = 32 'Stackanweisungen nicht optimiert
$swstack = 16
$hwstack = 16
$crystal = 8000000 'Frequenz
$baud = 9600 'Baudrate RS232 Ausgabe.
$lib "mcsbyte.lbx" 'only support bytes!! for numeric<>string conversion
$lib "I2C_TWI.LBX" 'Hardware I2C aktiviert
Config Twi = 100000
'Config Sda = Portc.1 'für Software I2C umstellen
'Config Scl = Portc.0
I2cinit
'Adresse des PCF8583 ggf. auch &HA0 !!
Const Addressw = &HA2 'slave write address
Const Addressr = Addressw + 1 'slave read address
'Taster 1 und 2
Config Portd = &B00000000 '0=INPUT 1=OUTPUT
Portd = Portd Or &B00110000 'pull up Widerstände setzen
Taster1 Alias Pind.4 'Auswahl der Position
Taster2 Alias Pind.5 'Hochzählen
'Pins des LCD-Modules setzen ggf. an eigene Anschlüsse anpassen
Config Lcdpin = Pin , Db4 = Portc.5 , Db5 = Portc.4 , Db6 = Portc.3 , Db7 = Portc.2 , E = Portc.6 , Rs = Portc.7
Config Lcdmode = Port
Config Lcdbus = 4 '4 bit mode
Config Lcd = 20 * 4
Initlcd
Cls
Declare Sub Settime()
Declare Sub Gettime()
Declare Sub Menu()
'Declare array
Dim Tm_raw(5) As Byte At &H60
'pointers to Tm_raw() for simple handling.
Dim S As Byte At &H60 Overlay
Dim M As Byte At &H61 Overlay
Dim H As Byte At &H62 Overlay
Dim Yd As Byte At &H63 Overlay 'Year+Day
Dim Wm As Byte At &H64 Overlay 'Week+Month
Dim Tm(7) As Byte At &H70
'pointers to Tm() for simple handling.
Dim Weekday As Byte At &H70 Overlay
Dim Hour As Byte At &H71 Overlay
Dim Minute As Byte At &H72 Overlay
Dim Second As Byte At &H73 Overlay
Dim Day As Byte At &H74 Overlay
Dim Month As Byte At &H75 Overlay
Dim Year As Byte At &H76 Overlay
'Declare variables
Dim Weekday_s As String * 2
Dim I As Byte
Dim Menupunkt As Byte
Menupunkt = 0
'Main
Do
Call Menu()
Call Gettime()
Locate 1 , 1
Lcd Weekday_s
For I = 2 To 7 'Uhrzeit+Datum 20 Zeichen breit ausgeben
If I = 2 Or I = 5 Then Lcd Chr(255) Else Lcd ":"
If Tm(i) < 10 Then Lcd "0"
Lcd Tm(i)
Next
If Menupunkt > 0 Then
I = 3 * Menupunkt
Decr I
Locate 1 , I
Cursor On Blink
Else
Cursor Off Noblink
End If
Waitms 100
If Taster1 = 0 Or Taster2 = 0 Then Waitms 200
Loop
End
Weekdays:
Data "Mo" , "Di" , "Mi" , "Do" , "Fr" , "Sa" , "So" '0=Mo 1=Di ... 6=So
Sub Settime()
Second = Second Mod 60
Minute = Minute Mod 60
Hour = Hour Mod 24
Decr Day
Day = Day Mod 31
Incr Day
Decr Month
Month = Month Mod 12
Incr Month
'Year = Year Mod 4 'unnötig da 2 Bit Variable
Weekday = Weekday Mod 7
Tm_raw(1) = Makebcd(second)
Tm_raw(2) = Makebcd(minute)
Tm_raw(3) = Makebcd(hour)
Tm_raw(4) = Year * 64 'Jahr um 6 Bit verschieben
Tm_raw(4) = Tm_raw(4) + Makebcd(day)
Tm_raw(5) = Weekday * 32 'Wochentag um 5 Bit verschieben
Tm_raw(5) = Tm_raw(5) + Makebcd(month)
I2cstart 'generate start
I2cwbyte Addressw 'write address
I2cwbyte 0 'select control register
I2cwbyte 0 'set year and day bit for masking
I2cstart 'repeated start
I2cwbyte Addressw 'write mode
I2cwbyte 2 'select Register 2 = seconds
For I = 1 To 5
I2cwbyte Tm_raw(i)
Next 'write Register 2,3,4,5,6
I2cstop
End Sub
Sub Gettime()
Tm_raw(1) = 2 'set start point to second register
I2creceive Addressw , Tm_raw(1) , 1 , 5 'write 1 byte from Tm_raw(1) = 2, and read 5 bytes
Second = Makedec(s) 'values are stored in BCD format
Minute = Makedec(m)
Hour = Makedec(h)
Day = Yd And &B00111111 'Bit 6 und 7 löschen
Day = Makedec(day)
Month = Wm And &B00011111 'Bit 5,6 und 7 löschen
Month = Makedec(month)
Year = Yd / 64 'Register YYDD DDDD
Year = Year + 4 '2004 bis 2007
Weekday = Wm / 32 'Register WWWM MMMM
Weekday_s = Lookupstr(weekday , Weekdays) 'Wochentag ermitteln
End Sub
Sub Menu()
If Taster1 = 0 Then Incr Menupunkt
Menupunkt = Menupunkt Mod 8
If Taster2 = 0 And Menupunkt > 0then
Incr Tm(menupunkt)
Call Settime()
End If
End Sub
Ich habe den Code kurz gehalten. Ich nutze ihn weiter, um Messwerte in ein AT24Cxxx zu schreiben. Da die EEPROMs die gleiche Adresse wie der 8583 haben (!!) habe ich den 8583 auf die Adresse &HA2 gesetzt.
Wer will kann die Jahreszahl aufbohren (derzeit nur 04 bis 07), indem man den batteriegestützen RAM des PCF 8583 benutzt, um eine Variable für die Jahreszahl abzulegen, die von Bascom mit hochgezählt wird.
Ich gehe von einer gestützen Stromversorgung für die RTC aus.
Obwohl im Datenblatt steht VDD=1.0V bei I2C-bus inactive, kommen mir die 1,5V mit Diode mir etwas knapp vor. Bei mir sind es 3V aus einer CR2032. Der Stromverbrauch bei Stromausfall beträgt dann 3,0 µA.
Lesezeichen