如何在arduino项目中正确配置和使用RTC DS3231?

如何解决如何在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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-