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

STM32F4VE RTC (Real-time clock)

Опубликовано stm32 - чт, 04/30/2020 - 17:02

STM32F4VE RTC (Real-time clock).

В этой статье я хочу остановиться на подключении модуля RTC который есть в микроконтроллере STM32F407VE установленном на отладочной плате STM32F4VE.  Все, что необходимо для запуска модуля в своем проекте находится в документе с названием RM0090 Reference manual
STM32F405/415, STM32F407/417, STM32F427/437 and STM32F429/439 advanced Arm®-based 32-bit MCUs. Этот  документ доступен на сайте ST.com для микроконтроллеров четвертой серии.  Все что нам нужно это установить батарейку в держатель. Сконфигурировать RTC как необходимо по задаче и из своей программы считывать необходимые для работы данные.  Единственный вопрос который остается - это точность хода счетчика и соответственно получение точных показаний времени и даты. Поэтому мы:

1. настроим RTC

2. выведем время  на LCD.

3. подключим DS3231 

4. выведем время из DS3231  на LCD.

5. Скорректируем частоту работы RTC 

Итак начнем ..

На отладочной плате STM32F407VE  установлено все необходимое держатель для батарейки которая будет питать RTC в отсутствии основного питания схемы.

 d1_9

 

d1_15

Можно проверить на всякий случай заряд батарейки д.б. желательно > 3v

Далее .. 

На  STM32F407VE  установлен внешний кварц на 32768 для RTC 

d1_10  d1_11

d1_14

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

d1_12

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

 Далее перейдем к программной части .. 

Я воспользуюсь проектом который я описал в статье STM32F4VE LCD ili9341 DS3231 Kei я дополню его модулем  RTC . 

Так как я собираюсь использовать библиотеки в дальнейшем то оформлю все отдельными файлами и добавлю их к проекту.

Файлы :

rtc.h

***********************************************************************************************

#ifndef RTC_H
#define RTC_H
#include "stm32f4xx.h" 


// Инициализация модуля
void rtc_ini(void);

#endif

***********************************************************************************************

rtc.с

**********************************************************************************************

void rtc_ini(void)
{

// Если часы до этого работали то выходим и ни чего не делаем.
if(RTC->ISR & RTC_ISR_INITS)return;

//Если настройка первоначальная - замена батарейки то делаем инициализацию заново     
    
RTC_InitTypeDef rtc_use;  // Создаем структуру для настройки RTC
RTC_TimeTypeDef rtc_time_use;  // Создаем структуру для времени    
RTC_DateTypeDef rtc_date_use; // Создаем структуру для даты
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); // Включаем тактирование

PWR_BackupAccessCmd(ENABLE);
RCC_BackupResetCmd(ENABLE);
RCC_BackupResetCmd(DISABLE);    
    
RCC_LSEConfig(RCC_LSE_ON);  // Подключаем наш припаянный кварц
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET)  {;}// Ждем когда включиться 
  
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

RCC_RTCCLKCmd(ENABLE);
RTC_WaitForSynchro();
    
 rtc_use.RTC_AsynchPrediv = 0x7F;   // т.к. у нас кварц внешний 
  rtc_use.RTC_SynchPrediv  = 0xFF;   // т.к. у нас кварц внешний 
  rtc_use.RTC_HourFormat   = RTC_HourFormat_24; // 24 часовой формат данных
  RTC_Init(&rtc_use); 

  // Устанавливаем время 0:00:00   
  rtc_time_use.RTC_H12     = RTC_H12_AM;
  rtc_time_use.RTC_Hours   = 0;
  rtc_time_use.RTC_Minutes = 0;
  rtc_time_use.RTC_Seconds = 0;  
  RTC_SetTime(RTC_Format_BCD, &rtc_time_use);
    
 // RTC_TimeStructure.RTC_H12     = RTC_H12_AM;
 // RTC_TimeStructure.RTC_Hours   = 0x05;
 // RTC_TimeStructure.RTC_Minutes = 0x20;
 // RTC_TimeStructure.RTC_Seconds = 0x00;
    
Устанавливаем дату и день недели  
// Установим дату на 30.04.20 четверг
  rtc_date_use.RTC_Year = 0x20;
  rtc_date_use.RTC_Month = RTC_Month_April;
  rtc_date_use.RTC_Date = 0x30;
  rtc_date_use.RTC_WeekDay = RTC_Weekday_Thursday;
  RTC_SetDate(RTC_Format_BCD, &rtc_date_use);
    
/* Indicator for the RTC configuration */
  RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2);     

}

******************************************************************************************

Изменим файл main.c

main.c

/****************************************************************************************************

......

#include "rtc.h"  // Подключаем созданные файлы

//
TDateTime DT;
DS3231_DateTime ds3132dt;
//

    rtc_ini(); // Инициализация RTC
    ds3132_init();
    
    ds3132dt.Hour = 0;
    ds3132dt.Minutes = 0;
    
    ds3132dt.Seconds = 0;
    
    ds3132dt.Date = 30;
    ds3132dt.Month = 4; 
    ds3132dt.Year = 20;
    ds3132dt.DayofWeek = 4;


DS3231_SetDateTime(I2C2, &ds3132dt);// set time and date

 

 while (1) {

       // Считываем данные 
        rtc_read(&DT);    // Получаем время   с RTC       
        DS3231_GetDateTime(I2C2, &ds3231dt);// Получаем время с DS3231
        delay_ms(500);
    

        lcdSetCursor(10, 80);   // xy
        lcdPrintf("RTC STM32f4 - ");

                                            
        lcdSetCursor(200, 80);   // xy
        sprintf(str019,"%02d:%02d:%02d",DT.Hours,DT.Minutes,DT.Seconds);    //выводим время        
        lcdPrintf(str019);

    
        lcdSetCursor(10, 100);   // xy
        lcdPrintf("DS3231      - ");
                                      
        lcdSetCursor(200, 100);   // xy
        sprintf(str1,"%02d:%02d:%02d",ds3132dt.Hour,ds3132dt.Minutes,ds3132dt.Seconds);    //выводим время        
        lcdPrintf(str1);
                                            
                                       
        lcdSetCursor(100, 200);   // xy
        sprintf(str019,"%02d.%02d.%02d %02d",DT.Day,DT.Month,DT.Year,DT.DayOfWeek);    //выводим дату и день недели        
        lcdPrintf(str019);

 

 

}

******************************************************************************************************************************

Выделил то что добавил в проект.

Собираем проект проверяем на ошибки, прошиваем микроконтроллер и запускаем работу в режиме отладчика. После того как отладчик загрузился - выбираем RTC в System Viewer

d1_16

Запускаем отладку 

d1_17

 

Раскрываем списке в окне RTC и в нем должны начаться счет см. видео

 

Видео файл

 

 

А на экране должно появиться 

d1_18

 

Отлично!

Все работает ! И даже считает одинаково .. В чем тогда проблема ? Проблема обнаружиться на следующий день когда часы опоздают или убегут на несколько минут. 

Как избежать этого? Один из методов ..

1. Выведем частоту кварца подключенного к STM32F407VE . Значение будет частота кварца деленная  на 64 на специально для этого выделенный порт PC13 т.е 32768 /64 = 512 - должно получиться у нас 

По схеме подключим

d1_20

 

И измерив частоту посмотрим, что у нас получается ..

Но для этого сначала убедимся, что подключенная DS3231 тоже выдает корректные данные. Для этого подключимся к ножке которая должна выдавать 32768.

d1_27

Это ножка  №1 и выведем ее на свободный пин разъема.

d1_20

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

Собираем схему и измеряем. 

В итоге на первой ножке DS3231 

d1_21

Точнее не бывает ...

Модернизируем нашу программу и добавим в инициализацию RTC порт для вывода частоты.

файл 

rtc.c

****************************************************** 

После ранее написанной строчки  

RTC_SetDate(RTC_Format_BCD, &rtc_date_use);
    
    Добавляем еще две...

  RTC_CalibOutputConfig(RTC_CalibOutput_512Hz);
  RTC_CalibOutputCmd(ENABLE);

Закомментируем строчку 

// Если часы до этого работали то выходим и ни чего не делаем она в начале функции инициализации.
//if(RTC->ISR & RTC_ISR_INITS)return;

Иначе инициализация не пройдет .

Собираем проект и прошиваем микроконтроллер.

Подключаемся к порту PC13 и получаем в моем случае на втором канале измерительного прибора

d1_22

т.е. 512.02 x 64 =  32 769,28‬ вот и она ошибка !!!!

Попробуем исправить эту ситуацию .. 

Метод исправления имеет два варианта.. Подробнее в документе под названием RM0090
Reference manual,  а также 

AN3371 Application note Using the hardware real-time clock (RTC) in STM32 F0, F2, F3, F4 and L1 series of MCUs

Два вида калибровки ...

d1_23

 

d1_24

 

а также 

 

d1_25

Воспользуемся Smooth calibration

И добавим в инициализацию RTC  следующие строки 

После внесенного ранее ..

RTC_CalibOutputConfig(RTC_CalibOutput_512Hz);
RTC_CalibOutputCmd(ENABLE);

Напишем следующее (спасибо разработчикам Keil за функцию) .

 RTC_SmoothCalibConfig(RTC_SmoothCalibPeriod_8sec, 
                                  RTC_SmoothCalibPlusPulses_Reset,
                                  0x20);  

Вот описание 

/**
  * @brief  Configures the Smooth Calibration Settings.
  * @param  RTC_SmoothCalibPeriod : Select the Smooth Calibration Period.
  *   This parameter can be can be one of the following values:
  *     @arg RTC_SmoothCalibPeriod_32sec : The smooth calibration period is 32s.
  *     @arg RTC_SmoothCalibPeriod_16sec : The smooth calibration period is 16s.
  *     @arg RTC_SmoothCalibPeriod_8sec  : The smooth calibration period is 8s.
  * @param  RTC_SmoothCalibPlusPulses : Select to Set or reset the CALP bit.
  *   This parameter can be one of the following values:
  *     @arg RTC_SmoothCalibPlusPulses_Set  : Add one RTCCLK pulse every 2**11 pulses.
  *     @arg RTC_SmoothCalibPlusPulses_Reset: No RTCCLK pulses are added.
  * @param  RTC_SmouthCalibMinusPulsesValue: Select the value of CALM[8:0] bits.
  *   This parameter can be one any value from 0 to 0x000001FF.
  * @retval An ErrorStatus enumeration value:
  *          - SUCCESS: RTC Calib registers are configured
  *          - ERROR: RTC Calib registers are not configured
*/

 

Т.к. в моем случае вместо 512 у меня 512.02 нам необходимо скорректировать до 512 .

Соберем проект с последней корректировкой и посмотрим как изменится частота на выходе микроконтроллера.

В конечном итоге ... (после нахождения цифры 20) получаем на экране заветные 512 

d1_26

Не плохо... 

Ошибка будет явно меньше чем та которая была при начальном включении.

Вывод только один. Для подобных настроек желательно иметь прибор который измеряет частоту сигнала с гораздо большим количеством нулей после запятой. Чем выше точность - тем настройка будет точнее . И скорее всего даже после того как я добился результата с двумя нулями после запятой - часы будут отставать или спешить. Но для домашнего результата это даже очень не плохо!! 

 И если посмотреть видео - практически не отличимо от DS3231  

Видео файл

 

Ура! Ура! Ура!

Во вложении файлы  system_stm32f4xx.c для правильной настройки частоты шины и скрин экрана - скачать 

Если есть вопросы или необходим исходник проекта  из статьи - пишите по адресу stm32@stm32res.ru или Website feedback

 

Яндекс.Метрика