Вы здесь

AVR134: Часы Реального Времени на основе Асинхронного Таймера

RTC

Статья написана по мотивам Application Note AVR134 и является её вольным переводом. Кроме того, исходная статья была нацелена на применение устаревшего на текущий момент микроконтроллера ATmega103. В этой статье я в качестве целевого микроконтроллера выбрал ATmega16, так как это единственный микроконтроллер фирмы ATMEL, продающийся на каждом углу, выпускаемый в корпусе DIP, имеющий модуль счётчика реального времени, и, что оказалось для меня ключевым, раздельные выводы для подключения основного и часового кварцевых резонаторов.


Для реализации часов реального времени потребуется только один дискретный элемент – кварцевый резонатор на частоту 32,768 кГц. Устройство обладает очень низким энергопотреблением за счёт того, что большую часть времени микроконтроллер находится в энергосберегающем режиме. В энергосберегающем режиме активен только таймер. Таймер тактируется отдельным внешним резонатором. Время, день, месяц и год считаются при каждом его переполнении. Эта реализация часов реального времени может быть легко перенесена на любой микроконтроллер с модулем счётчика реального времени. Преимущества программной реализации часов реального времени перед внешней аппаратной реализацией очевидны и заключаются в следующем:

  • дешевизна;
  • минимальное количество внешних компонентов;
  • низкое энергопотребление;
  • большая гибкость.

Основные свойства

Разрабатываемые нами Часы Реального Времени будут обладать следующими свойствами:

  • Низкое энергопотребление (4 мкА при 3,3В).
  • Низкая стоимость решения.
  • Регулируемый делитель частоты, позволяющий настраивать точность.
  • Считает время, день, месяц и год с учетом високосных годов.
  • Формат даты, совместимый с 2000-ым годом.
  • Прилагается готовый код на языке «C».

Теория

Данная реализация Часов Реального Времени использует асинхронные операции модуля Счётчика Реального Времени. В этом режиме таймер-счётчик 2 работает независимо от задающего генератора процессора.

На рисунке 1 показано подключение к контроллеру AVR двух кварцевых резонаторов. В этом случае сам контроллер тактируется от резонатора с частотой 4 МГц, от которого можно отказаться, если не требуется высокой стабильности тактовых импульсов для основной программы. Для этого достаточно запрограммировать предохранители (фьюзы) на использование внутреннего RC-генератора (см. даташит). Для тактирования Таймера Реального Времени в схему введен кварцевый резонатор на частоту 32,768 кГц. Для тактирования таймера от этого резонатора его необходимо перевести в асинхронный режим. Данная схема и асинхронный режим позволяют переводить контроллер в режим энергосбережения без остановки таймера.

Подключение резонатора к Счётчику Реального Времени

Рисунок 1. Подключение резонатора к Счётчику Реального Времени

Программные Часы Реального Времени реализованы с использованием 8-разрядного Таймера/Счётчика и прерывания в результате его переполнения. Программа перехватывает прерывание по переполнению для подсчёта часов и календарных переменных. Обработчик прерывания по переполнению таймера через равные интервалы времени обновляет переменные «second», «minute», «hour», «date», «month» и «year».

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

Чтобы уменьшить энергопотребление, контроллер AVR переводится в режим энергосбережения, в котором все модули контроллера, кроме Счётчика Реального Времени, отключены. Согласно Таблице 1, микроконтроллер в таком режиме потребляет, как правило, менее 4 мкА. При возникновении прерывания в результате переполнения счётчика устройство переходит в активный режим. Обновление переменных таймера осуществляется в течение активного периода, после чего контроллер снова переводится в режим энергосбережения до наступления нового прерывания.

На рисунках 2 и 3 показаны временные диаграммы энергопотребления контроллера в разных режимах.

Для расчёта суммарной потребляемой мощности необходимо энергопотребление в сберегающем режиме сложить с энергопотреблением в активном режиме. Время, необходимое для обновления переменных таймера внутри обработчика прерывания составляет менее 100 тактов, то есть при частоте основного резонатора 4 МГц оно составляет 25 мкс. Потребление энергии за этот период незначительно. Более важным является период пробуждения контроллера. При использовании внешнего резонатора время пробуждения контроллера может быть запрограммировано до 35 мс, а для керамического резонатора оно составляет 1 мс. Ниже приведены графики энергопотребления для обоих типов резонаторов для схемы, которая просыпаются каждую секунду для обновления состояния Счётчика Реального Времени:

График энергопотребления в случае резонатора со временем старта 35 мс

Рисунок 2. График энергопотребления в случае резонатора со временем старта 35 мс

Для случая с резонатором со временем старта 35 мс общее энергопотребление в секунду составляет:

(1 сек * 4 мкА) + (35 мс * 6 мА) = 4 мкА в сек + 210 мкА в сек = 214 мкА в секунду.

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

График энергопотребления в случае резонатора со временем старта 1 мс

Рисунок 3. График энергопотребления в случае резонатора со временем старта 1 мс

Для случая с резонатором со временем старта 1 мс общее энергопотребление в секунду составляет:

(1 сек * 4 мкА) + (1 мс * 6 мА) = 4 мкА в сер + 6 мкА в сек = 10 мкА/с.

Данный расчёт показывает, что за счёт сокращения времени запуска контроллера потребление электроэнергии снижается с 200 мкА до 10 мкА в секунду.

Таблица 1. Энергопотребление контроллера AVR в различных режимах

Режим Номинал Максимум
Активный, 4МГц, 3,3В 4мА 6мА
Простой, 4МГц, 3,3В 1,8мА 2мА
Power-down, 4МГц, 3,3В <1мкА 2мкА
Power-save, 4МГц, 3,3В <4мкА 6мкА

Расчёт

Учитывая частоту часового резонатора, пользователь может установить время для каждого отсчёта таймера-счётчика путем выбора требуемого коэффициента деления. Согласно Таблице 2, биты CS02, CS01 и CS00 регистра TCCR2 (Timer/Counter2 Control Register) определяют коэффициент деления частоты источника тактовых импульсов для Таймера/Счётчика, где CK это частота часового резонатора. Например, если CK равняется 32.768 кГц, коэффициент деления равен 128, то отсчёты таймера-счётчика будут производиться с частотой 256 Гц. Учитывая то, что разрядность счётчика составляет 8 бит, для его переполнения требуется 256 отсчётов (2 в степени 8). Следовательно, прерывание будет генерироваться каждую секунду (ёмкость счётчика поделённая на частоту отсчётов, то есть 256 / 256 = 1).

Таблица 2. Выбор коэффициента деления таймера-счётчика 2

CS02 CS01 CS00 Описание Период переполнения
0 0 0 Счётчик остановлен -
0 0 1 CK 1/64s
0 1 0 CK/8 1/8s
0 1 1 CK/32 1/4s
1 0 0 CK/64 1/2s
1 0 1 CK/128 1s
1 1 0 CK/256 2s
1 1 1 CK/1024 8s

Данные даны для CK=32,768 кГц.

Пример конфигурации

Согласно рисунку 1, резонатор должен быть подключен напрямую к выводам TOSC1 и TOSC2. Для некоторых низковольтных устройств может потребоваться подключение внешних конденсаторов к этим выводам. Генератор оптимизирован для использования часового резонатора на частоту 32,768 кГц или внешнего тактового сигнала частотой от 0 Гц до 256 кГц. В этом примере восемь светодиодов, подключенных к порту B, используются для отображения состояния часов реального времени. Светодиод, подключенный к линии 0 порта B, изменяет свое состояние каждую секунду. Следующие шесть светодиодов отображают минуты в двоичном коде. Светодиод, подключенный к линии 7, изменяет свое состояние каждый час (час горит, следующий не горит).

Основное внимание следует обратить на режим работы таймера-счётчика в асинхронном режиме. Резонатор на частоту 32,768 кГц имеет время стабилизации после подачи напряжения до одной секунды. По этой причине контроллер не должен переходить в режим энергосбережения в течение одной секунды после включения, иначе прерывания мы никогда не дождёмся.

Реализация

Программа состоит из двух подпрограмм. Подпрограмма «counter» - это обработчик события переполнения таймера-счётчика, которая обновляет все переменные таймера при возникновении переполнения таймера. Подпрограмма «not_leap» предназначена для корректной работы с високосными годами. Основная процедура инициализирует необходимые регистры, активизируя таким образом модуль Счётчика Реального Времени, а так же управляет энергосберегающим режимом.

Бит AS2 регистра ASSR (Asynchronous Status Register) установлен таким образом, чтобы таймер-счётчик 2 тактировался от внешнего источника. Только этот таймер позволяет выполнять асинхронные операции. В момент инициализации таймер сбрасывается и выставляется требуемый коэффициент деления. Для синхронизации с внешним источником импульсов программа ждет обновления регистра ASSR. Бит TOIE2 регистра TIMSK (Timer/Counter Interrupt Mask Register) устанавливается для включения прерывания при переполнении таймера-счётчика 2. Бит Global Interrupt Enable регистра SREG (Status Register) так же должен быть установлен для включения прерываний. Биты SM1 и SM0 регистра MCUCR (MCU Control Register) установлены для выбора режима энергосбережения. Цикл основной программы вызывает инструкцию SLEEP, которая переводит контроллер в спящий режим.

Подпрограмма «counter» - обработчик прерывания при переполнении счётчика

Обработчик прерывания вызывается каждый раз, когда происходит переполнение таймера. Прерывание выводит контроллер из спящего режима и обновляет переменные таймера. Процедура обработчика прерываний не возвращает и не принимает никаких переменных. Для хранения отпечатка времени объявлена глобальная структура, содержащая переменные таймера: значение секунд, минут, часов, дней, месяцев и годов. Поскольку время, необходимое для переполнения счётчика известно (в нашем случае время переполнения счётчика составляет 1 секунду), переменную “second” каждый раз необходимо увеличивать на одно и то же значение (на ту же 1 секунду). Когда значение секунд достигнет 60, значение минут увеличивается на 1, а секунд устанавливается в 0. Более подробно алгоритм представлен на блок-схеме.

Блок-схема процедуры «counter»

Рисунок 4. Блок-схема подпрограммы «counter»

Подпрограмма «not_leap»

Эта подпрограмма проверяет, является ли год високосным. Она возвращает true, если год не високосный, и false, если високосный. Подпрограмма рассматривает год как високосный, если выполняется одно из следующих условий:

  • Если год делиться на 4;
  • Если год делится на 100, он так же может делиться на 400 (каждый четырехсотый год не високосный).

Блок-схема процедуры «not_leap»

Рисунок 5. Блок-схема подпрограммы «not_leap»

Точность

Точность Счётчика Реального Времени контроллера AVR зависит от точности часового резонатора. Асинхронные операции позволяют таймеру работать без каких либо задержек, даже если ЦПУ выполняет вычисления. Тем не менее, происходит незначительное отклонение, связанное с тем, что переменные таймера обновляются не параллельно. До окончания обновления переменных они незначительно рассинхронизированы относительно таймера-счётчика. Наибольшая разница возникает тогда, когда происходит переполнение всех переменных таймера. То есть переменная «second» имеет значение 59, переменная «minute» имеет значение 59, переменная «hour» имеет значение 23 и так далее. Обновление всех этих переменных занимает 94 такта. При частоте ЦПУ 4МГц ошибка между Счётчиком Реального Времени и часовым кварцем не превышает 23,5 мкс (рассчитывается как 94 / (4 * 106)). Типичная ошибка составляет 6 мкс учитывая то, что на обновление поля «seconds» затрачивается 24 такта. Но эта ошибка не накапливается, так как таймер всегда синхронизирован с часовым кварцем и она (ошибка) существует только во время обновления переменных таймера.

Используемые ресурсы

Таблица 3. Использование ЦПУ и памяти

Функция Размер кода (в байтах) Тактов Регистры (как пример) Прерывания Описание
main 104 - R16 Timer0 Overflow Устанавливает требуемую конфигурацию периферии
counter 356 - R16, R17, R30, R31 - Обновляет переменные таймера
not_leap 48 10 R16, R17, R20, R21 - Производит проверку на високосный год
Всего 508 - -

Таблица 4. Использование периферии

Периферия Описание Активированные прерывания
TOSC1, TOSC2 подключены к внешнему резонатору -
таймер-счётчик 2 часы реального времени Timer/Counter2 overflow
8 выводов порта B светодиоды (необходимы только для демонстрации работы устройства) -

Исходный код программы

/**** A V R  A P P L I C A T I O N  NOTE 1 3 4 ************************** 
 *
 * Название:             Часы Реального Времени
 * Версия:               2.0
 * Последнее обновление: 07.02.2009
 * Целевое устройство:   ATmega16
 *
 *
 * Описание
 * This application note shows how to implement a Real Time Clock utilizing a secondary 
 * external oscilator. Included a test program that performs this function, which keeps
 * track of time, date, month, and year with auto leap-year configuration. 8 LEDs are used
 * to display the RTC. The 1st LED flashes every second, the next six represents the
 * minute, and the 8th LED represents the hour.
 *
 ******************************************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
 
char not_leap(void);
 
typedef struct{ 
    unsigned char second;
    unsigned char minute;
    unsigned char hour;
    unsigned char date;
    unsigned char month;
    unsigned int year;
}time;
 
time t;
 
 
int main(void)
{ 
    // Ждем стабилизации внешнего резонатора.
    _delay_ms(500);
 
    // Конфигурируем порт B как выход.
    DDRB = 0xFF;
 
    // Отключаем прерывания Таймера 2.
    TIMSK &= ~(_BV(TOIE2) | _BV(OCIE2));
 
    // Переводим Таймер 2 в асинхронный режим (тактирование от
    // часового кварцевого резонатора).
    ASSR |= _BV(AS2);
 
    TCNT2 = 0x00;
    TCCR2 = 0x05; //Устанавливаем коэффициент деления равным 128.
    OCR2  = 0x00;
 
    // Ждем готовности таймера.
    while (ASSR & (_BV(TCN2UB) | _BV(OCR2UB) | _BV(TCR2UB)));
 
    // Разрешаем прерывание от Таймера 2.
    TIMSK |= _BV(TOIE2);
 
    // Разрешаем прерывания глобально.
    sei();
 
    while(1)
    {
        sleep_enable();
        sleep_cpu();
        sleep_disable();
 
        TCCR2=0x05;           // Write dummy value to Control register
 
        // Ждем готовности таймера 2.
        while (ASSR & (_BV(TCN2UB) | _BV(OCR2UB) | _BV(TCR2UB)));
    }
 
    return 0;
}
 
 
ISR(TIMER2_OVF_vect) //overflow interrupt vector
{ 
    if (++t.second==60)        //keep track of time, date, month, and year
    {
        t.second=0;
 
    if (++t.minute==60) 
        {
            t.minute=0;
 
            if (++t.hour==24)
            {
                t.hour=0;
 
                if (++t.date==32)
                {
                    t.month++;
                    t.date=1;
                }
                else if (t.date==31) 
                { 
                    if ((t.month==4) || (t.month==6) || (t.month==9) || (t.month==11)) 
                    {
                        t.month++;
                        t.date=1;
                    }
                }
                else if (t.date==30)
                {
                    if(t.month==2)
                    {
                        t.month++;
                        t.date=1;
                    }
                } 
                else if (t.date==29) 
                {
                    if((t.month==2) && (not_leap()))
                    {
                        t.month++;
                        t.date=1;
                    } 
                } 
 
                if (t.month==13)
                {
                    t.month=1;
                    t.year++;
                }
            }
        }
    } 
 
    PORTB = ~(((t.second & 0x01) | t.minute 

Tags: 
Фирма наша рекомендует аренда апартаментов в черногории от 22 - заходите . tag heuer grand carrera 36