Forum: Mikrocontroller und Digitale Elektronik DS 1307 Register defekt? Programmfehler ?


von Marcel B. (gigi)


Lesenswert?

Hallo zusammen,

habe eine Uhr auf einem Atmega 8 programmiert die auch einige Zeit 
funktionierte.

Nun habe ich den Code der Übersicht wegen geändert und kann nun keine 
Zeit mehr auslesen, jedoch das Datum.

Anezige ist in etwa so :
1
[                ]
2
[ Datum: 21. 8.18]

Das Display bleibt in der ersten Zeile leer.
Komischerweise geht das Datum obwohl die Funktionen quasi identisch 
sind.
Zweites Problem:
Falls jemand weiss, wie ich die 0 auch als 0 anzeigen kann, würde ich 
mich über einen Tipp freuen.



Kann mir da jemand weiterhelfen ?

Vwerwendet werden die Libs von P. Fleury

Das Programm sieht so aus:
1
/*
2
 * LCD TWI.c
3
 *
4
 * Created: 20.08.2018 18:09:52
5
 * Author : Gigi
6
 */ 
7
#define F_CPU 8000000UL
8
#define Ds1307 0xD0  // DS1307 ID
9
10
#include <avr/io.h>
11
#include <stdio.h>
12
#include <util/delay.h>
13
#include "i2cmaster.h"
14
#include "lcd-routines.h"
15
16
17
void RTC_Init();
18
void RTC_GetDateTime();
19
void RTC_SetDateTime();
20
void clock_continue();
21
22
23
unsigned char sec, min, hour, weekDay, date, month,  year;
24
char zeit[32];
25
char datum[32];
26
27
int main() 
28
{
29
    lcd_init();
30
  RTC_Init();
31
  _delay_ms(5);
32
  
33
  hour = 0x20;   
34
    min =  0x51;
35
    sec =  0x00;
36
    date = 0x20; 
37
    month = 0x08;
38
    year = 0x18;
39
    weekDay = 1;
40
  _delay_ms(5);
41
  RTC_SetDateTime();
42
  _delay_ms(5); 
43
  _delay_ms(5);
44
  
45
    while(1)
46
    {  
47
        printf(zeit,"Zeit: %2x:%2x:%2x",hour,min,sec);
48
        lcd_setcursor(0,1);
49
    lcd_string(zeit); 
50
    sprintf(datum,"Datum: %2x.%2x.%2x",date,month,year);
51
    lcd_setcursor(0,2);
52
        lcd_string(datum);
53
    }
54
    return (0);
55
}
56
57
void RTC_Init(void)
58
{
59
  i2c_init();    
60
  i2c_start(Ds1307+I2C_WRITE);                           // Initialize the I2c module.
61
  
62
  i2c_write(0x07);            // Select the Ds1307 ControlRegister to configure Ds1307
63
  
64
  i2c_write(0x00);                        // Write 0x00 to Control register to disable SQW-Out
65
  
66
  i2c_stop();                             // Stop I2C communication after initializing DS1307
67
}
68
69
void RTC_SetDateTime()
70
{
71
  i2c_start(Ds1307+I2C_WRITE);                           // Start I2C communication
72
  
73
  i2c_write(0x00); // Request sec RAM address at 00H
74
  
75
  
76
  i2c_write(sec);                    // Write sec from RAM address 00H
77
  i2c_write(min);                    // Write min from RAM address 01H
78
  i2c_write(hour);                    // Write hour from RAM address 02H
79
  i2c_write(weekDay);                // Write weekDay on RAM address 03H
80
  i2c_write(date);                    // Write date on RAM address 04H
81
  i2c_write(month);                    // Write month on RAM address 05H
82
  i2c_write(year);                    // Write year on RAM address 06h
83
  
84
  i2c_stop();                              // Stop I2C communication after Setting the Date
85
}
86
87
void RTC_GetDateTime()
88
{
89
                            // Start I2C communication
90
  
91
  i2c_start(Ds1307+I2C_WRITE);        // connect to DS1307 by sending its ID on I2c Bus
92
  i2c_write(0x00);          // Request Sec RAM address at 00H
93
  i2c_stop();                         // Stop I2C communication after selecting Sec Register
94
  
95
                               
96
  i2c_start(Ds1307+I2C_READ);            // connect to DS1307(Read mode) by sending its ID
97
  
98
  sec = i2c_read(1);                // read second and return Positive ACK
99
  min = i2c_read(1);                 // read minute and return Positive ACK
100
  hour= i2c_read(1);               // read hour and return Negative/No ACK
101
  weekDay = i2c_read(1);           // read weekDay and return Positive ACK
102
  date= i2c_read(1);              // read Date and return Positive ACK
103
  month=i2c_read(1);            // read Month and return Positive ACK
104
  year =i2c_read(0);             // read Year and return Negative/No ACK
105
  i2c_stop();                              // Stop I2C communication after reading the Date
106
}
107
108
void clock_continue()
109
{
110
  _delay_ms(1000);
111
  sec ++;                
112
  if (sec == 0x3B) {_delay_ms(1000); min ++; sec = 0x00;}
113
  if (min == 0x3B && sec == 0x3B) {_delay_ms(1000);  RTC_GetDateTime();}  
114
}

: Bearbeitet durch User
von Heinz R. (Gast)


Lesenswert?

1
 while(1)
2
    {  
3
        printf(zeit,"Zeit: %2x:%2x:%2x",hour,min,sec);

versuch mal sprintf(), wie die Zeile drunter beim Datum

von Marcel B. (gigi)


Lesenswert?

Oh Mann!

Vielen lieben Dank!
Das "s" muss mir abhanden gekommen sein!

LG,
Marcel

von Marcel B. (gigi)


Lesenswert?

Gut, das Porgramm läuft jetzt.

Allerdings bekomme ich die Zahlen nicht vernünftig ausgegeben, bei jedem 
Überlauf der Sekunden zählt er in Buchstaben weiter.

Wie löst man dieses Problem am besten ?

von guest (Gast)


Lesenswert?

Marcel B. schrieb:
> Allerdings bekomme ich die Zahlen nicht vernünftig ausgegeben, bei jedem
> Überlauf der Sekunden zählt er in Buchstaben weiter.
>
> Wie löst man dieses Problem am besten ?

Was erwartest Du?
Du gibst sämtliche Werte hexadezimal aus und wunderst Dich dann über 
Buchstaben in der Ausgabe?

von hohesC (Gast)


Lesenswert?

Marcel B. schrieb:
> Gut, das Porgramm läuft jetzt.
>
> Allerdings bekomme ich die Zahlen nicht vernünftig ausgegeben, bei jedem
> Überlauf der Sekunden zählt er in Buchstaben weiter.
>
> Wie löst man dieses Problem am besten ?

d, i   int as a signed decimal number. %d and %i are synonymous for 
output, but are different when used with scanf() for input (where using 
%i will interpret a number as hexadecimal if it's preceded by 0x, and 
octal if it's preceded by 0.)

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Marcel B. schrieb:
> Wie löst man dieses Problem am besten ?
1
 if (sec == 0x3B) {_delay_ms(1000); min ++; sec = 0x00;}
2
3
//*** Wie soll das unten jemals wahr werden ?
4
 if (min == 0x3B && sec == 0x3B) {_delay_ms(1000);  RTC_GetDateTime();}

von Marcel B. (gigi)


Lesenswert?

Nicht wirklich, die Werte werden ja trotz Hex-Ausgabe (%2x) vernünftig 
als Zahl ausgegeben, nach dem lesen der RTC.

Und das Obwohl sie im BCD Format sind.
Da ist gerade mein Verständnisproblem.

Gebe ich die zahlen als INT aus, kommen von anfang an nur falsche Daten 
heraus.

Nach dem auslesen stimmt alles, aber wie zähle ich das manuell hoch ?

von guest (Gast)


Lesenswert?

Marcel B. schrieb:
> Falls jemand weiss, wie ich die 0 auch als 0 anzeigen kann, würde ich

Was meinst Du damit? Willst Du die Zahlen zweistellig mit gegebenenfalls 
führender Null ausgeben? Falls ja, dann schreib das doch einfach mit in 
Deine Formatanweisungen rein. Wie steht in der entsprechenden 
Dokumentation, z.B. der hier:
http://www.cplusplus.com/reference/cstdio/printf/

von Marcel B. (gigi)


Lesenswert?

Marc V. schrieb:
> Marcel B. schrieb:
>> Wie löst man dieses Problem am besten ?
>
>
1
>  if (sec == 0x3B) {_delay_ms(1000); min ++; sec = 0x00;}
2
> 
3
> //*** Wie soll das unten jemals wahr werden ?
4
>  if (min == 0x3B && sec == 0x3B) {_delay_ms(1000);  RTC_GetDateTime();}
5
>

0x3B = 59. Die Zahlen sind eh Binär gespeichert, also ist die Art, wie 
ich vergleiche egal.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Marcel B. schrieb:
> 0x3B = 59. Die Zahlen sind eh Binär gespeichert, also ist die Art, wie
> ich vergleiche egal.

 Uninteressant.
 In der Zeile davor hast du sec auf 0 gestellt, falls sec == 0x3B.
 Wie kann sec dann in der Zeile darunter wieder 0x3B sein ?

: Bearbeitet durch User
von guest (Gast)


Lesenswert?

Marcel B. schrieb:
> 0x3B = 59.

Und warum schreibst Du dann nicht einfach gleich 59 hin?
Allerdings hast Du gerade selbst geschrieben, daß die Zahlen im 
BCD-Format sind! Und damit sind Deine Vergleiche dann sowieso ziemlich 
daneben.

Außerdem ging es Marc nicht um die Art des Vergleichs, sondern um die 
Sinnlosigkeit des zweiten 'if', da dieses niemals wahr wird.

Btw. Daß Dein obiges Programm überhaupt irgenwie zählen soll kann ich 
auch nicht so recht glauben. Dein 'clock_continue' wird ja nirgends 
aufgerufen.

von Marcel B. (gigi)


Lesenswert?

Das habe ich bereits aufgerufen,
habe es zum Test des ersten Problems im Startbeitrag rausgenommen.

Was hier falsch ist, sehe ich auch, aber eine Lösung habe ich nicht, 
darum würde ich mir sehr über Tipps diesbezüglich freuen.

guest schrieb:
> Außerdem ging es Marc nicht um die Art des Vergleichs, sondern um die
> Sinnlosigkeit des zweiten 'if', da dieses niemals wahr wird.

Danke, ein Problem weniger.

Wie inkrementiere ich denn BCD manuell ?

: Bearbeitet durch User
von Frank _. (fbi)


Lesenswert?

Marcel B. schrieb:
> Wie inkrementiere ich denn BCD manuell ?

Addieren und auf Überlauf prüfen, halt genau wie mit Deinen Sekunden und 
Minuten, nur für die einzelnen Dezimalstellen.

Deutlich einfacher wäre es allerdings die Werte in 'RTC_GetDateTime' 
gleich von BCD ins normale Format zu wandeln. Das würde Dir die ganzen 
Klimmzüge mit dem BCD ersparen (in 'RTC_SetDateTime' dann natürlich 
wieder zurück nach BCD).

Z.B. so:
1
uint8_t tmp = i2c_read(1);
2
sec = ( ( tmp >> 4 ) * 10 ) + ( tmp & 0x0f );
bzw.
1
uint8_t tmp = ( ( sec / 10 ) << 4 ) | ( sec % 10 );
2
i2c_write(tmp);

von guest (Gast)


Lesenswert?

Marcel B. schrieb:
> Das habe ich bereits aufgerufen,
> habe es zum Test des ersten Problems im Startbeitrag rausgenommen.

Wo denn normalerweise? Innerhalb von 'while(1)' in 'main'? Dann hast Du 
durch die unterschiedlichen Laufzeiten von 'clock_continue' ein 
Anzeigeproblem. Du wirst z.B. nie einen Sekundenwert von 59 zu Gesicht 
bekommen, Deine Anzeige springt von 58 auf 0. Besser mit 60 vergleichen 
und die zusätzlichen '_delay_ms' wegwerfen. Also so in etwa:
1
void clock_continue()
2
{
3
  _delay_ms(1000);
4
  sec++;                
5
  if(sec == 60)
6
  {
7
    sec = 0;
8
    min++;
9
  }
10
  if(min == 60)
11
  {
12
    min = 0;
13
    RTC_GetDateTime();
14
  }
15
}

von Marcel B. (gigi)


Lesenswert?

Danke Euch beiden,
das werde ich direkt mal ausprobieren. :)

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.