Приветствую всех снова на нашем сайте! И сегодня мы продолжим заниматься программированием STM32, а точнее STM32F4. Казалось бы, мы уже рассмотрели огромное количество различных периферийных модулей этих микроконтроллеров, но еще ни разу не использовали RTC - Real Time CLock (часы реального времени). И в этой статье мы разберемся что же это вообще такое, как и зачем эти часы можно использовать, а также напишем маленькую программу с инициализацией RTC.
Что же делают часы реального времени, встроенные в микроконтроллеры STM32? Тут все понятно, никаких неожиданностей. Они предназначены для того, чтобы вести отсчет текущего времени. То есть по большому счету модуль RTC представляет из себя таймер, но есть одно важное отличие. Часы реального времени могут продолжать работу от резервного источника питания (например, батарейки), подключенной к выводу VBAT микроконтроллера. Что нам это дает? А то, что при выключенном устройстве часы будут тикать от резервного источника, и время будет отсчитываться корректно. Вот структурная схема из даташита:
Серым выделено то, что относится к области резервных данных, то есть то, что может питаться от резервного источника питания в отсутствие основного питания на контроллере.
Для того, чтобы часы реального времени начали отсчет, необходимо подключить источник тактирования. И здесь есть несколько вариантов:
- Во-первых, можно подключить внешний низкочастотный кварцевый резонатор на 32768 Гц. Соответственно, в этом случае при инициализации RTC в качестве источника тактовых импульсов надо выбрать LSE.
- Второй вариант - использовать внутренний низкочастотный генератор (LSI). В этом случае мы получим те же самые 32 КГц. Ну и наконец третий вариант - внешний высокочастотный генератор. В этом случае необходимо использовать предделитель частоты. С этим вроде бы все понятно.
Кроме того, часы реального времени в STM32 можно использовать в качестве будильника. Для этого есть специальный регистр RTCALR. Когда счетный регистр досчитывает до значения, хранящегося в этом регистре, контроллер формирует специальный сигнал, который может вызвать прерывание. Ну а уже в прерывании можно включить подвешенную к контроллеру звонилку-пищалку. Помимо этого есть также прерывание по переполнению счетного регистра.
Время традиционной вставки: поскольку компания STMicroelectronics прекратила поддержку библиотеки SPL, которая использовалась в этом курсе, я создал новый, посвященный работе уже с новыми инструментами, так что буду рад видеть вас там - STM32CubeMx. Кроме того, вот глобальная рубрика по STM32, а также небольшая подборка по таймерам из нового курса:
- STM32 и таймеры. STM32CubeMx. Настройка и использование.
- STM32 и watchdog. STM32CubeMx. Настройка модуля WWDG.
- STM32 и Timer Input Capture. Режим захвата сигнала.
- STM32CubeMx и watchdog. Настройка и использование IWDG.
Как видите, возможностей у RTC вполне достаточно. Минус только один - всего один счетный регистр, который считает секунды. То есть высчитывать из секунд минуты и часы нужно руками. Правда в SPL разработчики поместили специальные функции для удобной работы с временем, так что при желании можно этим и воспользоваться.
Перейдем уже к написанию программы наконец ) Пусть это будет простенькая инициализация. Наша сегодняшняя цель - увидеть отсчет секунд в счетном регистре RTC. Я буду использовать для этого отладочную плату STM32F4Discovery, ну а программу, как обычно, будем писать в Keil'е. Итак, для начала создадим новый проект (создание нового проекта для STM32F4).
Подключаем необходимые файлы:
/***************************************************************************************/ #include "stm32f4xx.h" #include "stm32f4xx_rtc.h" #include "stm32f4xx_rcc.h" #include "stm32f4xx_pwr.h" #include "stm32f4xx_conf.h" #include "system_stm32f4xx.h" /***************************************************************************************/
Для инициализации нам понадобится переменная:
/***************************************************************************************/ RTC_InitTypeDef rtc; /***************************************************************************************/
Функция инициализации:
/***************************************************************************************/ void initRTC() { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); PWR_BackupAccessCmd(ENABLE); RCC_BackupResetCmd(ENABLE); RCC_BackupResetCmd(DISABLE); RCC_LSICmd(ENABLE); RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); RCC_RTCCLKCmd(ENABLE); RTC_StructInit(&rtc); rtc.RTC_HourFormat = RTC_HourFormat_24; rtc.RTC_SynchPrediv = 0x7FFF; RTC_Init(&rtc); } /***************************************************************************************/
Тут надо разобраться подробнее... Включаем тактирование (PWR - Power Control):
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
Теперь необходимо разрешить доступ к области резервных данных, о которой уже упоминалось в начале статьи. Для этого используется функция:
PWR_BackupAccessCmd(ENABLE);
Далее выполняем Backup Domain Reset - то есть сброс RTC модуля:
RCC_BackupResetCmd(ENABLE); RCC_BackupResetCmd(DISABLE);
Включаем внутренний низкочастотный генератор и выбираем его в качестве источника тактирования для часов реального времени:
RCC_LSICmd(ENABLE); RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); RCC_RTCCLKCmd(ENABLE);
Ну и под конец настройка RTC:
rtc.RTC_HourFormat = RTC_HourFormat_24; rtc.RTC_SynchPrediv = 0x7FFF; RTC_Init(&rtc);
Что за волшебное число 0x7FFF? А все просто. У нас есть источник тактирования на 32768 Гц. А нам надо 1 Гц - то есть один импульс в секунду. Значит нужен предделитель, а 0x7FFF - это как раз 32767 и единичка добавляется аппаратно ) Не хватает в нашей программке только функции main():
/***************************************************************************************/ int main() { initRTC(); while(1); } /***************************************************************************************/
Вот и все, давайте посмотрим на результаты. Запускаем под отладчиком и смотрим на счетный регистр RTC:
Значение регистра увеличивается каждую секунду, как и задумывалось, поэтому на сегодня мы заканчиваем, скоро реализуем что-нибудь еще на RTC, например, какой-нибудь будильник...