Ich verwende MCP7940 RTC von Mikrochip, der den Wochentag als Teil der Aktualisierung von RTC mit Datum eingeben muss. Wie soll ich also den Wochentag basierend auf dem vom Benutzer angegebenen Datum berechnen?
Wenn Sie den Wochentag selbst berechnen möchten, finden Sie hier eine C-Implementierung eines Teils eines Perl-Moduls, das ich vor etwa 20 Jahren geschrieben habe. Ich mag diesen Algorithmus, weil er keine Schleifen oder eine Tabelle mit Monatslängen erfordert. Beachten Sie, dass int
angenommen wird, dass s 32 Bit sind.
/* Returns the number of days to the start of the specified year, taking leap
* years into account, but not the shift from the Julian calendar to the
* Gregorian calendar. Instead, it is as though the Gregorian calendar is
* extrapolated back in time to a hypothetical "year zero".
*/
int leap (int year)
{
return year*365 + (year/4) - (year/100) + (year/400);
}
/* Returns a number representing the number of days since March 1 in the
* hypothetical year 0, not counting the change from the Julian calendar
* to the Gregorian calendar that occured in the 16th century. This
* algorithm is loosely based on a function known as "Zeller's Congruence".
* This number MOD 7 gives the day of week, where 0 = Monday and 6 = Sunday.
*/
int zeller (int year, int month, int day)
{
year += ((month+9)/12) - 1;
month = (month+9) % 12;
return leap (year) + month*30 + ((6*month+5)/10) + day + 1;
}
/* Returns the day of week (1=Monday, 7=Sunday) for a given date.
*/
int dow (int year, int month, int day)
{
return (zeller (year, month, day) % 7) + 1;
}
Laut Datenblatt gibt es unter Adresse 0x03 in Tabelle 4-1 ein Feld „Tag“. Am Ende der Zeile steht eine kurze Beschreibung:
Das bedeutet, dass der Tag auf eine beliebige Zahl zwischen 1 und 7 eingestellt werden kann. Sie können Ihren eigenen Wochentag auswählen. Auf POSIX-Systemen ist der Montag als 1 definiert, ich denke, das ist ein guter Standard. Dann Dienstag = 2; Mittwoch = 3; ...
Tag = 0 ist nicht dokumentiert, also nicht verwenden.
Unter Linux kann diese Nummer leicht mit dem Befehl gefunden werden date +%u
, der heute antwortet, 6
da es Samstag ist. Wenn Sie dies lokal auf Ihrem PIC berechnen möchten, müssen Sie die C-Bibliothek finden, die die Formel implementiert, von der ich glaube, dass strftime
sie <time.h>
genau das tut, aber ich bin nicht genug C-Programmierer, um zu erklären, wie diese bestimmte Bibliothek verwendet wird. Es ist eine häufig verwendete Bibliothek, daher ist die Dokumentation leicht zu finden.
Der Wochentag ist beliebig . Sie definieren es. Sie könnten den julianischen Sonntag = Tag 1 verwenden. Sie könnten Montag als Tag 1 verwenden, da Sonntag der 7. Tag ist. Sie könnten Freitag als Tag 1 verwenden, weil es der erste Tag des Wochenendes ist. Sie könnten den Dienstag als Tag 1 verwenden, weil Sie Montage hassen.
Ich schlage vor, Sie verwenden die RTClib-Bibliothek
#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
void setup () {
Serial.begin(9600);
delay(3000); // wait for console opening
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, lets set the time!");
// Comment out below lines once you set the date & time.
// Following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// Following line sets the RTC with an explicit date & time
// for example to set January 27 2017 at 12:56 you would call:
// rtc.adjust(DateTime(2017, 1, 27, 12, 56, 0));
}
}
void loop () {
DateTime now = rtc.now();
Serial.println("Current Date & Time: ");
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.print(now.second(), DEC);
Serial.println();
Serial.println("Unix Time: ");
Serial.print("elapsed ");
Serial.print(now.unixtime());
Serial.print(" seconds/");
Serial.print(now.unixtime() / 86400L);
Serial.println(" days since 1/1/1970");
// calculate a date which is 7 days & 30 seconds into the future
DateTime future (now + TimeSpan(7,0,0,30));
Serial.println("Future Date & Time (Now + 7days & 30s): ");
Serial.print(future.year(), DEC);
Serial.print('/');
Serial.print(future.month(), DEC);
Serial.print('/');
Serial.print(future.day(), DEC);
Serial.print(' ');
Serial.print(future.hour(), DEC);
Serial.print(':');
Serial.print(future.minute(), DEC);
Serial.print(':');
Serial.print(future.second(), DEC);
Serial.println();
Serial.println();
delay(1000);
}
Superkatze
David Tweed