如何解决如何在arduino项目中正确配置和使用RTC DS3231?
我的目标是构建一个闹钟(以CSGO中C4的形式)。 我无法正确设置或使用 RTC DS3231 ,它不会更改时间/日期,并且每次都输出相同的怪异值(17:59:40.727-> Mittwoch,165。2165 45 :165:85) 我使用一些随机库在Arduino Uno上测试了DS3231。 我在做什么错了?
以下是代码*.ino
(注释为德语):
#include <Wire.h>
#define RTC_I2C_ADDRESS 0x68 // I2C Adresse des RTC DS3231
//Membervariablen
int jahr,monat,tag,stunde,minute,sekunde,wochentag;
int daysInMonth[12]={31,28,31,30,31};
String daysInWeek[7] = {"Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"};
String monthInYear[12] = {"Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"};
String outputFormat = "%s,%02d.%s %04d %02d:%02d:%02d Uhr";
//Ließt den aktuellen Zeitstempel aus dem RTC Modul.
void rtcReadTime(){
Wire.beginTransmission(RTC_I2C_ADDRESS); //Aufbau der Verbindung zur Adresse 0x68
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(RTC_I2C_ADDRESS,7);
sekunde = bcdToDec(Wire.read() & 0x7f);
minute = bcdToDec(Wire.read());
stunde = bcdToDec(Wire.read() & 0x3f);
//Der Wochentag wird hier nicht ausgelesen da dieses mit
//dem Modul RTC DS3231 nicht über die Wire.h zuverlässig funktioniert.
/* wochentag =*/ bcdToDec(Wire.read());
tag = bcdToDec(Wire.read());
monat = bcdToDec(Wire.read());
jahr = bcdToDec(Wire.read())+2000;
}
//Funktion zum schreiben / setzen der Uhrzeit.
void rtcWriteTime(int jahr,int monat,int tag,int stunde,int minute,int sekunde){
Wire.beginTransmission(RTC_I2C_ADDRESS);
Wire.write(0); // Der Wert 0 aktiviert das RTC Modul.
Wire.write(decToBcd(sekunde));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(stunde));
Wire.write(decToBcd(0)); // Wochentag unberücksichtigt
Wire.write(decToBcd(tag));
Wire.write(decToBcd(monat));
Wire.write(decToBcd(jahr-2000));
Wire.endTransmission();
}
//Berechnet den Tag der Woche aus dem übergebenen Datumswerten.
byte calcDayOfWeek(int jahr,byte monat,byte tag) {
static int t[] = {0,3,2,5,1,4,6,4};
jahr -= monat < 3;
return ((jahr + jahr/4 - jahr/100 + jahr/400 + t[monat-1] + tag) % 7);
}
//Convertiert Dezimalzeichen in binäre Zeichen.
byte decToBcd(byte val){
return ( (val/10*16) + (val%10) );
}
//Convertiert binäre Zeichen in Dezimal Zeichen.
byte bcdToDec(byte val){
return ( (val/16*10) + (val%16) );
}
//Ließt einen String und liefert einen Integer Wert von einer
//definierten Stelle (byte num) des Stringwertes.
int getIntFromString (char *stringWithInt,byte num){
char *tail;
while (num>0){
num--;
//Bei Kommanseparierten Listen werden die Kommata
//übersprungen und geben damit die Unterteilung des Strings an.
while ((!isdigit (*stringWithInt))&&(*stringWithInt!=0)){
stringWithInt++;
}
tail=stringWithInt;
//Schleife solange ausführen bis eine Zahl gefunden wurde
//welche größer 0 ist.
while ((isdigit(*tail))&&(*tail!=0)){
tail++;
}
if (num>0){
stringWithInt=tail;
}
}
return(strtol(stringWithInt,&tail,10));
}
//Setup Methode
void setup(){
Wire.begin(); //Kommunikation über die Wire.h bibliothek beginnen.
Serial.begin(57600); //Übertragungsgeschwindigkeit 9600 Baud
Serial.println("Mit dem Befehl kann das Datum und die Uhrzeit gesetzt oder veraendert werden.");
Serial.println("Beispiel: set 28.08.2013 10:54");
}
//Gibt einen Zeitstempel auf der Seriellen Schnittstelle aus.
void printRTCDateTime(){
char linebuf[60];
int dOW = calcDayOfWeek(jahr,tag);
String wochentagC = daysInWeek[dOW];
String monatC = monthInYear[monat];
String result = "";
result += wochentagC;
result += ",";
result += tag;
result += ".";
result += monatC;
result += " ";
result += jahr;
result += " ";
if(stunde<10) { result += "0"; }
result += stunde;
result += ":";
if(minute<10) { result += "0"; }
result += minute;
result += ":";
if(sekunde<10) { result += "0"; }
result += sekunde;
Serial.println(result);
}
//Manuelles setzen der Uhrzeit über den Seriellen Monitor der IDE.
void setRTCTime(){
char linebuf[30];
byte counter;
if (Serial.available()){
delay(100); // Warte auf das Eintreffen aller Zeichen vom seriellen Monitor
memset(linebuf,sizeof(linebuf)); // Zeilenpuffer löschen
counter=0; // Zähler auf Null
while (Serial.available()){
linebuf[counter]=Serial.read(); // Zeichen in den Zeilenpuffer einfügen
if (counter<sizeof(linebuf)-1) counter++; // Zeichenzähler erhöhen
}
// Wenn in der gelesenen Zeile das Wort 'set' vorkommt dann...
//(Hier muss man bedenken das die Suche nach 'set' auch nach x Zeichen ein positives Ergebnis liefern wird,zbsp. 123set 09.01.2016 12:00:00)
if (strstr(linebuf,"set")==linebuf){
tag=getIntFromString (linebuf,1);
monat=getIntFromString (linebuf,2);
jahr=getIntFromString (linebuf,3);
stunde=getIntFromString (linebuf,4);
minute=getIntFromString (linebuf,5);
sekunde=getIntFromString (linebuf,6);
} else {
Serial.println("Befehl unbekannt.");
return;
}
// Ausgelesene Werte einer groben Plausibilitätsprüfung unterziehen:
if (!checkDateTime(jahr,sekunde)){
Serial.println(linebuf);
Serial.println("Fehlerhafte Zeitangabe im 'set' Befehl");
Serial.println("Beispiel: set 28.08.2013 10:54");
return;
}
rtcWriteTime(jahr,sekunde);
Serial.println("Zeit und Datum wurden auf neue Werte gesetzt.");
}
}
//Prüft das eingegebene Datum auf korrektheit.
boolean checkDateTime(int jahr,int sekunde){
boolean result = false;
if(jahr>2000){
result = true;
} else {
return false;
}
// Schaltjahr prüfen
if(jahr % 400 == 0 || (jahr % 100 != 0 && jahr % 4 == 0)){
//Wenn es ein Schaltjahr ist dann den Wert 29 in das Array an der Stelle 1 für den Monat Februar schreiben.
daysInMonth[1]=29;
}
//Monat muss kleiner 13 sein.
if (monat<13){
if( tag <= daysInMonth[monat-1] ){
result = true;
}
} else {
return false;
}
//Wert für Stunde muss zwischen 0 und 24 liegen,//Wert für Minute und sekunde muss zwischen 0 und 59 liegen
if(stunde <24 && minute <60 && sekunde <60 && stunde >= 0 && minute >=0 && sekunde >=0){
result = true;
} else {
return false;
}
return result;
}
void loop(){
rtcReadTime();
printRTCDateTime();
setRTCTime();
delay(1000);
}
解决方法
要获得第二名,你就
sekunde = bcdToDec(Wire.read() & 0x7f);
因此,您只需读取第一个字节的最低7位。这有点复杂。仔细阅读数据表!
从数据表:
MSB BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 LSB
0 | 10 seconds | seconds
您只需读取7位作为秒值。那行不通。
49秒为0b01001001
您阅读了73。
您应该计算
0b01001001 & 0x0F -> 9
您的秒值
和
0b01001001 & 0xF0 -> 4
您的10秒值
-> 10 * 4 + 9 = 49
对于其他所有值,您都遇到相同或严重的问题。希望你明白我的意思。
您还应该检查应该设置时间的代码。为什么将整数值写入寄存器字节?在这里,您也不遵循地址表。您不仅要做decToBcd
任何值并将其填充到总线上,还要做更多的事情。
我还没有阅读完所有代码。我想您应该先解决这些问题。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。