Forum: Mikrocontroller und Digitale Elektronik RTC läuft nicht


von Sebastian (Gast)


Lesenswert?

Hi!

ich hab mit einem DS1307Z und einem Atmega164P eine RTC gebaut. Das 
Programm für die Uhr habe ich vor einiger Zeit schon auf einem M8 
betrieben (aus dem Internet), funktioniert also.
Mein Problem ist nun, dass das Uhrzeit und Datum jeweils mit 00.00.00 
angezeigt werden und sich sonst nichts weiter tut. Ich habe keine Ahnung 
woran das liegen könnte, wie gesagt auf einem M8 funktioniert alles 
einwandfrei.
Der Atmega164 wird mit einem 8Mhz Quarz betrieben. Ich hatte die 
vermutung, dass die Taktquelle vllt irgendwo falsch eingestellt ist und 
der qC dann nicht richtig uber I²C mit dem ds1307 kommunizieren kann. 
Hier habe ich jetzt aber auch schon alle möglichen Einstellungen durch 
und bin mir eigentlich sicher, dass alle richtig sind.

Gruß Sebastian

Hier noch der Quellcode:
1
$regfile = "m164pdef.dat"
2
$prog &HFF , &HFF , &H99 , &HFF                             ' generated. Take care that the chip supports all fuse bytes.
3
4
$crystal = 8000000
5
6
Config Lcd = 20 * 2
7
Config Lcdbus = 4
8
Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , Rs = Portb.5 , E = Portb.4
9
Cursor Off
10
Cls
11
12
Dim Seczaehler As Byte
13
14
   'Interrups aktivieren
15
   Enable Interrupts
16
17
   'Interrupts einstellen
18
   On Int0 Ds1307_int
19
   Config Int0 = Rising
20
   Enable Int0
21
   'Disable Interrupts
22
23
    ' TWI (Hardware I2C) einbinden und starten
24
    '$lib "i2c_twi.lbx"
25
    'Config Twi = 100000 ' Init TWBR und TWSR, 100kHz
26
    Config Sda = Portc.1
27
    Config Scl = Portc.0
28
    ' Adressen festlegen
29
    Const Ds1307w = &HD0                                    ' Addresse des DS1307 zum schreiben
30
    Const Ds1307r = &HD1                                    ' Addresse des DS1307 zum lesen
31
32
    ' Uhr konfigurieren
33
    Config Clock = User
34
    Config Date = Dmy , Separator = .                       ' Datumsformat DD.MM.YY
35
36
    ' Variablen für die Uhr festlegen
37
    Dim _wd As Byte                                         ' Wochentag
38
    Dim _sec_bcd As Byte , _min_bcd As Byte , _hour_bcd As Byte , _day_bcd As Byte , _month_bcd As Byte , _year_bcd As Byte
39
40
41
    'Gosub Enable_sqw                                        'SQW der RTC aktivieren
42
    ' Datum und Uhrzeit auslesen
43
    Gosub Getdatetime
44
45
    ' sind schon Daten im DS1307 vorhanden?
46
    If _day = 1 And _month = 1 And _year = 0 Then           ' 01.01.00 = keine Daten
47
    ' Wenn der DS1307 das Datum 01.01.00 enthält können wir davon ausgehen,
48
    ' dass keine gültigen Daten vorhanden sind und diesen Initialisieren.
49
50
    ' Control Register in DS1307 schreiben
51
    ' Genaue Informationen zu dem Conrol Register sind im Datenblatt zu finden.
52
    I2cstart
53
    I2cwbyte Ds1307w
54
    I2cwbyte &H07
55
    I2cwbyte &B00000000
56
               ' |||||||\--RS0
57
               ' ||||||\---RS1
58
               ' |||||\----0
59
               ' ||||\-----0
60
               ' |||\------SQWE
61
               ' ||\-------0
62
               ' |\--------0
63
               ' \---------OUT
64
    I2cstop
65
66
    ' Datum und Uhrzeit stellen
67
    Date$ = "21.01.14"                                      ' Datum
68
    _wd = 5                                                 ' Wochentag
69
    Gosub Setdate                                           ' Datum schreiben
70
    Time$ = "12:48:00"                                      ' Uhrzeit
71
    Gosub Settime                                           ' Uhrzeit schreiben
72
    End If
73
74
    ' Hauptschleife
75
    Do
76
77
    ' Datum und Uhrzeit auslesen
78
    Gosub Getdatetime
79
80
        ' zum Terminal ausgeben
81
    Locate 1 , 1
82
    Lcd Date$ ; " " ; _wd
83
    Locate 2 , 1
84
    Lcd Time$ ; " " ; Seczaehler
85
86
    Waitms 200
87
    Cls
88
89
    Loop
90
91
    End
92
93
    ' RTC DS1307 Programmteile
94
95
    ' Datum und Uhrzeit auslesen
96
    Getdatetime:
97
    ' Daten aus DS1307 abrufen
98
    I2cstart                                                ' I2C Start
99
    I2cwbyte Ds1307w                                        ' Adresse zum schreiben senden
100
    I2cwbyte &H00                                           ' Registeradresse senden
101
    I2cstart                                                ' erneuter I2C Start
102
    I2cwbyte Ds1307r                                        ' Adresse zum lesen senden
103
    I2crbyte _sec_bcd , Ack                                 ' Sekunden
104
    I2crbyte _min_bcd , Ack                                 ' Minuten
105
    I2crbyte _hour_bcd , Ack                                ' Stunden
106
    I2crbyte _wd , Ack                                      ' Wochentag
107
    I2crbyte _day_bcd , Ack                                 ' Tag
108
    I2crbyte _month_bcd , Ack                               ' Monat
109
    I2crbyte _year_bcd , Nack                               ' Jahr
110
    I2cstop                                                 ' I2C Stop
111
    ' BCD-Zahlen in DEC-Zahlen konvertieren
112
    _sec = Makedec(_sec_bcd) : _min = Makedec(_min_bcd) : _hour = Makedec(_hour_bcd)
113
    _day = Makedec(_day_bcd) : _month = Makedec(_month_bcd) : _year = Makedec(_year_bcd)
114
    Return
115
116
    ' Datum schreiben
117
    Setdate:
118
    ' DEC-Zahlen in BCD-Zahlen konvertieren
119
    _day_bcd = Makebcd(_day) : _month_bcd = Makebcd(_month) : _year_bcd = Makebcd(_year)
120
    ' Daten in DS1307 schreiben
121
    I2cstart                                                ' I2C Start
122
    I2cwbyte Ds1307w                                        ' Adresse zum schreiben senden
123
    I2cwbyte &H03                                           ' Registeradresse senden
124
    I2cwbyte _wd                                            ' Wochentag
125
    I2cwbyte _day_bcd                                       ' Tag
126
    I2cwbyte _month_bcd                                     ' Monat
127
    I2cwbyte _year_bcd                                      ' Jahr
128
    I2cstop                                                 ' I2C Stop
129
    Return
130
131
    ' Uhrzeit schreiben
132
    Settime:
133
    ' DEC-Zahlen in BCD-Zahlen konvertieren
134
    _sec_bcd = Makebcd(_sec) : _min_bcd = Makebcd(_min) : _hour_bcd = Makebcd(_hour)
135
    ' Daten in DS1307 schreiben
136
    I2cstart                                                ' I2C Start
137
    I2cwbyte Ds1307w                                        ' Adresse zum schreiben senden
138
    I2cwbyte &H00                                           ' Registeradresse senden
139
    I2cwbyte _sec_bcd                                       ' Sekunden
140
    I2cwbyte _min_bcd                                       ' Minuten
141
    I2cwbyte _hour_bcd                                      ' Stunden
142
    I2cstop                                                 ' I2C Stop
143
    Return
144
145
    Enable_sqw:                                             'sqw ausgang auf 1hz setzten
146
    I2cstart
147
    'I2cwbyte Ds1307w                                        ' Adresse zum schreiben senden
148
    I2cwbyte &HD0
149
    I2cwbyte 7
150
    I2cwbyte &B00010000                                     'ausgang sqw einschalten (bit4) und ausgangsfrequenz wählen (bit0&1)
151
    I2cstop
152
    Return
153
154
155
   Ds1307_int:
156
   Incr Seczaehler
157
   Return

von Thomas F. (igel)


Lesenswert?


von Sebastian (Gast)


Lesenswert?

Hi
interessanter Hinweis, der leider keine Besserung brachte.

von Sebastian (Gast)


Lesenswert?

selbst wenn ich andere quellcodes aus dem internet probiere funktioniert 
es nicht. es wird alles auf dem display angezeigt, nur die uhr bleibt 
bei 00.00.00 stehen. das datum genauso.
woran kann ich denn erkennen, dass der uC überhaupt mit dem ds1307 
kommuniziert?

von Joachim R. (jorath)


Lesenswert?

Nabend,

Bascom ist nicht meine Welt, aber schau dir mal die Funktion vom Bit 
"CH"
im Register 00 an.
Datenblatt Seite 8.

Desweiteren sollten die Statusmeldungen der I2C Funktionen ausgewertet 
werden, alles andere ist Blinflug.

MfG

von BoomBoomMagic (Gast)


Lesenswert?

Deine IF-Anweisung ist so nicht richtig nutzbar.

>If _day = 1 And _month = 1 And _year = 0 Then           ' 01.01.00 = keine Daten

Der RTC arbeitet ja mit BCD-Werten.
Ein frischer RTC hat demnach nicht 0 oder 1, sondern 255er Werte im 
Speicher.
255 ist ja dezimal , du bekomst jedoch BCD 001001010101

Da also deine IF-Anweisung nie durchlaufen wird , wird somit auch das 
Controlregister nicht gesetzt , was am Ende eine unvollständige 
Initialisierung ist.


Auch deine LCD Ausgabe ist äußerst suboptimal mit dem ständigen CLS
Da das Format in der Länge immer gleich ist, reicht ein 
Aktualisieren/Überschreiben völlig aus - ich nehm an das dein Display 
derzeit schön sekundenweise flackert.

von Sebastian (Gast)


Lesenswert?

ja, das habe ich eben schon ausprobiert. mit
1
I2cstart                    
2
I2cwbyte Ds1307w                                            
3
I2cwbyte &H00
4
I2cwbyte &B00000000
5
I2cstop

habe ich das bit auf "0" gesetzt. wie schon gesagt funktioniert das 
leider immer noch nicht.

wie meinst du das mit den staturmeldungen? bin bei i2c noch nicht so 
ganz fit ;)

von Sebastian (Gast)


Lesenswert?

BoomBoomMagic schrieb:
> Deine IF-Anweisung ist so nicht richtig nutzbar.
>
>>If _day = 1 And _month = 1 And _year = 0 Then           ' 01.01.00 = keine Daten
>
> Der RTC arbeitet ja mit BCD-Werten.
> Ein frischer RTC hat demnach nicht 0 oder 1, sondern 255er Werte im
> Speicher.
> 255 ist ja dezimal , du bekomst jedoch BCD 001001010101
>
> Da also deine IF-Anweisung nie durchlaufen wird , wird somit auch das
> Controlregister nicht gesetzt , was am Ende eine unvollständige
> Initialisierung ist.
>
> Auch deine LCD Ausgabe ist äußerst suboptimal mit dem ständigen CLS
> Da das Format in der Länge immer gleich ist, reicht ein
> Aktualisieren/Überschreiben völlig aus - ich nehm an das dein Display
> derzeit schön sekundenweise flackert.

Danke für den Hinweis, werde ich gleich mal nachgucken;) ja flackern tut 
das display momentan, habe aber die anzeige nur schnell dahin getippt, 
wollte erstmal nur die uhr wieder zum laufen bringen. komischerweise hat 
es auch mit der if-bedingung auf meinem atmega8 so funktioniert
gruß sebastian

von BoomBoomMagic (Gast)


Lesenswert?

Jetzt seh ich gerade erst welchen RTC du nutzt  ..... hatte erst DS1337 
gelesen ,
Deiner ist ja nur der DS1307 ;-)

Da ist die Initialisierung eh völlig falsch , da du ja nicht das BIT7 
gesetzt hast , das der RTC loslegen soll

&B10000000  - ohne SQW

&B10010000 -  mit SQW

von Sebastian (Gast)


Lesenswert?

quatsch, die variablen in der if-bedingung sind in der funktion 
"getdatetime" doch schon aus dem bcd-wert abgewandelt worden

von Sebastian (Gast)


Lesenswert?

BoomBoomMagic schrieb:
> Jetzt seh ich gerade erst welchen RTC du nutzt  ..... hatte erst
> DS1337
> gelesen ,
> Deiner ist ja nur der DS1307 ;-)
>
> Da ist die Initialisierung eh völlig falsch , da du ja nicht das BIT7
> gesetzt hast , das der RTC loslegen soll
>
> &B10000000  - ohne SQW
>
> &B10010000 -  mit SQW

also du meinst
1
I2cstart
2
    I2cwbyte Ds1307w
3
    I2cwbyte &H07
4
    I2cwbyte &B10010000
5
    I2cstop

?

funzt leider auch nicht :(

von BoomBoomMagic (Gast)


Lesenswert?

Ich habe von diesen DS1307 und DS1337 hunderte programmiert  ....
guck Dir mal den Code auf dieser Seite an wie dort Initialisiert wurde.
Das ist eines von vielen vielen Beispielen .

http://hühnerklappe-diy.de/zeitschaltuhr.html

Der Code ist zwar mit Eingabe und weiteren Funktionen , spielt aber 
keinen Walzer , geht ja nur um die Initialisierung.

von BoomBoomMagic (Gast)


Lesenswert?

Sebastian schrieb:
> quatsch, die variablen in der if-bedingung sind in der funktion
> "getdatetime" doch schon aus dem bcd-wert abgewandelt worden


auch dann sind die Werte bei einem frischen RTC niemals 1

von Sebastian (Gast)


Lesenswert?

hmm, ich erkenne in der initialisierung zu deinem programm da nicht 
wirklich einen unterschied. vllt erklärst du ihn mir ja mal etwas 
genauer

mein programm kann an sich ja nicht so falsch sein, sonst hätte es auf 
dem anderen controller doch gar nicht funktioniert oder sehe ich das 
falsch? wenn doch wo liegt der unterschied, außer das ich die taktrate 
und ein paar pins an den anderen uC angepasst habe...? habe mittlerweile 
auch schon 3 andere codes aus dem internet probiert, bei allen die 
gleichen symptome. also muss das problem doch eigentlich ein viel 
grundlegenderes sein?

gruß sebastian

von Sebastian (Gast)


Lesenswert?

gibt es eine möglichkeit wie ich sehen kann, ob uC und ds1307 mit 
einander kommunizieren? oszi hab ich keins hier.

von BoomBoomMagic (Gast)


Lesenswert?

Mal eine ganz banale Frage am Rande  .....
hast Du auch die 3V Batterie/Knopfzelle am DS1307 angeschlossen ?
Sind die beiden Pullups (4K7) an den Pins SCK + SDA ?

von BoomBoomMagic (Gast)


Lesenswert?

Sebastian schrieb:
> hmm, ich erkenne in der initialisierung zu deinem programm da nicht
> wirklich einen unterschied. vllt erklärst du ihn mir ja mal etwas
> genauer

Naja, .... der Code ist jetzt allgemein äußerst unglücklich ausgedacht.
Du hast eine DO LOOP in der alle 200ms mittels GETDATETIME vom RTC
die Zeit ausgelesen wird.
Dann nutzt du INT0 um vom RTC das SQW als Sekundenzähler nehmen zu 
können.
Somit würde nach 5x GETDATETIME ein Konflikt entstehen , da 
codetechnisch der Aufruf GETDATETIME kommt und per SQW ein Interrupt 
anliegt.

Wobei  .... ALLE Pins am RTC sind aktiv low !
Das heißt sie werden alle mittels 4K7 Pullup auf high gesetzt.
Demnach müßte dein INT auf Falling reagieren , nicht auf Rising.


Zur Initialisierung gehört zum Einen das das Bit 7 vom Controlregister 
auf 1 gesetzt wird um den internen Takt des RTC zu aktivieren , zum 
Anderen auch das Bit 4 um den SQW Ausgang aktiv zu schalten.
Desweiteren muß das Bit 7 der Sekunden auf 0 gesetzt sein und gesendet 
werden.
Das erfolgt in der Regel , in dem man pauschal eine Zeit beim Starten 
vorgibt.

DU liest ja gleich aus , da passiert ja so nix.
Grammatisch ist das ja alles soweit ok, nur ..... es ist halt einfach 
nicht rund ...
wenn dann noch die externe Beschaltung nicht korrekt ist , hakt es an 
verschiedene Ecken.

von güst (Gast)


Angehängte Dateien:

Lesenswert?

Sebastian schrieb:
> Config Sda = Portc.1
> Config Scl = Portc.0

da es auf einem mega8 lief, schau mal ob im BASCOM auch diese Ports so 
in der IDE angegeben sind, bei mir waren andere Ports eingestellt ergo 
RTC funzt nicht, nach der korrektur alles ok.

von Pete K. (pete77)


Lesenswert?

Sebastian schrieb:
> gibt es eine möglichkeit wie ich sehen kann, ob uC und ds1307 mit
> einander kommunizieren? oszi hab ich keins hier.

Ja, in dem Du die Rückgabewerte Deiner Funktionsaufrufe überprüfst.
Also nicht nur
     tuwas()
sondern eher so:
     if (tuwas()) errorhandling()

Voraussetzung: tuwas() gibt bei Erfolg eine 0 zurück, bei Mißerfolg !=0
Errorhandling kann man dann z.B. über eine RS232 Ausgabe auf den PC 
machen oder einfach eine LED an einem Port anschalten.

Hast Du auch die DS1307 nach Datenblatt beschaltet? Liegt Strom an? 
I2C-Adresse der DS1307 korrekt eingetragen?

Wenn die DS1307 hardwaremäßig nicht korrekt läuft dann sollte das 
I2cstart eine Fehlermeldung zurückgeben.

von BoomBoomMagic (Gast)


Lesenswert?

Mal ne andere Frage :

Warum bist du vom mega8 auf nen mega164 umgestiegen ?
Laut Code ist ja nur ein 20X2 Display dran und ein RTC.

von Sebastian (Gast)


Lesenswert?

Pete K. schrieb:
> lg eine 0 zurück, bei Mißerfolg !=0
> Errorhandling kann man dann z.B. über eine RS232 Ausgabe auf den PC
> machen oder einfach eine LED an einem Port anschalten.
>
> Hast Du auch die DS1307 nach Datenblatt beschaltet? Liegt Strom an?
> I2C-Adresse der DS1307 korrekt eingetragen?
>
> Wenn die DS1307 hardwaremäßig nicht korrekt läuft dann sollte das
> I2cstart eine Fehlermeldung zurückgeben.

danke, aber das wäre jetzt zu einfach gewesen;)

Pete K. schrieb:
> Sebastian schrieb:
>> gibt es eine möglichkeit wie ich sehen kann, ob uC und ds1307 mit
>> einander kommunizieren? oszi hab ich keins hier.
>
> Ja, in dem Du die Rückgabewerte Deiner Funktionsaufrufe überprüfst.
> Also nicht nur
>      tuwas()
> sondern eher so:
>      if (tuwas()) errorhandling()
>
> Voraussetzung: tuwas() gibt bei Erfolg eine 0 zurück, bei Mißerfolg !=0
> Errorhandling kann man dann z.B. über eine RS232 Ausgabe auf den PC
> machen oder einfach eine LED an einem Port anschalten.
>
> Hast Du auch die DS1307 nach Datenblatt beschaltet? Liegt Strom an?
> I2C-Adresse der DS1307 korrekt eingetragen?
>
> Wenn die DS1307 hardwaremäßig nicht korrekt läuft dann sollte das
> I2cstart eine Fehlermeldung zurückgeben.

ah, interessant. die interne Variabel ERR liefert aber "0" also "kein 
Fehler zurück"

BoomBoomMagic schrieb:
> Sebastian schrieb:
>> hmm, ich erkenne in der initialisierung zu deinem programm da nicht
>> wirklich einen unterschied. vllt erklärst du ihn mir ja mal etwas
>> genauer
>
> Naja, .... der Code ist jetzt allgemein äußerst unglücklich ausgedacht.
> Du hast eine DO LOOP in der alle 200ms mittels GETDATETIME vom RTC
> die Zeit ausgelesen wird.
> Dann nutzt du INT0 um vom RTC das SQW als Sekundenzähler nehmen zu
> können.
> Somit würde nach 5x GETDATETIME ein Konflikt entstehen , da
> codetechnisch der Aufruf GETDATETIME kommt und per SQW ein Interrupt
> anliegt.
>
> Wobei  .... ALLE Pins am RTC sind aktiv low !
> Das heißt sie werden alle mittels 4K7 Pullup auf high gesetzt.
> Demnach müßte dein INT auf Falling reagieren , nicht auf Rising.
>
> Zur Initialisierung gehört zum Einen das das Bit 7 vom Controlregister
> auf 1 gesetzt wird um den internen Takt des RTC zu aktivieren , zum
> Anderen auch das Bit 4 um den SQW Ausgang aktiv zu schalten.
> Desweiteren muß das Bit 7 der Sekunden auf 0 gesetzt sein und gesendet
> werden.
> Das erfolgt in der Regel , in dem man pauschal eine Zeit beim Starten
> vorgibt.
>
> DU liest ja gleich aus , da passiert ja so nix.
> Grammatisch ist das ja alles soweit ok, nur ..... es ist halt einfach
> nicht rund ...
> wenn dann noch die externe Beschaltung nicht korrekt ist , hakt es an
> verschiedene Ecken.

den interrupt und SQW habe ich vorerst komplett abgeschaltet um den von 
dir beschriebenen konflikt erstmal auszugrenzen. Die benötigten bits 
werden alle gesetzt. wie genau meinst du

> Das erfolgt in der Regel , in dem man pauschal eine Zeit beim Starten
> vorgibt.
>
> DU liest ja gleich aus , da passiert ja so nix.

?

BoomBoomMagic schrieb:
> Mal eine ganz banale Frage am Rande  .....
> hast Du auch die 3V Batterie/Knopfzelle am DS1307 angeschlossen ?
> Sind die beiden Pullups (4K7) an den Pins SCK + SDA ?

Batterie ist dran und 4k7 pullups an sck, sda und sqw

Danke schonmal für weitere hilfe, auch wenn es immer noch nicht 
funktioniert habe ich immerhin dank euch schon ein paar nützliche sachen 
dazu gelernt;)
gruß sebastian

von Sebastian (Gast)


Lesenswert?

BoomBoomMagic schrieb:
> Mal ne andere Frage :
>
> Warum bist du vom mega8 auf nen mega164 umgestiegen ?
> Laut Code ist ja nur ein 20X2 Display dran und ein RTC.

für mein neues projekt brauchte ich ne HW-PWM mehr, mehr speicher und 
nen weiteren port ;)
wie gesagt weil die uhr als nicht läuft hab ich den quellcode erstmal 
nur darauf beschränkt, damit nicht möglicherweise noch der rest vom 
programm bei der fehlersuche mitspielt. für die rtc alleine hätte ich 
natürlich beim m8 bleiben können

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
Noch kein Account? Hier anmelden.