Forum: Mikrocontroller und Digitale Elektronik I2C Real Time Clock/Calendar (DS1337


von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Hi,

ich habe hier einen ISL12057 im Betrieb.

• Pin Compatible to Maxim DS1337
• Functionally Equivalent to Maxim DS1337

Dabei setze ich erfolgreich eine Zeit mittels:
1
// DS1307 RTC ROUTINES
2
#define DS1307 0xD0 // I2C bus address of DS1307 RTC
3
#define SECONDS_REGISTER 0x00
4
#define MINUTES_REGISTER 0x01
5
#define HOURS_REGISTER 0x02
6
#define DAYOFWK_REGISTER 0x03
7
#define DAYS_REGISTER 0x04
8
#define MONTHS_REGISTER 0x05
9
#define YEARS_REGISTER 0x06
10
#define CONTROL_REGISTER 0x07
11
#define RAM_BEGIN 0x08
12
#define RAM_END 0x3F
13
14
void SetTimeDate()
15
// simple, hard-coded way to set the date.
16
{
17
  I2C_WriteRegister(DS1307, MONTHS_REGISTER, 0x08);
18
  I2C_WriteRegister(DS1307, DAYS_REGISTER, 0x31);
19
  I2C_WriteRegister(DS1307, YEARS_REGISTER, 0x17);
20
  I2C_WriteRegister(DS1307, HOURS_REGISTER, 0x08 + 0x40); // add 0x40 for PM
21
  I2C_WriteRegister(DS1307, MINUTES_REGISTER, 0x51);
22
  I2C_WriteRegister(DS1307, SECONDS_REGISTER, 0x00);
23
}
und lese diese wieder mit:
1
void DS1307_GetTime(uint8_t *hours, uint8_t *minutes, uint8_t *seconds)
2
// returns hours, minutes, and seconds in BCD format
3
{
4
  *hours = I2C_ReadRegister(DS1307, HOURS_REGISTER);
5
  *minutes = I2C_ReadRegister(DS1307, MINUTES_REGISTER);
6
  *seconds = I2C_ReadRegister(DS1307, SECONDS_REGISTER);
7
  if (*hours & 0x40) // 12hr mode:
8
    *hours &= 0x1F; // use bottom 5 bits (pm bit = temp & 0x20)
9
  else
10
    *hours &= 0x3F; // 24hr mode: use bottom 6 bits
11
}

Doch wenn ich mir die Sekunden in einer Endlosschleife auf dem Display 
ausgeben lasse (natürlich frage ich genauso oft den Chip ab), dann 
erhalte ich keine "neue" Uhrzeit. Also der Sekundenzeiger bleibt still.

Die Hardware ist in 20-Facher Ausführung vorhanden und ging auch bereits 
mit einem anderem Chip (closed Source) an den Kunden ohne Reklamation.
Daher gehe ich davon aus, dass dort kein Fehler ist.

Muss ich dem DS1337 noch irgendwie sagen, dass er loslaufen darf/soll?
Ich finde keinerlei Hinweise diesbezüglich im Datenblatt.

Ich danke euch schon mal für eure Mühen. gute Nacht ;)

Oekel

: Verschoben durch User
von Johnny B. (johnnyb)


Lesenswert?

Das ist jetzt keine Antwort auf Deine Frage, aber solltest Du nicht die 
Stunden-, Minuten- und Sekundenregister mit einem einzigen Lesebefehl 
"gleichzeitig" lesen?
Ansonsten kann es zu inkonsistenten Daten kommen; d.h. das z.B. die 
Stunden und Minuten noch zu einer alten Zeit gehören und die Sekunden 
schon zu einer neuen.

Bei Deiner Anwendung ist es vielleicht nicht so kritisch, da es nur jede 
Minute mal vorkommen kann, aber bei schnelleren Angelegenheiten ist 
sowas gar nicht gut.

von Aa B. (aaab)


Lesenswert?

D a v i d K. schrieb:
> Hi,
>
> ich habe hier einen ISL12057 im Betrieb.
>

>
> Doch wenn ich mir die Sekunden in einer Endlosschleife auf dem Display
> ausgeben lasse (natürlich frage ich genauso oft den Chip ab), dann


Ich hoffe dass du die I2C bus alles richtig initialisiert hast, nehme 
mal an, Ja.

> erhalte ich keine "neue" Uhrzeit. Also der Sekundenzeiger bleibt still.
Hast Du
1
*seconds
 in Debugger beobachtet, bleibt der Wert still wenn
1
DS1307_GetTime(&HH,&MM,&SS)
 in main() aufgerufen wird?

: Bearbeitet durch User
von Joachim B. (jar)


Lesenswert?

D a v i d K. schrieb:
> Muss ich dem DS1337 noch irgendwie sagen, dass er loslaufen darf/soll?
> Ich finde keinerlei Hinweise diesbezüglich im Datenblatt.

dem 1307 muss man das jedenfalls sagen beim 1337 habe ich auch nichts 
gefunden

aber das die DS13xx so ungenau sind arbeite ich eh nur noch mit DS3231
1
void DS1307new::stopClock(void)         // set the ClockHalt bit high to stop the rtc
2
{ Wire.beginTransmission(DS1307_ID);
3
  printIIC(0x00);                      // Register 0x00 holds the oscillator start/stop bit
4
  Wire.endTransmission();
5
  Wire.requestFrom(DS1307_ID, 1);
6
  second = readIIC() | 0x80;       // save actual seconds and OR sec with bit 7 (sart/stop bit) = clock stopped
7
  Wire.beginTransmission(DS1307_ID);
8
  printIIC(0x00);
9
  printIIC(second);                    // write seconds back and stop the clock
10
  Wire.endTransmission();
11
}
12
13
void DS1307new::startClock(void)        // set the ClockHalt bit low to start the rtc
14
{ Wire.beginTransmission(DS1307_ID);
15
  printIIC(0x00);                      // Register 0x00 holds the oscillator start/stop bit
16
  Wire.endTransmission();
17
  Wire.requestFrom(DS1307_ID, 1);
18
  second = readIIC() & 0x7f;       // save actual seconds and AND sec with bit 7 (sart/stop bit) = clock started
19
  Wire.beginTransmission(DS1307_ID);
20
  printIIC(0x00);
21
  printIIC(second);                    // write seconds back and start the clock
22
  Wire.endTransmission();
23
}

: Bearbeitet durch User
von Hurra (Gast)


Lesenswert?

Lies mal "Control Register (0Eh)"

ist EOSC LOW?
Sollte zwar mit LOW initialisiet sein, aber nachprüfen schadet nicht.

Was ist mit "Status Register (0Fh)"
Was sagt OSF? Das muss LOW sein.

Haste einen Quarz dran, schwingt der?

Wenn du einen 1Hz auf den Ausgang schaltest, tut sich was?

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Hurra schrieb:

> ist EOSC LOW?
> Sollte zwar mit LOW initialisiet sein, aber nachprüfen schadet nicht.


Gerade noch mal kontrolliert: JA

Er läuft wohl doch, allerdings viel zu langsam: Das Increment ist so 
alle 40Sekunden.

Also mit MINUTENREGISTER habe ich es definitiv nicht verwechselt, passt 
also auch nicht.
Der Quarz passt auch, es sein denn ihr erzählt mir jetzt, dass man den 
Takt durch zu heißes Löten völlig verändern kann?

Grüße Oekel

von Bastian W. (jackfrost)


Lesenswert?

Hast du die Frequenz mal am SQW Pin mal gemessen ?

Gruß JackFrost

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Bastian W. schrieb:
> Hast du die Frequenz mal am SQW Pin mal gemessen ?
>
> Gruß JackFrost

Scheinbar ist wirklich der Chip oder der Quarz im A****
Andere Platinen zeigen bei gleichem Code das gewünschte Ergebnis.

Habe dennoch etwas aus den Antworten gelernt, daher vielen Dank und 
Entschuldigung für die Umstände.

Grüße Oekel

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Jetzt muss ich doch noch mal stören.
Wieso funktionieren folgende funktion bei Skunden wunderbar, erzeugen 
mir jedoch falsche Berechnungen bei minuten und stunden?
1
static inline int bcd_decimal(uint8_t hex) {
2
  int dec = ((hex & 0xF0) >> 4) * 10 + (hex & 0x0F);
3
  return dec;
4
}
5
static inline int decimal_bcd(uint8_t dec) {
6
  int hex = ((dec / 10) << 4) | (dec % 10);
7
  return hex;
8
}

Angewendet:
1
I2C_WriteRegister(DS1307, MINUTES_REGISTER, decimal_bcd(58));
2
...
3
...
4
void lcd_printInt(uint16_t value, uint8_t c, bool leadingZeros)
5
{
6
  char str[c];
7
  utoa(value, str, 10);
8
  if(leadingZeros)
9
  {
10
11
    for( uint8_t i = getDigitCount(value); i < c; i++)
12
      lcd_print_P(PSTR("0"));
13
  }
14
  lcd_print(str);
15
}
16
...
17
lcd_printInt(bcd_decimal(minutes), 2, true);


Grüße Oekel

von Bastian W. (jackfrost)


Lesenswert?

Hast du die RTC auf 24h gestellt?

Welche Werte hast du für Minuten und Stunden ( BCD als auch dezimal )

Gruß JackFrost

von Hurra (Gast)


Lesenswert?

D a v i d K. schrieb:
> Jetzt muss ich doch noch mal stören.
> Wieso funktionieren folgende funktion bei Skunden wunderbar, erzeugen
> mir jedoch falsche Berechnungen bei minuten und stunden?
>
>
1
> static inline int bcd_decimal(uint8_t hex) {
2
>   int dec = ((hex & 0xF0) >> 4) * 10 + (hex & 0x0F);
3
>   return dec;
4
> }
5
> static inline int decimal_bcd(uint8_t dec) {
6
>   int hex = ((dec / 10) << 4) | (dec % 10);
7
>   return hex;
8
> }
9
>

Das will mir auf den ersten Blick richtig erscheinen.

Eine mögliche Erklärung für das Problem der Stunden findest du im 
Datenblatt auf S8 (Abschnitt Timekeeper Register).

Zumindest bei den Stunden befinden sich im Zeitregister auch Statusbits 
(10/24, AM/PM), die musst man ausmarkieren.
Bei den Minuten kommt mir das komisch vor, da müsste es eine andere 
Erklärung geben. Möglicherweise kann man aber das Bit 7 manuell setzen.

Schau dir die Werte in Hex an, die in die Funkion reingehen, und was sie 
zurückliefert. Dann überleg dir auf Papier, wie das zustandekokmmt.

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Hurra schrieb:

> Das will mir auf den ersten Blick richtig erscheinen.
>
Ich denke auch, dass die Funktionen richtig sind, denn wenn ich mal hin 
UND her konvertiere und es auf dem Display ausgebe, so bekomme ich die 
Zahlen von 00-59 korrekt dargestellt.

Dann habe ich nun noch mal folgendes probiert:
1
for(uint8_t i= 0; i< 60; i++){
2
    lcd_gotolc(1, 1);
3
    I2C_WriteRegister(DS1307, MINUTES_REGISTER, decimal_bcd(i));
4
    DS1307_GetTime(&hours, &minutes, &seconds);
5
    lcd_printBinary(minutes);
6
    lcd_gotolc(2, 1);
7
    lcd_printInt(bcd_decimal(minutes), 2, true);
8
    wait_10ms(50);
9
  }

zuerst natürlich mit sekunden und hatte eine "ständig ändernde" (also 
korrekte) Anzeige.
Das Gleiche 1:1 wie oben abgebildet bleibt zu 90% auf 0b00010100 (10) 
stehen und wechselt 1x auf 0b0010000 hin und zurück.

Ich habe die bitte Vermutung, dass auch dieser Chip defekt ist und ich 
eine ganze Reihe Montagsmodelle bekommen habe.

Kann so etwas sein? Also einzelne Register im A* ? Und wie geht man da 
vor? Ich habe mir 500 Stück davon hingelegt.

Grüße Oekel

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Habe jetzt noch mal 10 weitere Chips ausprobiert und überall das gleiche 
Ergebnis.

Nehmen wir mal folgendes:
1
  for(uint8_t i= 0; i<= 13; i++){
2
    lcd_gotolc(1, 1);
3
    I2C_WriteRegister(DS1307, SECONDS_REGISTER, decimal_bcd(i));
4
    I2C_WriteRegister(DS1307, MINUTES_REGISTER, decimal_bcd(i));
5
    DS1307_GetTime(&hours, &minutes, &seconds);
6
    uint8_t sec = bcd_decimal(seconds);
7
    uint8_t min = bcd_decimal(minutes);
8
    lcd_printBinary(sec);
9
    //lcd_printInt(sec, 2, true);
10
    lcd_gotolc(2, 1);
11
    lcd_printBinary(min);
12
    //lcd_printInt(min, 2, true);
13
    wait_10ms(50);
14
  }
so scheinen beide Register sinnige Werte zu liefern. (Also ich erhalte 
eine binäre Ausgabe für ALLE gewünschten Werte.
Doch kommentiere ich die beiden Zeilen wieder ein, so komme ich bei 
"sec" ans Ziel mit 13 und bei "min" nur bis 10 und erhalte für die 
theorischen 11,12,13 nur 00.

Erhöhe ich die "Stellenanzahl" (=c) für meine Funktion:
1
void lcd_printInt(uint16_t value, uint8_t c, bool leadingZeros)
2
{
3
  char str[c];
4
  utoa(value, str, 10);
5
  if(leadingZeros)
6
  {
7
8
    for( uint8_t i = getDigitCount(value); i < c; i++)
9
      lcd_print_P(PSTR("0"));
10
  }
11
  lcd_print(str);
12
}
 auf 3, so bekomme ich auch die richtigen Werte von 0-59 angezeigt.

Aber wieso ist das so? Wieso klappt die Umwandlung bei Sekunden mit char 
str[2]; und bei Minuten nur mit char str[3];

Zuvor habe ich ja die eingängigen Binärwerte miteinander verglichen und 
auch gleiche Werte erhalten.
Hier noch mal die komplette Funktion dazu:
1
void lcd_printBinary(uint8_t bin){
2
  for(uint8_t i= 0; i< 8; i++){
3
    if(bin & (0b10000000 >> i )){
4
      lcd_print_P(PSTR("1"));
5
    }else{
6
      lcd_print_P(PSTR("0"));
7
    }
8
  }
9
}

Hat Jemand für mich hier noch eine Bahnbrechende Idee, wo ich mich da 
vertue?

Grüße Oekel

: Bearbeitet durch User
von Joachim B. (jar)


Lesenswert?

D a v i d K. schrieb:
> Habe jetzt noch mal 10 weitere Chips ausprobiert und überall das gleiche
> Ergebnis.

und warum nicht DS3231?
war für mich stressfreier.

von Bastian W. (jackfrost)


Lesenswert?

Normal muss doch der String mit \0 terminiert werden. Ggf. überschreibt 
es dir etwas im Speicher bei Minuten und Stunden mit dem \0.

Kannst du den µC debuggen und dir den Speicher vor und nach dem 
beschreiben der Sekunden und Minuten ansehen ?

Gruß JackFrost

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Bastian W. schrieb:

> Kannst du den µC debuggen und dir den Speicher vor und nach dem
> beschreiben der Sekunden und Minuten ansehen ?

Nein, leider keine Debugger-Fähigkeiten (in der Hardware)
Es scheint aber ein ganz anderes Verständnisproblem zu existieren.

Habe jetzt mal 23:58:48 eingestellt und nach 12 Sekunden zeigt er mir 
für eine Minute lang 23:59:00_ an. Ab 00:00:00 zählt er brav Sekunden 
und Minuten hoch.
Lass ihn gerade mal laufen....

Also bis 00:10:00 läuft er durch, danach bewegen sich die Sekunden schon 
wieder nicht. auch bei Minute 11,12,13,14,15...
Gleiche Ergebnis, wenn ich initial einen dieser Werte einstelle.
Also zwischen 00:00:00 - 00:09:59 sehe ich Sekunden, danach nur noch 
Minuten und Stunden. (zB. auch 13:09:00)

: Bearbeitet durch User
von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Jetzt lief das Teil ca 1 Std. und die Sekunden-Werte stehen ebenfalls 
bei 01:01:00, 01:02:00, 01:03:00, ...

Da ist doch irgendwie der Wurm drin. :'(

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

OK, es muss etwas mit dem BCD Format zu tun haben.
Also der Chip funktioniert korrekt, da bin ich mir mittlerweile 100% 
sicher.

Trotzdem zerschieße ich mir irgendwie die Variablen.
Was mich zu dieser Überzeugung bringt, möchte ich mit einigen 
Variationen meines Testcodes darstellen. In der Hoffnung, dass mich 
Jemand von euch erleuchten kann.
(Danke an dieser Stelle für die Geduld und das Lesen)

Als Testausgabe habe ich zwei Displays (7-segment & LCD)
Folgenden Code:
1
void test_Clock() {
2
3
  cli();
4
  uint8_t hours, minutes, seconds, months, days, years;
5
  DS1307_GetTime(&hours, &minutes, &seconds);
6
  //DS1307_GetDate(&years, &months, &days);
7
8
  print_timeAtLine(1, bcd_decimal(hours), bcd_decimal(minutes), bcd_decimal(seconds));
9
10
11
  SS_SetDigits(minutes >> 4, // 10 hour digit
12
    minutes & 0x0F, // 1 hour digit
13
    seconds >> 4, // 10 minute digit
14
    seconds & 0x0F, // 1 minute digit
15
    1); // turn on colon
16
  sei();
17
}
18
19
void print_timeAtLine(uint8_t line, uint8_t hours, uint8_t minutes, uint8_t seconds) {
20
  //____hh:mm:ss____
21
  lcd_gotolc(line, 5);
22
  lcd_printInt(hours, 2, true);
23
  lcd_print_P(PSTR(":"));
24
  lcd_printInt(minutes, 2, true);
25
  lcd_print_P(PSTR(":"));
26
  lcd_printInt(seconds, 2, true);
27
28
}

Ergibt eine korrekte sekündliche Anzeige auf dem 7-Segment, jedoch 
bleiben die Sekunden auf dem LCD bis auf die bereits erwähnten Minunte 
1-9 auf "00".
1
void test_Clock() {
2
3
  cli();
4
  uint8_t hours, minutes, seconds, months, days, years;
5
  DS1307_GetTime(&hours, &minutes, &seconds);
6
  //DS1307_GetDate(&years, &months, &days);
7
8
  print_timeAtLine(1, bcd_decimal(hours), bcd_decimal(minutes), bcd_decimal(seconds));
9
  lcd_gotolc(1, 11);
10
  lcd_printInt(bcd_decimal(seconds), 2, true);
11
  //print_dateAtLine(2, years, months, days);
12
13
  SS_SetDigits(minutes >> 4, // 10 hour digit
14
    minutes & 0x0F, // 1 hour digit
15
    seconds >> 4, // 10 minute digit
16
    seconds & 0x0F, // 1 minute digit
17
    1); // turn on colon
18
  sei();
19
}
20
...

Ergibt eine korrekte Sekundenanzeige auf dem LCD aber auf der 7-Segment 
werden ab Sekunde 10 "04 00" angezeigt. :(

Als weiter Variation habe ich innerhalb der LCD Anzeigefuktion mal an 
sec:sec:sec ausgegeben.
1
void test_Clock() {
2
3
  cli();
4
  uint8_t hours, minutes, seconds, months, days, years;
5
  DS1307_GetTime(&hours, &minutes, &seconds);
6
  //DS1307_GetDate(&years, &months, &days);
7
8
  print_timeAtLine(1, bcd_decimal(hours), bcd_decimal(minutes), bcd_decimal(seconds));
9
  //lcd_gotolc(1, 11);
10
  //lcd_printInt(bcd_decimal(seconds), 2, true);
11
  //print_dateAtLine(2, years, months, days);
12
13
  SS_SetDigits(minutes >> 4, // 10 hour digit
14
    minutes & 0x0F, // 1 hour digit
15
    seconds >> 4, // 10 minute digit
16
    seconds & 0x0F, // 1 minute digit
17
    1); // turn on colon
18
  sei();
19
}
20
21
void print_timeAtLine(uint8_t line, uint8_t hours, uint8_t minutes, uint8_t seconds) {
22
  //____hh:mm:ss____
23
  lcd_gotolc(line, 5);
24
  lcd_printInt(seconds, 2, true);
25
  lcd_print_P(PSTR(":"));
26
  lcd_printInt(seconds, 2, true);
27
  lcd_print_P(PSTR(":"));
28
  lcd_printInt(seconds, 2, true);
29
30
}

Dies bewirkt wie erwartet auf dem LCD eine 3 fach korrekte Anzeige, doch 
steht dann auf dem 7-Segment plötzlich "00 04" bei allen Sekunden größer 
9.

Ist meine printInt denn vielleicht so verkorkst, dass sie etwas 
verrücktes anstellt? Wir sind doch aber eigentlich hier bei C und 
primitiven Datentypen stehts bei Call-By-Value, oder?
1
void lcd_printInt(uint16_t value, uint8_t c, bool leadingZeros)
2
{
3
  char str[c];
4
  utoa(value, str, 10);
5
  if(leadingZeros)
6
  {
7
8
    for( uint8_t i = getDigitCount(value); i < c; i++)
9
      lcd_print_P(PSTR("0"));
10
  }
11
  lcd_print(str);
12
}

Wie könnte ich es komplett zum laufen bekommen bzw. noch detailierter 
debuggen (ohne JTAG nur per Printausgabe/Try-And-Error)?

Grüße Oekel

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

D a v i d K. schrieb:

> Ist meine printInt denn vielleicht so verkorkst, dass sie etwas
> verrücktes anstellt? Wir sind doch aber eigentlich hier bei C und
> primitiven Datentypen stehts bei Call-By-Value, oder?
>
>
1
> void lcd_printInt(uint16_t value, uint8_t c, bool leadingZeros)
2
> {
3
>   char str[c];
4
>   utoa(value, str, 10);
5
>   if(leadingZeros)
6
>   {
7
> 
8
>     for( uint8_t i = getDigitCount(value); i < c; i++)
9
>       lcd_print_P(PSTR("0"));
10
>   }
11
>   lcd_print(str);
12
> }
13
>
1
...
2
void lcd_print(char *string) {
3
4
  while(*string)  {
5
    lcd_putchar(*string++);
6
  }
7
}

schneller Nachtrag: scheinbar ist diese Funktion wirklich schuld, denn 
bei
1
void print_timeAtLine(uint8_t line, uint8_t hours, uint8_t minutes, uint8_t seconds) {
2
  //____hh:mm:ss____
3
//  lcd_gotolc(line, 5);
4
//  lcd_printInt(hours, 2, true);
5
//  lcd_print_P(PSTR(":"));
6
//  lcd_printInt(minutes, 2, true);
7
//  lcd_print_P(PSTR(":"));
8
//  lcd_printInt(seconds, 2, true);
9
10
  lcd_gotolc(1, 1);
11
  lcd_printBinary(hours);
12
  lcd_gotolc(2, 1);
13
  lcd_printBinary(minutes);
14
  lcd_printBinary(seconds);
15
16
}
Bleibt die 7-Segmentanzeige "sauber" und die Binärwerte laufen auf dem 
LCD munter stetig weiter.

Trotzdem sehe ich den Fehler leider nicht.
Verwende ich "utoa" falsch? Oder hat diese evtl. Seiteneffekte, welche 
ich nicht berücksichtige?

PS: sollte ich einen neuen Thread starten, da es mit dem eigentlichen 
Problem ja nichts mehr zu tun hat. Bzw. das eigentliche Problem ganz 
woanders als in der Überschrift liegt.

: Bearbeitet durch User
von eProfi (Gast)


Lesenswert?

Versuche doch einfach mal:
void lcd_printInt(uint16_t value, uint8_t c, bool leadingZeros){
  lcd_print(value/10);
  lcd_print(value%10);
}

von eProfi (Gast)


Lesenswert?

Korrektur: print erwartet einen String, das geht nicht.
1
void print_timeAtLine(uint8_t line, uint8_t h, uint8_t m, uint8_t s){
2
  //____hh:mm:ss____
3
  lcd_gotolc(line, 5);
4
  lcd_putch('0'+h/10);lcd_putch('0'+h%10);lcd_putch(':');
5
  lcd_putch('0'+m/10);lcd_putch('0'+m%10);lcd_putch(':');
6
  lcd_putch('0'+s/10);lcd_putch('0'+s%10);
7
}

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

eProfi schrieb:

>
1
> void print_timeAtLine(uint8_t line, uint8_t h, uint8_t m, uint8_t s){
2
>   //____hh:mm:ss____
3
>   lcd_gotolc(line, 5);
4
>   lcd_putch('0'+h/10);lcd_putch('0'+h%10);lcd_putch(':');
5
>   lcd_putch('0'+m/10);lcd_putch('0'+m%10);lcd_putch(':');
6
>   lcd_putch('0'+s/10);lcd_putch('0'+s%10);
7
> }
8
>

das funktioniert in der Tat wunderbar. Vielen DANK!

Wie stehen denn die Chancen den Fehler in meinem lcd_printInt(...) zu 
finden?
Workarrounds sind gut, aber ich möchte ja auch etwas lernen.

von Joachim B. (jar)


Lesenswert?

D a v i d K. schrieb:
> OK, es muss etwas mit dem BCD Format zu tun haben.
> Also der Chip funktioniert korrekt, da bin ich mir mittlerweile 100%
> sicher.

logisch und darum nutzen alle DS Uhren die bcd2int

avr gcc z.B. A(VR)- oder Atmel-Studio
1
uint8_t bcd2int( uint8_t bcd )
2
{  return ((uint8_t)(((bcd>>4)*10)+(bcd&15)));
3
} // uint8_t bcd2int( uint8_t bcd )
4
5
uint8_t int2bcd( uint8_t integer )
6
{  return ((uint8_t)(((integer/10)<<4)+(integer%10)));
7
} // uint8_t int2bcd( uint8_t integer )

in Arduino nutze ich die LIB
die geht mit DS1307 und DS3231 gleichermaßen weil die ersten Register an 
gleicher Stelle liegen
1
#include <DS1307new.h>


D a v i d K. schrieb:
> Wie stehen denn die Chancen den Fehler in meinem lcd_printInt(...) zu
> finden?

in diesem Code?
1
> void lcd_printInt(uint16_t value, uint8_t c, bool leadingZeros)
2
> {
3
>   char str[c];
4
>   utoa(value, str, 10);
5
>   if(leadingZeros)
6
>   {
7
> 
8
>     for( uint8_t i = getDigitCount(value); i < c; i++)
9
>       lcd_print_P(PSTR("0"));
10
>   }
11
>   lcd_print(str);
12
> }

ich versuchs dann mal

von Joachim B. (jar)


Lesenswert?

bevor ich anfange, in diesem Code den ich vorher zeigte?
Beitrag "Re: I2C Real Time Clock/Calendar (DS1337"

warum uint16_t value?
die Uhrzeiten sind eh immer 2-stellig also reicht uint8_t value

sollte mehr dazu kommen wegen uint16_t dann sollte man auch die Ausgbe 
Stellenzahl 2,3,4,5 ? angeben, sowie linksbündig oder rechtsbündig mit 
führende Nullen oder lieber doch führende SPACE?

Die "lcd_printInt" scheint mir nicht universell ausgereift

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.