Ich möchte den RAM Speicher der DS1307 zum Speichern von Einstellungen benutzen.
Im Forum habe ich dazu folgendes gefunden. (Beitrag #2)
#define DS1307_ADDR 0x68
#define RAM_OFFSET 8 //map logical ram addresses (0-55) to physical addresses (8-63)
//write to DS1307 RAM where addr>=0 and addr<56
void dsSramWrite(byte addr, byte *values, byte nBytes)
{
Wire.beginTransmission(DS1307_ADDR);
Wire.write(addr + RAM_OFFSET);
for (byte i=0; i<nBytes; i++) Wire.write(values[i]);
Wire.endTransmission();
}
//read from DS1307 RAM where addr>=0 and addr<56
void dsSramRead(byte addr, byte *values, byte nBytes)
{
Wire.beginTransmission(DS1307_ADDR);
Wire.write(addr + RAM_OFFSET);
Wire.endTransmission();
Wire.requestFrom( (uint8_t)DS1307_ADDR, nBytes );
for (byte i=0; i<nBytes; i++) values[i] = Wire.read();
}
//is the DS1307 oscillator running?
boolean dsIsRunning(void)
{
byte secRegister; //seconds register, bit 7 is clock halt (CH) bit
Wire.beginTransmission(DS1307_ADDR);
Wire.write(0x00); //seconds register is address zero
Wire.endTransmission();
Wire.requestFrom( DS1307_ADDR, 1 );
secRegister = Wire.read();
return !(secRegister & 0x80);
}
Ich verstehe allerdings nicht wie man die Funktionen benutzt.
Die DS1307 benutzt ja die ersten 8 Adresse des RAM Speichers für Zeit und Datum und die anderen 56 sind frei verfügbar. Nun wollte ich testweise einfach mal einen Wert der ersten 8 Adressen auslesen (dazu habe ich RAM_OFFSET auf 0 gesetzt).
Wie mache ich das?
Die Funktion "dsSramRead" ist ja mit void definiert und gibt mir keine Werte zurück oder verstehe ich das falsch. Und für was wird die Variable byte *values, verwendet?
ArduinoArti:
Die Funktion "dsSramRead" ist ja mit void definiert und gibt mir keine Werte zurück oder verstehe ich das falsch. Und für was wird die Variable byte *values, verwendet?
Informiere Dich über Arrays und Zeiger/Pointer und die Grundlagen von Werteübergaben an Funktionen.
Die Funktion "dsSramRead" ist ja mit void definiert und gibt mir keine Werte zurück oder verstehe ich das falsch
Funktionen können keine Arrays zurückgegeben. Das sind in C/C++ keine Objekte wie in manchen anderen Sprachen. Deshalb übergibt das Ziel-Array als Parameter und die Funktion füllt es
Außerdem entsprechen Array-Variablen praktisch Zeigern auf das erste Element. Deshalb byte*. Und zusätzlich übergibt man noch die Größe des Arrays damit die Funktion weiß wie viel Platz ist
//read from DS1307 RAM where addr>=0 and addr<56
void dsSramRead(byte addr, byte *values, byte nBytes)
{
Wire.beginTransmission(DS1307_ADDR);
Wire.write(addr + RAM_OFFSET);
Wire.endTransmission(false);
Wire.requestFrom( (uint8_t)DS1307_ADDR, nBytes );
for (byte i=0; i<nBytes; i++) values[i] = Wire.read();
}
Das fehlte ein false, ich habe es mal eingetragen
Macht für diese Anwendung wohl keinen Unterschied, könnte aber dem einen oder anderen unverhofft ein Beinchen stellen.
Zudem könnte man die Rückgabewerte der Methoden überprüfen, und so herausfinden ob die Aktion überhaupt Erfolg hatte.
Also ich habe mich mal eingelesen. Die Rückgabe erfolgt also "per pointer". Ganz verstanden habe ich es aber trotzdem noch nicht. Der Zeiger hat den gleichen Datentyp wir die Variable auf die gezeigt wird. Wie ich den Zeiger in diesem Fall jetzt aber definieren muss ist mir noch nicht klar. Ich wollte probeweise mal den Wochentag, den Tag und den Monat auslesen. Hier sind die Speicherorte der RTC nachzulesen.
Versucht habe ich es folgendermaßen
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
#define DS1307_ADDR 0x68
#define RAM_OFFSET 0
byte Ram[3];
void setup () {
while (!Serial); // for Leonardo/Micro/Zero
Serial.begin(9600);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (! rtc.isrunning()) {
Serial.println("RTC is NOT running!");
}
}
void loop () {
DateTime now = rtc.now();
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(" (");
Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
Serial.print(") ");
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.println(now.second(), DEC);
dsSramRead(3, Ram, 3);
Serial.print("Wert1:");
Serial.println(Ram[0]);
Serial.print("Wert2:");
Serial.println(Ram[1]);
Serial.print("Wert3:");
Serial.println(Ram[2]);
delay(3000);
}
void dsSramRead(byte addr, byte *values, byte nBytes)
{
Wire.beginTransmission(DS1307_ADDR);
Wire.write(addr + RAM_OFFSET);
Wire.endTransmission(false);
Wire.requestFrom( (uint8_t)DS1307_ADDR, nBytes );
for (byte i = 0; i < nBytes; i++) values[i] = Wire.read();
}
Wie ich den Zeiger in diesem Fall jetzt aber definieren muss ist mir noch nicht klar.
Gar nicht. Der Zeiger wird doch von der Funktion schon definiert. Du darfst nicht Arrays mit Zeigern verwechseln. Die sind miteinander verwandt, aber zwei verschiedene Dinge
Danach stehen in data 3 Bytes aus dem RAM. Die Adresse musst du noch eintragen
Die Array-Variable zerfällt bei der Übergabe einfach in einen Zeiger auf das erste Element. Oder in anderen Worten man übergibt die Anfangs-Adresse eines Bereichs im Speicher
Ich wollte probeweise mal den Wochentag, den Tag und den Monat auslesen.
Du solltest beachten dass Zeit und Datum im BCD Format abgespeichert sind:
wno158:
Hmmm.
Das Lesen startet an Adresse 3 - dem Link nach wäre das der Wochentag.
Und dann ist 3 Dienstag und nicht Sonntag.
Vielleich habe ich auch was übersehen...
Ja das ist mir auch aufgefallen.
Ich nutze aktuell die Bibliothek RTClib von Adafruit Version 1.11.2. Laut Beschreibung enthält diese bereits Funktionen zum Schreiben und auslesen.
Diese funktionieren auch, sodass mein eigentliches Problem, das Speichern im Ram Speicher, gelöst ist.
Was mich wundert ist jedoch, dass wenn ich über diese Funktionen die ersten 8 Stellen auslese bekomme ich wieder komplett andere Werte.
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
#define DS1307_ADDR 0x68
#define RAM_OFFSET 0
byte Ram[13];
uint8_t Ram2;
byte testin;
void setup () {
while (!Serial); // for Leonardo/Micro/Zero
Serial.begin(9600);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (! rtc.isrunning()) {
Serial.println("RTC is NOT running!");
}
}
void loop () {
DateTime now = rtc.now();
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(" (");
Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
Serial.print(") ");
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.println(now.second(), DEC);
dsSramRead(0, Ram, 12);
Serial.println(Ram[0]);
Serial.println(Ram[1]);
Serial.println(Ram[2]);
Serial.println(Ram[3]);
Serial.println(Ram[4]);
Serial.println(Ram[5]);
Serial.println(Ram[6]);
Serial.println(Ram[7]);
Serial.println(Ram[8]);
Serial.println(Ram[9]);
Serial.println(Ram[10]);
Serial.println(Ram[11]);
Serial.println(" ");
//Versuch mit rtc lib von adafruit
//testin = 45;
//rtc.writenvram(10,testin);
Serial.println(rtc.readnvram (0));
Serial.println(rtc.readnvram (1));
Serial.println(rtc.readnvram (2));
Serial.println(rtc.readnvram (3));
Serial.println(rtc.readnvram (4));
Serial.println(rtc.readnvram (5));
Serial.println(rtc.readnvram (6));
Serial.println(rtc.readnvram (7));
Serial.println(rtc.readnvram (8));
Serial.println(rtc.readnvram (9));
Serial.println(rtc.readnvram (10));
Serial.println(rtc.readnvram (11));
delay(30000);
}
void dsSramRead(byte addr, byte *values, byte nBytes)
{
Wire.beginTransmission(DS1307_ADDR);
Wire.write(addr + RAM_OFFSET);
Wire.endTransmission(false);
Wire.requestFrom( (uint8_t)DS1307_ADDR, nBytes );
for (byte i = 0; i < nBytes; i++) values[i] = Wire.read();
}
Nochmal: Das ist BCD kodiert. Lese nach was BCD ist und rechne das um. Das geht auch bequem mit dem Windows Taschenrechner wenn man sich die Binärdarstellung ansieht
22 -> 16
16 -> 10
32 -> 20
3 -> 3 (das sollte aber eher 1 sein für Sonntag)
39 -> 27
9 -> 9
32 -> 20 (Jahre haben nur zwei Stellen)
Das ist ein Zähler, der unabhängig vom gestellten Datum ist.
Müsste ich jetzt nachsehen,ob 0..6 oder 1..7.
Wenn du ihn brauchst, musst du ihn eben richtig setzen, zusammen mit dem Datum.