Advertisement
teplofizik

rtc.c

Mar 29th, 2013
1,551
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.06 KB | None | 0 0
  1. //
  2. // rtc.c STM32F4Discovery
  3. //
  4.  
  5. #include "rtc.h"
  6. #include <stm32f4xx.h>
  7.  
  8. // Выключить защиту от записи
  9. static void rtc_Unlock(void)
  10. {
  11.     // Запишем эти значения по очереди
  12.     RTC->WPR = 0xCA;
  13.     RTC->WPR = 0x53;
  14. }
  15.  
  16. // Включить защиту от записи
  17. static void rtc_Lock(void)
  18. {
  19.     // Запишем какую-нибудь фигню, главное, чтоб не правильную
  20.     RTC->WPR = 0xFF;
  21. }
  22.  
  23. // Установить дату
  24. static void rtc_SetDate(uint8_t Day, uint8_t Month, uint8_t Year, uint8_t DayOfWeek)
  25. {
  26.     uint32_t Tens, Units;
  27.     uint32_t TempReg = 0;
  28.    
  29.     // Очистим поле даты
  30.     TempReg = 0;
  31.    
  32.     // Запишем год
  33.     {
  34.         Tens  = (Year / 10) & 0x0f;          // Десятки лет
  35.         Units = (Year - (Tens * 10)) & 0x0f; // Единицы лет
  36.        
  37.         TempReg |= (Tens  << 20); // YT, 20
  38.         TempReg |= (Units << 16); // YU, 16
  39.     }
  40.     // Запишем месяц
  41.     {
  42.         Tens  = (Month / 10) & 0x01;          // Десятки месяцев
  43.         Units = (Month - (Tens * 10)) & 0x0f; // Единицы месяцев
  44.        
  45.         TempReg |= (Tens  << 12); // MT, 12
  46.         TempReg |= (Units << 8);  // MU, 8
  47.     }
  48.     // Запишем день
  49.     {
  50.         Tens  = (Day / 10) & 0x03;          // Десятки дней
  51.         Units = (Day - (Tens * 10)) & 0x0f; // Единицы дней
  52.        
  53.         TempReg |= (Tens  << 4); // DT, 4
  54.         TempReg |= (Units << 0);  // DU, 0
  55.     }
  56.     // День недели:
  57.     {
  58.         TempReg |= ((DayOfWeek & 0x07) << 13); // WDU, 13
  59.     }
  60.    
  61.     // Записывать надо всё сразу
  62.     RTC->DR = TempReg;
  63. }
  64.  
  65. // Установить время
  66. static void rtc_SetTime(uint8_t Hours, uint8_t Minutes, uint8_t Seconds)
  67. {
  68.     uint32_t Tens, Units;
  69.     uint32_t TempReg = 0;
  70.    
  71.     // Очистим поле даты
  72.     TempReg = 0;
  73.    
  74.     // Запишем часы
  75.     {
  76.         Tens  = (Hours / 10) & 0x03;          // Десятки часов
  77.         Units = (Hours - (Tens * 10)) & 0x0f; // Единицы часов
  78.        
  79.         TempReg |= (Tens  << 20); // HT, 20
  80.         TempReg |= (Units << 16); // HU, 16
  81.     }
  82.     // Запишем минуты
  83.     {
  84.         Tens  = (Minutes / 10) & 0x07;          // Десятки минут
  85.         Units = (Minutes - (Tens * 10)) & 0x0f; // Единицы минут
  86.        
  87.         TempReg |= (Tens  << 12); // MNT, 12
  88.         TempReg |= (Units << 8);  // MNU, 8
  89.     }
  90.     // Запишем секунды
  91.     {
  92.         Tens  = (Seconds / 10) & 0x07;          // Десятки секунд
  93.         Units = (Seconds - (Tens * 10)) & 0x0f; // Единицы секунд
  94.        
  95.         TempReg |= (Tens  << 4); // ST, 4
  96.         TempReg |= (Units << 0);  // SU, 0
  97.     }
  98.    
  99.     // Записывать надо всё сразу
  100.     RTC->TR = TempReg;
  101. }
  102.  
  103. // Сброс состояния часов
  104. void rtc_Reset(void)
  105. {
  106.     // Включим тактирование PWR
  107.     RCC->APB1ENR |= RCC_APB1ENR_PWREN;
  108.    
  109.     // Разрешим доступ к управляющим регистрам энергонезависимого домена
  110.     PWR->CR |= PWR_CR_DBP;
  111.    
  112.     // Выберем его как источник тактирования RTC:
  113.     RCC->BDCR |=  RCC_BDCR_BDRST;
  114.     RCC->BDCR &= ~RCC_BDCR_BDRST;
  115. }
  116.  
  117. // Инициализация модуля
  118. void rtc_Init(void)
  119. {
  120.     // Включим тактирование PWR
  121.     RCC->APB1ENR |= RCC_APB1ENR_PWREN;
  122.    
  123.     // Разрешим доступ к управляющим регистрам энергонезависимого домена (для BKP в том числе)
  124.     PWR->CR |= PWR_CR_DBP;
  125.  
  126.     // Если часы запущены, делать тут нечего.
  127.     if(RTC->ISR & RTC_ISR_INITS) return;
  128.    
  129.     // Запускаем LSI:
  130.     RCC->CSR |= RCC_CSR_LSION;
  131.    
  132.     // Ждём, когда он заведётся
  133.     while(!(RCC->CSR & RCC_CSR_LSIRDY)) {}
  134.    
  135.     // Ок, генератор на 32 кГц завёлся.
  136.    
  137.     // Сбросим состояние энергонезависимого домена
  138.     RCC->BDCR |=  RCC_BDCR_BDRST;
  139.     RCC->BDCR &= ~RCC_BDCR_BDRST;
  140.    
  141.     // Выберем его как источник тактирования RTC:
  142.     RCC->BDCR &= ~RCC_BDCR_RTCSEL; // сбросим
  143.     RCC->BDCR |= (RCC_BDCR_RTCSEL_1); // запишем 0b10
  144.        
  145.     // Включим тактирование RTC
  146.     RCC->BDCR |= RCC_BDCR_RTCEN;
  147.    
  148.     // Снимем защиту от записи с регистров RTC
  149.     rtc_Unlock();
  150.     {
  151.         // Здесь можем менять регистры RTC
  152.  
  153.         // Войдём в режим инициализации:
  154.         RTC->ISR |= RTC_ISR_INIT;
  155.        
  156.         // Ждём, когда это произойдёт
  157.         while(!(RTC->ISR & RTC_ISR_INITF)) {}
  158.        
  159.         // Часы остановлены. Режим инициализации
  160.         // Настроим предделитель для получения частоты 1 Гц.
  161.        
  162.         // LSI:
  163.         // LSE: нужно разделить на 0x7fff (кварцы так точно рассчитаны на это)
  164.         {
  165.             uint32_t Sync = 249;   // 15 бит
  166.             uint32_t Async = 127;  // 7 бит
  167.            
  168.             // Сначала записываем величину для синхронного предделителя
  169.             RTC->PRER = Sync;
  170.            
  171.             // Теперь добавим для асинхронного предделителя
  172.             RTC->PRER = Sync | (Async << 16);
  173.         }
  174.        
  175.         // Устанавливаем дату: 29.03.13, пятница
  176.         rtc_SetDate(29, 3, 13, 5);
  177.        
  178.         // Устанавливаем время: 14:37:00
  179.         rtc_SetTime(14, 37, 00);
  180.        
  181.         // Инициализация закончилась
  182.         RTC->ISR &= ~RTC_ISR_INIT;
  183.     }  
  184.     rtc_Lock();
  185.    
  186.     // Всё, часы запустились и считают время.
  187. }
  188.  
  189. // Получить текущее время
  190. void rtc_Get(TDateTime * DateTime)
  191. {
  192.     uint32_t Date = RTC->DR;
  193.     uint32_t Time = RTC->TR;
  194.    
  195.     // Год
  196.     DateTime->Year      = ((Date >> 20) & 0x0f) * 10 + ((Date >> 16) & 0x0f);
  197.     // Месяц
  198.     DateTime->Month     = ((Date >> 12) & 0x01) * 10 + ((Date >>  8) & 0x0f);
  199.     // День
  200.     DateTime->Day       = ((Date >>  4) & 0x03) * 10 + ((Date >>  0) & 0x0f);
  201.     // День недели
  202.     DateTime->DayOfWeek = ((Date >> 13) & 0x07);
  203.    
  204.     // Час
  205.     DateTime->Hours     = ((Time >> 20) & 0x03) * 10 + ((Time >> 16) & 0x0f);
  206.     // Минуты
  207.     DateTime->Minutes   = ((Time >> 12) & 0x07) * 10 + ((Time >> 8) & 0x0f);
  208.     // Секунды
  209.     DateTime->Seconds   = ((Time >> 4) & 0x07) * 10 + ((Time >> 0) & 0x0f);
  210. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement