RTC на STM32 и реализация календаря (с рабочей библиотекой)
Всем Доброго Времени Суток! В данной статье хотелось бы рассказать о запуске часов реального времени (RTC), и реализации календаря на STM32, а точнее на отладочной плате STM32-P103.
При написании данной статьи пользовался сл. источниками:
Как подключать и настраивать дисплей можно посмотреть здесь
Вот собственно код для запуска и настройки RTC:
#include "stm32f10x.h"
#include "stdio.h"
#include "delay.h"
#include "unix_time.h"
char LCDBUF[50];
uint32_t timer=1384850400+14400;
uint32_t tim;
void RTC_INIT (void) //Инициализация RTC
{
if ((RCC->BDCR & RCC_BDCR_RTCEN) != RCC_BDCR_RTCEN) //Проверка работы часов, если не включены, то инициализировать
{
RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN; //Включить тактирование PWR и Backup
PWR->CR |= PWR_CR_DBP; //Разрешить доступ к Backup области
RCC->BDCR |= RCC_BDCR_BDRST; //Сбросить Backup область
RCC->BDCR &= ~RCC_BDCR_BDRST;
RCC->BDCR |= RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_LSE; //Выбрать LSE источник (кварц 32768) и подать тактирование
RCC->BDCR |= RCC_BDCR_LSEON; //Включить LSE
while ((RCC->BDCR & RCC_BDCR_LSEON) != RCC_BDCR_LSEON){} //Дождаться включения
BKP->RTCCR |= 3; //калибровка RTC
while (!(RTC->CRL & RTC_CRL_RTOFF)); //проверить закончены ли изменения регистров RTC
RTC->CRL |= RTC_CRL_CNF; //Разрешить Запись в регистры RTC
RTC->PRLL = 0x7FFF; //Настроит делитель на 32768 (32767+1)
RTC->CRL &= ~RTC_CRL_CNF; //Запретить запись в регистры RTC
while (!(RTC->CRL & RTC_CRL_RTOFF)); //Дождаться окончания записи
RTC->CRL &= (uint16_t)~RTC_CRL_RSF; //Синхронизировать RTC
while((RTC->CRL & RTC_CRL_RSF) != RTC_CRL_RSF){} //Дождаться синхронизации
PWR->CR &= ~PWR_CR_DBP; //запретить доступ к Backup области
}
}
uint32_t RTC_GetCounter_(void) //Получить значение счетчика
{
return (uint32_t)((RTC->CNTH << 16) | RTC->CNTL);
}
void RTC_SetCounter_(uint32_t count) //Записать новое значение счетчика
{
RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN; //включить тактирование PWR и Backup
PWR->CR |= PWR_CR_DBP; //разрешить доступ к Backup области
while (!(RTC->CRL & RTC_CRL_RTOFF)); //проверить закончены ли изменения регистров RTC
RTC->CRL |= RTC_CRL_CNF; //Разрешить Запись в регистры RTC
RTC->CNTH = count>>16; //записать новое значение счетного регистра
RTC->CNTL = count;
RTC->CRL &= ~RTC_CRL_CNF; //Запретить запись в регистры RTC
while (!(RTC->CRL & RTC_CRL_RTOFF)); //Дождаться окончания записи
PWR->CR &= ~PWR_CR_DBP; //запретить доступ к Backup области
}
int main(void)
{
unix_cal unix_time;
LCD_INIT(); //Инициализируем LCD
RTC_INIT(); //Инициализируем RTC
RTC_SetCounter_(timer); //Записать новое значение счетчика
while(1)
{
timer=RTC_GetCounter_(); //Получить значение счетчика
timer_to_cal (timer, &unix_time); //Получит из счетчика календарь и время
tim=cal_to_timer(&unix_time); //Получить из значения календаря и времени счетчик
LCD_CLEAR(); //очистить LCD
sprintf(LCDBUF,"%i",unix_time.mday ); //Вывести
LCD_PUT(LCDBUF); //
LCD_PUT("."); //на
sprintf(LCDBUF,"%i",unix_time.mon ); //
LCD_PUT(LCDBUF); //LCD
LCD_PUT("."); //
sprintf(LCDBUF,"%i",unix_time.year ); //Дату
LCD_PUT(LCDBUF); //
LCD_PUT(" "); //и
LCD_GOTO(0,1); //
sprintf(LCDBUF,"%i",unix_time.hour ); //Время
LCD_PUT(LCDBUF); //
LCD_PUT(":"); //
sprintf(LCDBUF,"%i",unix_time.min ); //
LCD_PUT(LCDBUF); //
LCD_PUT(":"); //
sprintf(LCDBUF,"%i",unix_time.sec ); //
LCD_PUT(LCDBUF); //
delay_ms(100);
}
}
Вот этого хватит что бы у вас заработали часы с календарем на вашем STM.
Результат:
Подключаем батарейку, комментируем вот эту строчку:
RTC_SetCounter_(timer); //Записать новое значение счетчика
и прошиваем еще раз, что бы при подачи основного питания не перезаписывался счетчик.
Теперь у вас ходят часы не зависимо от внешнего питания. Если вы решите делать на этой же отладочной плате, то не забудьте убрать перемычку:
Это необходимо для того что бы батарейка запитывала только RTC и BKP, иначе она запитывает полностью весь контроллер.
Библиотека для перевода счетчика в календарь и время, и обратно, находится здесь.
Если вы заметили, в программе имеется сл. строка:
BKP->RTCCR |= 3; //калибровка RTC
Это калибровка RTC. Как ее правильно рассчитать объясню в сл. статье.
Обратная связь
Интересуют вопросы реализации алгоритмов, программирования, выбора электроники и прочая информация, постараюсь осветить в отдельных статьях
пишите мне на netdm@mail.ru