Установить регистр управления на низкий уровень в ds3231 rtc

Я использую модуль ds3231 rtc для постоянного отслеживания и создания сигнала тревоги вместе с резервной батареей. когда я использовал его в первый раз, он работал нормально. но теперь он не отслеживает мое время, когда питание отключается от основного питания, но я проверил, что мой баттри находится в безопасности. Поэтому я ищу на многих форумах, где говорится, что бит EOSC был установлен высоко, что остановит часы, когда он остановит внутренний генератор. также хочу установить его на низкий уровень тогда только rtc будет следить за временем

но в другом на некоторых форумах они проинструктировали что поставьте этот следующий код для установки его на низкий уровень

DS3231 RTC;

  Wire.beginTransmission(0x68);
  Wire.write(0xF); // Адрес регистра состояния
  Wire.write(0x00); // Ноль регистра состояния
  Wire.endTransmission(); 
  Wire.beginTransmission(0x68);
  Wire.write(0xE); // Адрес регистра состояния
  Wire.write(0x00); // Обнуление регистра состояния
  Wire.endTransmission(); 

  RTC.setA2Time( ADay, AHour, AMin, 0x00, true, false, false);
  delay(100);
  RTC.turnOnAlarm( 2 );

в другом месте показали следующий код

// очистить /EOSC бит, чтобы убедиться, что часы работают от батареи
  Wire.beginTransmission(0x68); // address DS3231
  Wire.write(0x0E); // выбрать регистр
  Wire.write(0b00011100); // запись bitmap регистра, бит 7 is /EOSC
  Wire.endTransmission();

но теперь проблема заключается в том, где я должен разместить этот код и как правильно его использовать, чтобы продолжать отслеживать время, когда ds3231 тоже теряет питание? пожалуйста, кто-нибудь знает об этой проблеме, потому что я обнаружил, что так много людей борются с этой проблемой, когда они приходят вперед, чтобы использовать этот модуль ds3231 rtc. если какой либо орган знает о том как решить эту проблему пожалуйста подумайте о том чтобы поделиться своей идеей это определенно поможет полностью для evryone потому что нет ни одного правильного ответа на этот вопрос

, 👍3

Обсуждение

итак , что же мне нужно делать?, @Sharifdeen Ashshak

как я определяю это в своем кодировании?, @Sharifdeen Ashshak

Я бы порекомендовал вам использовать эту библиотеку ([RTClib](https://github.com/adafruit/RTClib)) для тестирования вашего модуля. Если он работает нормально, вы можете посмотреть соответствующую функцию, чтобы проверить, как там все работает, и таким образом вы можете исправить свой код., @Arslan

Чтобы понять структуру регистра DS3231, вы должны посмотреть здесь на странице 11 https://www.analog.com/media/en/technical-documentation/data-sheets/ds3231.pdf. Приведенный вами пример кода Wire.write(0xE); . . . Wire.write(0x00); устанавливает регистр управления (0Eh) в ноль, что позволяет генератору сбрасывать бит /EOSC. Однако я предполагаю, что ваша проблема где-то в другом, потому что обычно ничто не должно отключать осциллятор, когда он включен., @6v6gt

Какую библиотеку вы используете для DS3231 и для установки сигналов тревоги? Дело в том, что тот же самый регистр DS3231, который управляет генератором (0x11), также управляет прерываниями по тревоге. Если библиотека написана небрежно, она может, как побочный эффект, отключить осциллятор при изменении конфигурации будильника. Добавление кода для включения осциллятора может не сильно помочь, если вы не можете гарантировать его запуск в тот момент, когда осциллятор отключен, и в любом случае это будет только обходной путь., @6v6gt


3 ответа


-1

У меня также есть DS3231 RTC в моем проекте робота. Вот мой полный установочный код. Это может быть размещено в любом месте настройки(): Я не думаю, что вам нужно возиться с отдельными регистрами, чтобы получить то, что вы хотите.

    if (rtc.begin()) //02/19/19 теперь это возвращает значение FALSE, если RTC не отвечает
    {
        Serial.println("Found RTC...");
        delay(100);
        bRTCLostPower = rtc.lostPower(); //added 10/17/18
        mySerial.printf("rtc.lostPower() reports %d\n", bRTCLostPower);

        if (rtc.lostPower())
        {
            Serial.println("RTC потерял питание.  Установка RTC на время последней компиляции");
            rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));// устанавливает RTC на дату/время последней компиляции
        }

#ifdef FORCE_RTC_TO_LAST_COMPILE_TIME
        Serial.println("Forcing RTC to last compile time");
        rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));//  устанавливает RTC на дату/время последней компиляции
#endif 

        DateTime now = rtc.now();
        char buffer[100];
        memset(buffer, '\0', 100);
        mySerial.printf("Retrieving Date/Time from RTC with rtc.now() =  %ld\n", now.unixtime());
        GetDayDateTimeStringFromDateTime(now, buffer);
        Serial.print("Date/Time: "); Serial.println(buffer);
        RTC_Avail = true;
    }
    else
    {
        Serial.println("Couldn't find RTC. Real-time clock functions won't be available");
        RTC_Avail = false; //используйте это вместо
    }

    if (RTC_Avail && rtc.lostPower())
    {
        DateTime Comp_dt = DateTime(F(__DATE__), F(__TIME__)); //__DATE__ & __TIME__ are environment variables)
        uint8_t mydayofweek = Comp_dt.dayOfTheWeek();  //возвращает 0 для воскресенья, 6 для субботнего дня недели
        int mymonth = Comp_dt.month();
        int myday = Comp_dt.day();
        int myyear = Comp_dt.year();
        int myhour = Comp_dt.hour();
        int mymin = Comp_dt.minute();
        int mysec = Comp_dt.second();
        long unixtime = Comp_dt.unixtime();
        char* dayofweek = (char*)daysOfTheWeek[mydayofweek];

        Serial.print("day of week value = "); Serial.println(mydayofweek);
        Serial.print("day of week value = "); Serial.println(Comp_dt.dayOfTheWeek());

        mySerial.printf("RTC lost power - setting to datetime of last compile %ld (%s %4d/%02d/%02d at %02d:%02d:%02d)\n",
            unixtime, dayofweek, myyear, mymonth, myday, myhour, mymin, mysec);

        rtc.adjust(Comp_dt);
    }
,

что вы подразумеваете под индивидуальным реестром?, @Sharifdeen Ashshak


0

Я рекомендую вам использовать эту (RTClib) библиотеку для тестирования вашего модуля. Если он работает нормально, вы можете посмотреть в соответствующей функции, чтобы проверить, как там все работает, и таким образом вы можете исправить свой код.

,

1

Из технического описания DS3231:

Регистр управления (0Eh)

Бит 7: включить генератор (EOSC). При установке на логический 0 генератор запускается. При установке на логическую 1 генератор останавливается, когда DS3231 переключается на VBAT. Этот бит сбрасывается (логический 0) при первом включении питания. Когда DS3231 питается от VCC, генератор всегда включен независимо от состояния бита EOSC. Когда EOSC отключен, все данные регистра являются статическими.

Регистр состояния (0Fh)

Бит 7: флаг остановки генератора (OSF). Логическая 1 в этом бите указывает, что генератор либо остановлен, либо был остановлен на некоторый период, и может использоваться для оценки достоверности данных хронометража. Этот бит устанавливается в логическую 1 всякий раз, когда генератор останавливается. Ниже приведены примеры условий, которые могут привести к установке бита OSF:

  1. При первом включении питания.
  2. Напряжения, присутствующего как на VCC, так и на VBAT, недостаточно для поддержки генерации.
  3. Бит EOSC отключен в режиме с питанием от батареи.
  4. Внешние воздействия на кристалл (например, шум, утечка и т. д.). Этот бит остается в логической 1 до тех пор, пока не будет записан в логическую 0.

Я откопал старую плату D3231. В нем была батарея, но последний раз ее устанавливали ~ 3 года назад, и я не уверен, сколько лет ей было, когда я впервые вставил ее в плату. Батарея не может поддерживать ход часов. Когда я подключил его к Arduino UNO и загрузил, регистры часов читались следующим образом (обратите внимание на время, бит EOSC и флаг OSF):

ЧАСЫ: 00:01:15 (24-часовой формат) Воскресенье, 01.01.2000 Температура=21C Смещение старения=0

Будильник №1: 00:00:00 (24-часовой формат) DY/DT=18[режим DoM] Выбор будильника: при совпадении даты, часов, минут и секунд

Будильник №2: 00:00 (24-часовой формат) DY/DT=20[режим DoM] Выбор будильника: при совпадении даты, часов и минут

Управляющий байт = 00011100 /EOSC включен /BBSQW отключен /CONV сброшен /режим INTCN установлен на совпадение /Тревога 1 отключена /Тревога 2 отключена

STATUS byte=10000000 /OSF включен /EN32KHZ отключен /BSY выключен /A1F выключен /A2F выключен

Теперь часы работают, потому что с VCC, поставляемым Arduino, осциллятор будет работать всегда. Когда я читаю часы, я вижу, как идет время, но оно началось с 00:00:00

Теперь я отключаю питание и примерно через минуту включаю UNO и часы и считываю показания часов. Он снова запущен, но время не продвинулось — просто перезапустилось с 00:00:00. EOSC включен. OSF включен.

Без VBAT время не сохранялось.

Вставлен новый аккумулятор, и я включаю питание. Часы снова идут, снова перезапущены в 00:00:00. EOSC включен. OSF включен.

Через пару минут я выключаюсь (в часах все еще стоит свежая батарейка). Когда я загружаюсь и читаю часы, они работают И продолжают работать от батареи, поэтому текущее время является точным. EOSC включен. OSF включен.

EOSC всегда был включен (читается как 0) — это значение POR. Если ваша программа явно не установит бит в 1, EOSC будет надежно включен. Если вы отключите EOSC (установите значение 1), осциллятор НЕ будет работать от резервной батареи (VCC выключено, а VBAT включено). При отключенном EOSC и при достаточном заряде батареи он будет удерживать время (и другие регистры), когда VCC выключен, а VBAT включен. Когда VCC включен, осциллятор будет работать всегда.

А как насчет флага OSF?

Читая лист данных, вы можете видеть, что флаг OSF устанавливается, когда осциллятор останавливается, что может произойти из-за ряда условий.

Он разработан таким образом, что программное обеспечение может обоснованно подозревать, что время неточное, но OSF устанавливается в качестве значения POR.

Вам необходимо включать EOSC И ОЧИСТИТЬ OSF каждый раз, когда вы выполняете чистое включение питания и каждый раз, когда OSF устанавливается из-за отключения (без VCC) и замены батарей. Также помните, что с VCC осциллятор будет работать независимо от состояния бита EOSC.

Не игнорируйте OSF, это важный флаг, и его не следует устанавливать регулярно. На самом деле, как только вы вставите батарею и очистите OSF, ее не следует устанавливать снова, пока батарея не разрядится. Если он устанавливается регулярно, у вас есть проблемы в другом месте.

Некоторое программное обеспечение считывает OSF, и если оно установлено, программное обеспечение будет сопротивляться и сообщит вам столько, сколько должно. Поскольку OSF настроен на POR, он будет устанавливаться всякий раз, когда вы удаляете VCC и VBAT, а затем снова включаете питание.

Вам нужно явно очистить OSF И знать, почему он был установлен.

Этот фрагмент кода включает EOSC И очищает OSF.

 // включить EOSC и очистить флаг OSF
 // *** Остальные биты в этих двух регистрах записываются
 // со значениями POR или '0', если значение POR=X.
  Wire.beginTransmission(0x68); // адрес DS3231
  Wire.write(0x0E); // выбор регистра CONTROL
  Wire.write(0b000011100); // регистр записи (бит 7 — EOSC)
  Wire.endTransmission();
  Wire.beginTransmission(0x68); 
  Wire.write(0x0F); // выбор регистра STATUS
  Wire.write(0b00001000); // регистр записи (бит 7 — OSF)
  Wire.endTransmission();

Надеюсь, это поможет.

,