Особенности запуска RTC PCF8563 при подаче питания

08.03.2022

Эта статья была мной ранее (14 февраля 2020 года) опубликована на канале Разумный мир в Яндекс.Дзен. Однако, последние изменения в Дзен привели к необходимости переноса статей на другие ресурсы. Статья публикуется с небольшими изменениями.

Микросхема PCF8563 это часы реального времени. Она довольно популярна, несмотря на то, что выпускается с конца прошлого века, из-за невысокой цены, простоты и достаточности функционала для многих применений. И встретить ее можно и в конструкции на Ardiuno, и в любительских устройствах, и в промышленных изделиях. С описываемой в сегодняшней статье особенностью сталкиваются далеко не все, но знать об этом полезно, а учитывать в своих конструкциях необходимо. Начну я с того, как эта особенность проявляется, для чего несколько усугублю ситуацию. Для наглядности.

Лабораторный стенд и внешнее проявление "проблемы"

Наш лабораторный стенд будет выглядеть вот так:

Аппаратная часть

Лабораторный стенд для PCF8563

Это функциональная схема. Если присмотреться внимательнее, можно узнать очень упрощенную схему электронных часов. Здесь используется собственно микросхема PC8563, о которой и идет разговор, 7-сегментный 10 разрядный ЖК дисплей MT10T11 (производства МЭЛТ) и микроконтроллер PIC16F886. Собственно тип дисплея и тип микроконтроллера не важны, можно использовать любые другие. Просто данный дисплей тоже работает с шиной I2C, как и наша микросхема, а PIC16F886 имеет модуль MSSP который поддерживает I2C на аппаратном уровне (что нам тоже понадобится).

Из дополнительных особенностей нужно отметить конденсатор C (в данном случае емкостью 100 мкФ) и два переключателя. Конденсатор позволяет обеспечить плавное снижение напряжения питания после отключения источника переключателем S2 и имитирует разряжающую "часовую батарейку", которая используется в реальных схемах. Переключатель S1 позволяет быстро разрядить конденсатор, что будет имитировать первое включение питания или работу устройства при отсутствии "часовой батарейки".

Программная часть

Я не буду приводить полный текст программы, там нет ничего особо интересного. Но функциональная модель нам понадобится. Мы будем использовать такие высокоуровневые функции:

  • LcdInitDelay() - обеспечивает задержку на 10-12мс. Дело в том, что дисплею нужно некоторое время после включения питания, что бы провести собственную инициализацию.
  • LcdInit() - выполняет инициализацию дисплея.
  • LcdShowBuf() - выводит на дисплей содержимое буфера с преобразованием из формата BCD (в таком виде хранит время PCF8563) в цифровой 7-сегментный. Время отображается в виде ЧЧ-ММ-СС.
  • RTC_Write(h, m ,s) - записывает в микросхему RTC время. Параметрами являются часы, минуты, секунды. Преобразование не выполняется, параметры должны быть уже в формате BCD.
  • RTC_Read() - выполняет чтение текущего времени из микросхемы RTC и сохранение ее в буфере дисплея.

Собственно программа "испытаний" выглядит так

            LcdInitDelay();
            LcdInit();
            RTC_Write(0x23, 0x58, 0x22);
            while(1) {
                RTC_Read();
                LcdShowBuf();
            }
                    

Как я уже говорил, это только имеющая отношение к вопросу часть программы.

Внешнее проявление проблемы

После включения питания переключателем S2 у нас на дисплее должно появиться 23-58-22, то есть, установленное нами время, и часы должны "пойти". Если сейчас выключить на пару секунд питание (переключателем S2), то дисплей померкнет, а потом и погаснет. Но после включения питания время не сбросится, благодаря конденсатору, а часы продолжат идти. Однако, с некоторой долей вероятности на дисплее вы увидите 00-00-00, но часы будут идти. Как же так? Если выключить и снова включить питание (S2), на дисплее появится 23-58-22 и часы пойдут. Какой то сбой? Но если выключить питание переключателем S1, который разрядит конденсатор, и снова включить, то на дисплее опять появится 00-00-00. Явная ошибка? Микросхема PCF8563 настолько не надежна? Да нет, с микросхемой то все в порядке. И я сейчас покажу, в чем тут причина.

Куда эти "часики" денутся?

Если программа работает с внешним устройством, которое может быть неисправно или отключено, то программист, как правило, проверяет коды возвращаемые функциями работающими с этим устройством. Но вот если это устройство распаяно прямо на нашей печатной плате, то подход "куда оно денется и зачем его проверять?" нередко становится реальностью. Тем более, так часто поступают при работе с макетами и при различных экспериментах. Вот и в данном случае я поступил именно так. Осознанно и с учебной целью, что бы показать, к каким последствиям это может привести.

Ошибка программиста из-за недостатка информации

Давайте посмотрим, как реализована RTC_Write в данном случае, когда мы игнорируем возможность появления ошибки

            void RTC_Write(uns8 h, uns8 m, uns8 s) {
                i2c_Start();
                i2c_Write(RTC_ADDR);
                i2c_Write(0x02);
                i2c_Write(s);
                i2c_Write(m);
                i2c_Write(h);
                i2c_Stop();
            }
                    

Раз микросхема RTC у нас никуда деться не может, я просто не стал проверять (еще раз подчеркну, что осознанно, с учебной целью!), а получено ли подтверждение от устройства при записи байта. К сожалению, так нередко поступают и в реальных программах.

Микросхеме PCF8563 тоже требуется время на инициализацию. Только вот вы не найдете его документации. Описание от Philips (1999 год), которое довольно распространено в интернете и часто используется, говорит, что микросхема имеет внутренние цепи сброса при подаче питания которые инициализируют внутренние регистры микросхемы и логику шины I2C. Описана и последовательность сигналов I2C которая позволяет отключить стандартную процедуру сброса с целью ускорения тестирования микросхемы (в специальных режимах).

Документация от NXP (2015 год, возможно, и более ранние редакции) немного более многословна. Тут наконец появляется упоминание весьма важной тонкости

The PCF8563 includes an internal reset circuit which is active whenever the oscillator is stopped. In the reset state the I2C-bus logic is initialized including the address pointer and all registers. I2C-bus communication is not possible during reset.

Того, что шина I2C не работает во время внутренней инициализации микросхемы раньше не говорилось. И еще одна особенность, не менее важная, оказывается, схема сброса активна не при включении питания, а при не работающем генераторе. Эту вторую особенность я рассмотрю чуть позже, а пока остановлюсь на невозможности обмена по I2C с PCF8563 в то время, когда она выполняет процедуру внутреннего сброса.

Практически полное отсутствие информации о тонкостях внутреннего сброса и приводит к тому, что программист зачастую его игнорирует. "Хорошо, надо подождать, значит подождем. Но сколько времени ждать? 100мс хватит? Да хватит наверное..." типичный подход, в данном случае. Если вообще дают хоть сколько то времени микросхеме на инициализацию.

Немного про обмен по I2C

Давайте посмотрим на то, как происходит обмен по I2C

Передача байта информации по I2C

На рисунке показана передача байта по шине. Не важно, передает информацию ведущий (микроконтроллер, в данном случае), или принимает, после передачи всех 8 информационных бит передается дополнительный бит подтверждения. Если ведущий передает информацию, то бит подтверждения передает устройство. Если ведущий принимает информацию, то бит подтверждения передает он. Бит подтверждения передается в инверсном виде. Если получатель присутствует на шине и считает принятые данные достоверными, то будет передан бит равный 0 (ACK - подтверждение). Если получатель отсутствует, неисправен, считает принятые данные ошибочными, то будет передан бит равный 1 (NAK - нет подтверждения). Есть и еще одно использование бита подтверждения. Когда ведущий принимает данные, то он может передать NAK в ответ на байт данных от устройства, что бы сообщить устройству, что больше ничего передавать не надо.

Если у нас PCF8563 занята внутренним сбросом и не отвечает на запросы по шине, то бит ACK передавать будет просто некому. Но мы это не отслеживаем и продолжаем передачу. В один прекрасный момент времени микросхема разблокирует логику шины и начнет обрабатывать наши запросы и отвечать на них. Но произойдет это в случайный момент времени, где то в середине одного из передаваемых/принимаемых блоков данных.

Правильная реализация начала обмена с PCF8563

Микросхема RTC действительно "никуда не денется" в 99.99% случаев, поэтому слишком параноидальный подход будет не лучшим решением. Вполне достаточно ожидания готовности микросхемы простым обращением по ее адресу и анализу полученного бита подтверждения.

            void RTC_Wait() {
                while(1) {
                    i2c_Start();
                    if(!i2c_Write(RTC_ADDR)) {
                        i2c_Stop();
                        return;
                    }
                    i2c_Stop();
                }
            }
                    

Процедура i2c_Write на самом деле возвращает значение полученного от устройства бита подтверждения. Если PCF8563 еще не готова к работе и не отвечает на передачу адреса, то i2c_Write вернет 1. А мы и будем ждать реального ответа, то есть 0 значения бита подтверждения. Можно ввести какую-нибудь задержку в цикл, что бы не гонять шину на максимальной скорости. Но это совершенно не принципиально. Для большей надежности можно вызывать RTC_Wait несколько раз подряд, с небольшой задержкой. Это иногда бывает полезным, но в редких случаях. Так что достаточно одного вызова.

А что же в действительности происходит внутри PCF8563 и сколько времени продолжается сброс?

А внутри микросхемы действительно есть цепи сброса. Причем их несколько.

Я не имею никакого отношения к производителям микросхемы PCF8563. Вся изложенная далее информация построена на основе имеющейся документации и результатах анализа.

Во первых, действительно есть схема контроля напряжения питания, которая обеспечивает состояние сброса при слишком низком напряжении питания. В документации эта схема называется Voltage detector. Эта схема выполняет две функции. Первая - удержание микросхемы в состоянии сброса. Вторая - установка специального бита (VL в регистре секунд) для индикации того, что хранимое время может являться недостоверным. Согласно документации, пороговый уровень напряжения Vlow лежит в пределах 0.9-1.0В.

А вот вторую схему можно найти в несколько неожиданном месте (в документации NXP). А именно, в описании работы тестового бита STOP регистра Control_status_1. Вот как это выглядит

Функциональная схема сброса PCF8563

Видите сверху прямоугольник "OSCILLATOR STOP DETECTOR"? Вот это именно та самая схема, которая и генерирует внутренний сброс при остановке генератора. Правда есть еще и такое, но тут нет никаких дополнительных подробностей и описаний

Фрагмент функциональной схемы PCF8563

Зачем же нужен контроль работы генератора? Дело в том, что генератор на кварцевом резонаторе запускается довольно долго и ему требуется время для установления амплитуды и формы колебаний, а так же, для стабилизации частоты. Вот так, упрощенно, выглядит запуск генератора при подаче питания

Процедура запуска и стабилизации сигнала кварцевого генератора

Та самая схема контроля генератора отслеживает появление сигнала превышающего некий пороговый уровень. Это означает, что генератор заработал. После этого генератору дается дополнительное время, что бы амплитуда и частота колебаний окончательно стабилизировались. И только после этого считается, что внутренняя инициализация завершилась. Время ожидания сигнала определяется в основном используемым кристаллом кварца и может быть разным. NXP в документации просто говорят

Due to the long start-up times experienced by these types of circuits, a mechanism has been built in to disable the POR and hence speed up on-board test of the device.

в обоснование введения специальной последовательности для отмены процедуры инициализации при использовании режима тестирования устройств. То есть, данный тип схем генераторов запускается долго.

Время стабилизации обычно задается или счетчиком импульсов с генератора, или простой схемой задержки. Microchip в своих микроконтроллерах используется 10 разрядный счетчик, что задает время стабилизации в 1024 периода колебаний генератора. Если принять такую реализацию задержки, то получим время стабилизации порядка 31мс для частоты 32768Гц.

Я измерял реальную задержку между включением питания и началом работы шины I2C для PCF8563 с кварцевым резонатором NDK 350039-32.768KHz. Общее время запуска колебалось примерно от 180 до 250мс. Для других резонаторов цифры могут быть другими. Я провел замер и указал эти цифры только что бы показать порядок величин задержки, раз в документации никакие данные не приводятся.

Если вы будете использовать подход аналогичный показанному в процедуре RTC_Wait, то вам не потребуется ни измерять время запуска, ни ждать слишком долго (с запасом).

Но почему же, при кратковременном отключении питания все работало верно?

А вот для этого нам уже потребуется посмотреть на всю картину в целом. Вот так примерно выглядит процесс отключения и включения питания, когда напряжение не падает до нуля (используется переключатель S2, а не S1)

Обработка питания PCF8563

Верхний график показывает изменение напряжения питания, а нижний амплитуду колебаний генератора.

От начала координат и до вертикальной линии "1" у нас микросхема удерживается в состоянии сброс внутренним детектором напряжения. После вертикально линии "1" у нас напряжение превышает уровень уровень Vlow (1.0В) и микросхема может начать работу. Однако, это еще не означает, что генератор надежно запустится. В документации говорится, что для надежного запуска желательно напряжение не ниже 1.3В. Однако, для нас это не важно, поскольку микросхема все еще в состоянии сброса, но уже от схемы контроля генератора. Самому генератору, впрочем, работать уже разрешено (как и схеме формирования сигнала CLKOUT).

В момент времени обозначенный вертикальной прямой "2" амплитуда колебаний генератора считается достаточной, что бы начать отсчет времени стабилизации. В момент времени обозначенный вертикальной прямой "3" внутренний сброс и инициализация считаются законченными и разрешается работа логики шины I2C. Именно с этого момента времени наша микросхема начинает реагировать на запросы микроконтроллера.

В момент времени обозначенный вертикальной прямой "4" у нас происходит отключение питания (переключателем S2) и схема начинает питаться от конденсатора. Напряжение начинает падать до момента времени обозначенного вертикальной прямой "5". Это отключились микроконтроллер и дисплей (внутренними схемами контроля), что привело к уменьшению потребляемого тока.

Однако обратите внимание, что у нас все еще считается, что сигнал генератора стабилен! Дело в том, что достаточность его амплитуды задана не абсолютным значением, а в процентах от напряжения питания (Vdd). Напряжение продолжает падать, но уже медленнее. Однако, оно не снижается ниже порога Vlow, а значит детектор напряжения не будет останавливать генератор и переводить микросхему в состояние сброса.

В момент времени обозначенный вертикальной прямой "6" мы включили питание. Однако, по какой то причине (для примера!) оно нарастает немного медленнее. Это никак не влияет на PCF8563, которая по прежнему считается находящейся в рабочем состоянии, а не в состоянии сброса. Где между вертикальными линиями "6" и "7" запустятся микроконтроллер и дисплей. Микроконтроллер начнет посылать запросы для PCF8563, которая теперь будет отвечать на них без задержек.

Почему же такое поведение мало кто замечает?

Дело в том, что эта особенность проявляется только при первом включении питания или в случае разряда резервной батареи. А значит, это довольно редкое событие. Замена резервной батареи не всегда приводит к полному отключению питания RTC, так как параллельно обычно стоит конденсатор, который и обеспечивает питание во время замены.

Относительная редкость событий приводящих к проявления такой особенности запуска и является причиной того, что об этом редко задумываются. Если чтение времени из RTC выполняется программой регулярно, то и установленный бит VL, говорящий о недостоверности времени, будет рано или поздно считан, а пользователь извещен. Так может просто не обращать на это внимания? Нет, так делать не стоит. Проверка готовности PCF8563 не настолько сложна, что бы ее исключать. А в некоторых ситуациях игнорирование проверки может быть довольно критичным.

А что там про аппаратный I2C, зачем он был нужен?

Дело в том, что аппаратный I2C четко следует правилам работы конечного автомата состояний шины. А такое вот начало работы микросхемы в случайный момент времени (из-за игнорирования времени инициализации) может вызвать сбой в работе этого автомата. Например, модуль MSSP в PIC Microchip выставляет флаг запроса прерывания SSPIF при окончании формирования состояний СТАРТ/РЕСТАРТ/СТОП, окончании передачи байта, окончании приема байта (необходимости формирования бита ACK ведущим). И этот флаг запроса прерывания или просто ожидается в процедурах записи/чтения, или действительно генерирует прерывания, если обмен по шине ведется параллельно основной работе.

Сбой в работе конечного автомата приводит к тому, что флаг SSPIF не будет устанавливаться. А значит, обмен по шине просто остановится. А программа будет вечно "висеть" а ожидании этого флага. И поможет тут только сброс. Это редкая ситуация, практически не встречающаяся в реальности. Но даже в нашем лабораторном стенде до такого можно довести.

Заключение

Я рассказал об особенности работы микросхемы RTC PCF8563. На другие микросхемы подобное поведение обычно отражено в документации. Генераторы с кварцевыми резонаторами имеют подобные схемы контроля запуска почтим всегда. И микроконтроллеры тут не исключение. Зачастую можно управлять несколькими задержками при включении, и таймер запуска генератора входит в их число.

Читайте документацию внимательно, стараясь не упускать даже таких вот, не очевидно описанных тонкостей. И ваши устройства будут работать надежно, а их пользователи не будут посылать в ваш адрес нелицеприятные проклятия


Вы можете обсудить данную статью или задать вопросы автору на форуме