RTC часы реального времени
В данном примере рассматривается простой вариант начальной инициализации модуля часов реального времени.
Этот пример был отлажен на микроконтроллере серии STM32F4.
MOV32 R0, RCC_BASE
@ Затактировать POWER control
@ Очевидно он был затактирован ранее
@ Во время инициализации RCC
LDR R1, [R0, RCC_APB1ENR]
ORR R1, RCC_APB1ENR_PWREN
STR R1, [R0, RCC_APB1ENR]
@ Разрешить доступ к backup domain
MOV32 R1, PWR_BASE+PWR_CR
LDR R2, [R1]
ORR R2, PWR_CR_DBP
STR R2, [R1]
Жёсткий сброс системы не влияет на состояние часов и они будут продолжать тикать,
не смотря на любые обстоятельства.
До начала процедуры инициализации вы можете проверить состояние флага INITS в регистре RTC_ISR.
Если этот флаг =1, вероятно часы уже были ранее настроены и счастливо тикают.
А значит перенастраивать их не нужно.
MOV32 R1, RTC_BASE+RTC_ISR
LDR R2, [R1]
TST R2, RTC_ISR_INITS
BNE Выход_из_настройки_часов
@ Если флаг =1 выйти из настройки
@ Иначе продолжим
@ Включаем усилитель часового кварца
LDR R1, [R0, RCC_BDCR]
ORR R1, RCC_BDCR_LSEON
STR R1, [R0, RCC_BDCR]
@ Ждём готовности часового кварца
@ Внимание! Если с кварцем будут проблемы
@ Этот цикл станет безконечным!
wait_lserdy:
LDR R1, [R0, RCC_BDCR]
TST R1, RCC_BDCR_LSERDY
BEQ wait_lserdy
Маленький комментарий. На моей тестовой платке из китая,
часовой кварц раскачивается в этом месте аж три секунды!
Система стоит и ждёт его в пустом цикле...
Что там за кварц на плате, можно догадаться..
Такие продаются на ебэе
по три копейки за мешок.
Далее:
@ Сбросим backup domain
LDR R1, [R0, RCC_BDCR]
ORR R1, RCC_BDCR_BDRST
STR R1, [R0, RCC_BDCR]
BIC R1, RCC_BDCR_BDRST
STR R1, [R0, RCC_BDCR]
@ Выбираем внешний часовой кварц
@ В качестве источника тактовых импульсов для часов
LDR R1, [R0, RCC_BDCR]
BIC R1, RCC_BDCR_RTCSEL
ORR R1, RCC_BDCR_RTCSEL_0
STR R1, [R0, RCC_BDCR]
@ Запускаем часики!
LDR R1, [R0, RCC_BDCR]
ORR R1, RCC_BDCR_RTCEN
STR R1, [R0, RCC_BDCR]
@ Начинаем работу непосредственно с регистрами часов
MOV32 R0, RTC_BASE
@ Вскроем защиту часовых регистров от записи
MOV R1, 0xCA
STR R1, [R0, RTC_WPR]
MOV R1, 0x53
STR R1, [R0, RTC_WPR]
@ Запросим режим инициализации
LDR R1, [R0, RTC_ISR]
ORR R1, RTC_ISR_INIT
STR R1, [R0, RTC_ISR]
@ Дождёмся разрешения
wait_initf:
LDR R1, [R0, RTC_ISR]
TST R1, RTC_ISR_INITF
BEQ wait_initf
@ Установим делитель в значение 32768-1
@ Что бы регистр обновился, STR нужно повторить два раза
MOV32 R1, 0x007F00FF
STR R1, [R0, RTC_PRER]
STR R1, [R0, RTC_PRER]
@ Установим какое-нибудь время, например 11:35:15
MOV32 R1, 0x00113515
STR R1, [R0, RTC_TR]
@ Установим дату, например понедельник 21 декабря 2015 года
MOV32 R1, (0x15<<16) + (1<<13) + (0x12<<8) + 0x21
STR R1, [R0, RTC_DR]
@ Выйдем из режима инициализации
LDR R1, [R0, RTC_ISR]
BIC R1, RTC_ISR_INIT
STR R1, [R0, RTC_ISR]
Выход_из_настройки_часов:
@ Закрыть доступ к backup domain
MOV32 R1, PWR_BASE+PWR_CR
LDR R2, [R1]
BIC R2, PWR_CR_DBP
STR R2, [R1]
Что ещё можно сделать..
В составе backup domain есть ещё одна полезняшка, называемая backup registers. Эти регистры являются альтернативой
EEPROM и FRAM памяти.
Они обладают всеми достоинствами встроенного ОЗУ, но требуют подпитки в дежурном режиме.
Если батарейка на часах установлена, регистры будут сохранять свои значения, потребляя нано-энергию.
Даже не предусмотрено их отключение от домена, настолько они экономичные, потому что их мало.
К backup регистрам можно обращаться по байту,
полуслову и целому слову в 32 бита.
В состав STM32F4 входит 20 регистров с именами RTC_BKP0R ... RTC_BKP19R.
Что бы получить к ним доступ на запись, нужно только установить флаг DBP.
@ Откроем доступ к backup domain
MOV32 R1, PWR_BASE+PWR_CR
LDR R2, [R1]
ORR R2, PWR_CR_DBP
STR R2, [R1]
@ Запишем что-нибудь в регистр
MOV32 R3, RTC
MOV32 R4, 0x12345678
STR R4, [R3, RTC_BKP0R]
@ Закроем backup domain
BIC R2, PWR_CR_DBP
STR R2, [R1]
Что бы прочитать backup регистр, дополнительного разрешения не требуется.
MOV32 R0, RTC
LDR R1, [R0, RTC_BKP0R]
Вот и всё.
Краткое описание часов на русском:
часть 1,
часть 2,
локальная копия.
Читайте так же
AN3371.