Ярлыки

_GetPixelIndex (1) _SetPixelIndex (1) 3-phase (1) 800x480 (1) АЦП (1) генератор (1) синхронный усилитель (2) структура (1) учебный курс (1) шаговый двигатель (1) ШИМ (2) accert (1) AD7608 (1) AD8429 (1) ADC (5) amplifer (1) arccos (1) arcsin (1) arctang (2) arctg (3) ARM (2) arm_sqrt_q15 (2) assembler (6) ASSERT (1) atan (2) bit (1) Bitband (1) boot (3) bootlloader (1) BUTTON (1) C (5) C# (1) CAN (2) CC2530 (5) CMSIS (4) command (1) Cordic (1) Core746I (1) CubeMX (4) DBGMCU (2) debug (2) debug.ini (1) delegate (1) Digital Potentiometers (1) DigitalPOT (1) Discovery (1) DMA (9) DMA2D (1) DSP (1) DSP library (1) DWT (1) EFM32 (5) EmWin (9) EXTI (1) FATFS (1) FMC (2) FreeRTOS (2) gl868-dual cmux (1) GPIO (4) GUI (2) GUIBuilder (1) GUIDRV_CompactColor_16 (1) HAL (3) HappyGecko (1) Hard Fault (2) heap (1) I2C (1) ID (1) ILI9320 (1) ILI9325 (1) Initialisation (1) InitLTDC (1) Instrumentithion (1) Interrupt (4) ITR (1) JTAG (1) Keil (5) LCDConf (2) lock-in (1) LTCD (1) LTDC (3) main (1) memory (1) MINI_STM32 Revision 01 (1) nBoot0 (1) NVIC (1) OnePulse (2) OSAL (4) pack (1) phase (1) printf (3) Pulse (1) PWM (12) RCC (2) RCR (1) Register (1) RESET (2) RS232 (3) RSS (1) RTC (3) RTOS-RTX (1) RTT (1) RTX-RTOS (1) SDCard (1) SDRAM (6) Segger (2) SPI (3) sqrt (3) SSD1298 (1) SSD1963 (1) Standart Peripherial Library (3) STANDBAY (1) startup (1) STemWin (8) stepper motor (1) STlink (2) STM32 (17) STM32429ZI (1) STM32Cube (1) STM32DBG.IN (1) STM32F (28) STM32F0 (4) STM32F1 (13) STM32F4 (10) STM32F4 Discovery (1) STM32F407ZG (1) STM32F429 (2) STM32F746 (1) STOP (1) string (1) struct (1) SWD (1) SWD JTAG (1) Synhronization (1) system_stm32f4xx.c (1) SystemInit (1) SysTick (1) task (4) telit (1) TIM (27) typedef (1) UART (1) USART (9) viewer (2) WM_PAINT (1) Z-stack (5) ZigBee (5)

пятница, 6 июня 2014 г.

RTC initialisation (инициализация часов) STM32F (STM32F103)

#include "stm32F10x.h"
#include "rtc.h"

//************************** Часы реального времени **************************

//****************************************************************************
//             Инициализация часов                            //
//****************************************************************************  
int  RtcInit  (void)
{
  //разрешить тактирование модулей управления питанием и управлением
  //резервной областью - enable APB1 clocks
  RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN;
  // disable backup domain write protection
//разрешить доступ к области резарвных данных
  PWR->CR |= PWR_CR_DBP;
  //если часы выключены - инициализировать их
//Bit 15 RTCEN: RTC clock enable
//Set and cleared by software.
//0: RTC clock disabled
//1: RTC clock enabled
if ((RCC->BDCR & RCC_BDCR_RTCEN) != RCC_BDCR_RTCEN)
{
//выполнить сброс области резервных данных
// reset Backup Domain
//Bit 16 BDRST: Backup domain software reset
//Set and cleared by software.
//0: Reset not activated
//1: Resets the entire Backup domain
RCC->BDCR |= RCC_BDCR_BDRST;
RCC->BDCR &= ~RCC_BDCR_BDRST;
//выбрать источником тактовых импульсов внешний кварц 32768 и подать тактирование
//Bit 15 RTCEN: RTC clock enable
//Set and cleared by software.
//0: RTC clock disabled
//1: RTC clock enabled
//Bits 9:8 RTCSEL[1:0]: RTC clock source selection
//Set by software to select the clock source for the RTC. Once the RTC clock source has been selected,
// it cannot be changed anymore unless the Backup domain is reset. The BDRST bit can be used to reset them.
//00: No clock
//01: LSE oscillator clock used as RTC clock10: LSI oscillator clock used as RTC clock
//11: HSE oscillator clock divided by 128 used as RTC clock
RCC->BDCR |= RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_LSE;
//установка маски разрешения секундных прерываний
//Bit 0 SECIE: Second interrupt enable
//0: Second interrupt is masked.
//1: Second interrupt is enabled.
RTC->CRH |= RTC_CRH_SECIE; ///!!!!!!!!!!!!SECOND INTERRUPT ENABLE
//Bit 4 CNF: Configuration flag
//This bit must be set by software to enter in configuration mode so as to allow new values to
//be written in the RTC_CNT, RTC_ALR or RTC_PRL registers. The write operation is only
//executed when the CNF bit is reset by software after has been set.
//0: Exit configuration mode (start update of RTC registers).
//1: Enter configuration mode.
RTC->CRL |= RTC_CRL_CNF;
//If the input clock frequency (fRTCCLK) is 32.768 kHz, write 7FFFh in this register to get a
//signal period of 1 second.
RTC->PRLH = 0;
RTC->PRLL = 0x8000;         //тактирование от внешнего кварца

AFIO->EVCR =0xAD; //PC13-calibration clock output enable

BKP->RTCCR |= BKP_RTCCR_CCO; //Setting this bit outputs the
//RTC clock with a frequency divided by 64 on the TAMPER pin
BKP->RTCCR |= BKP_RTCCR_ASOS | BKP_RTCCR_ASOE;
//0: Exit configuration mode (start update of RTC registers).
RTC->CRL &= ~RTC_CRL_CNF;
    //установить бит разрешения работы и дождаться установки бита готовности
RCC->BDCR |= RCC_BDCR_LSEON;
while ((RCC->BDCR & RCC_BDCR_LSEON) != RCC_BDCR_LSEON){}

//while ((RCC->BDCR & RCC_BDCR_LSERDY) != RCC_BDCR_LSERDY); //вариант

//Bit 3 RSF: Registers synchronized flag
//This bit is set by hardware at each time the RTC_CNT and RTC_DIV registers are updated
//and cleared by software. Before any read operation after an APB1 reset or an APB1 clock
//stop, this bit must be cleared by software, and the user application must wait until it is set to
//be sure that the RTC_CNT, RTC_ALR or RTC_PRL registers are synchronized.
//0: Registers not yet synchronized.
//1: Registers synchronized.
RTC->CRL &= (uint16_t)~RTC_CRL_RSF;
while((RTC->CRL & RTC_CRL_RSF) != RTC_CRL_RSF){}
return 0;
}
   return 1;
}


void RtcCorr (void)
{

/*
//разрешить тактирование модулей управления питанием и управлением
//резервной областью
RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN;
//разрешить доступ к области резарвных данных
PWR->CR |= PWR_CR_DBP;

//выполнить сброс области резервных данных
RCC->BDCR |= RCC_BDCR_BDRST;
RCC->BDCR &= ~RCC_BDCR_BDRST;
//выбрать источником тактовых импульсов внешний кварц 32768 и подать тактирование
RCC->BDCR |= RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_LSE;
//Bit 4 CNF: Configuration flag
//This bit must be set by software to enter in configuration mode so as to allow new values to
//be written in the RTC_CNT, RTC_ALR or RTC_PRL registers. The write operation is only
//executed when the CNF bit is reset by software after has been set.
//0: Exit configuration mode (start update of RTC registers).
//1: Enter configuration mode.
RTC->CRL |= RTC_CRL_CNF;
//If the input clock frequency (fRTCCLK) is 32.768 kHz, write 7FFFh in this register to get a
//signal period of 1 second.
RTC->PRLL = 0x7FF0;         //тактирование от внешнего кварца
//0: Exit configuration mode (start update of RTC registers).
RTC->CRL &= ~RTC_CRL_CNF;
    //установить бит разрешения работы и дождаться установки бита готовности
RCC->BDCR |= RCC_BDCR_LSEON;
while ((RCC->BDCR & RCC_BDCR_LSEON) != RCC_BDCR_LSEON){}

//while ((RCC->BDCR & RCC_BDCR_LSERDY) != RCC_BDCR_LSERDY); //вариант

//Bit 3 RSF: Registers synchronized flag
//This bit is set by hardware at each time the RTC_CNT and RTC_DIV registers are updated
//and cleared by software. Before any read operation after an APB1 reset or an APB1 clock
//stop, this bit must be cleared by software, and the user application must wait until it is set to
//be sure that the RTC_CNT, RTC_ALR or RTC_PRL registers are synchronized.
//0: Registers not yet synchronized.
//1: Registers synchronized.
RTC->CRL &= (uint16_t)~RTC_CRL_RSF;
while((RTC->CRL & RTC_CRL_RSF) != RTC_CRL_RSF){}
*/


// enable APB1 clocks
RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN;

// disable backup domain write protection
PWR->CR |= PWR_CR_DBP;

// set RTC prescaler: set RTC period to 1sec
RTC->CRL |= RTC_CRL_CNF; // enter config mode
RTC->PRLH = 0;
RTC->PRLL = 0x8000;

AFIO->EVCR =0xAD; //PC13-calibration clock output enable
BKP->RTCCR |= BKP_RTCCR_CCO; //Setting this bit outputs the
//RTC clock with a frequency divided by 64 on the TAMPER pin

RTC->CRL &= ~RTC_CRL_CNF; // exit config mode

// reset Backup Domain
// RCC->BDCR |= RCC_BDCR_BDRST;
// RCC->BDCR &= ~RCC_BDCR_BDRST;

RCC->BDCR &= ~(RCC_BDCR_LSEON | RCC_BDCR_LSEBYP);
// enable LSE
RCC->BDCR |= RCC_BDCR_LSEON;
// wait till LSE is ready
while (!(RCC->BDCR & RCC_BDCR_LSERDY)) ;
// select LSE as RTC clock source
RCC->BDCR |= RCC_BDCR_RTCSEL_LSE;

// enable RTC clock
RCC->BDCR |= RCC_BDCR_RTCEN;

// wait for RTC registers synchronization
    RTC->CRL &= ~RTC_CRL_RSF;
    while (!(RTC->CRL & RTC_CRL_RSF));

// set RTC prescaler: set RTC period to 1sec
RTC->CRL |= RTC_CRL_CNF; // enter config mode
RTC->PRLH = 0;
RTC->PRLL = 0x8000;

AFIO->EVCR =0xAD; //PC13-calibration clock output enable
//BKP->RTCCR |= BKP_RTCCR_CCO; //Setting this bit outputs the
//RTC clock with a frequency divided by 64 on the TAMPER pin

BKP->RTCCR |= BKP_RTCCR_ASOS | BKP_RTCCR_ASOE;

RTC->CRL &= ~RTC_CRL_CNF; // exit config mode
    while (!(RTC->CRL & RTC_CRL_RTOFF));
// enable backup domain write protection
PWR->CR &= ~PWR_CR_DBP;
    while (!(RTC->CRL & RTC_CRL_RTOFF));
}



#define FIRSTYEAR   2000 // start year
#define FIRSTDAY    1 // 0 = Sunday

static const uint8_t DaysInMonth[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

/*******************************************************************************
* Function Name  : isDST
* Description    : checks if given time is in Daylight Saving time-span.
* Input          : time-struct, must be fully populated including weekday
* Output         : none
* Return         : false: no DST ("winter"), true: in DST ("summer")
*  DST according to German standard
*  Based on code from Peter Dannegger found in the microcontroller.net forum.
*******************************************************************************/
static uint8_t isDST( const RTC_t *t )
{
uint8_t wday, month; // locals for faster access

month = t->month;

if( month < 3 || month > 10 ) { // month 1, 2, 11, 12
return 0; // -> Winter
}

wday  = t->wday;

if( t->mday - wday >= 25 && (wday || t->hour >= 2) ) { // after last Sunday 2:00
if( month == 10 ) { // October -> Winter
return 0;
}
} else { // before last Sunday 2:00
if( month == 3 ) { // March -> Winter
return 0;
}
}

return 1;
}

/*******************************************************************************
* Function Name  : adjustDST
* Description    : adjusts time to DST if needed
* Input          : non DST time-struct, must be fully populated including weekday
* Output         : time-stuct gets modified
* Return         : false: no DST ("winter"), true: in DST ("summer")
*  DST according to German standard
*  Based on code from Peter Dannegger found in the microcontroller.net forum.
*******************************************************************************/
static uint32_t adjustDST( RTC_t *t )
{
uint32_t hour, day, wday, month; // locals for faster access

hour  = t->hour;
day   = t->mday;
wday  = t->wday;
month = t->month;

if ( isDST(t) ) {
t->dst = 1;
hour++; // add one hour
if( hour == 24 ){ // next day
hour = 0;
wday++; // next weekday
if( wday == 7 ) {
wday = 0;
}
if( day == DaysInMonth[month-1] ) { // next month
day = 0;
month++;
}
day++;
}
t->month = month;
t->hour  = hour;
t->mday  = day;
t->wday  = wday;
return 1;
} else {
t->dst = 0;
return 0;
}
}
/*******************************************************************************
* Function Name  : counter_to_struct
* Description    : populates time-struct based on counter-value
* Input          : - counter-value (unit seconds, 0 -> 1.1.2000 00:00:00),
*                  - Pointer to time-struct
* Output         : time-struct gets populated, DST not taken into account here
* Return         : none
*  Based on code from Peter Dannegger found in the microcontroller.net forum.
*******************************************************************************/
static void counter_to_struct( uint32_t sec, RTC_t *t )
{
uint16_t day;
uint8_t year;
uint16_t dayofyear;
uint8_t leap400;
uint8_t month;

t->sec = sec % 60;
sec /= 60;
t->min = sec % 60;
sec /= 60;
t->hour = sec % 24;
day = (uint16_t)(sec / 24);

t->wday = (day + FIRSTDAY) % 7; // weekday

year = FIRSTYEAR % 100; // 0..99
leap400 = 4 - ((FIRSTYEAR - 1) / 100 & 3); // 4, 3, 2, 1

for(;;) {
dayofyear = 365;
if( (year & 3) == 0 ) {
dayofyear = 366; // leap year
if( year == 0 || year == 100 || year == 200 ) { // 100 year exception
if( --leap400 ) { // 400 year exception
dayofyear = 365;
}
}
}
if( day < dayofyear ) {
break;
}
day -= dayofyear;
year++; // 00..136 / 99..235
}
t->year = year + FIRSTYEAR / 100 * 100; // + century

if( dayofyear & 1 && day > 58 ) { // no leap year and after 28.2.
day++; // skip 29.2.
}

for( month = 1; day >= DaysInMonth[month-1]; month++ ) {
day -= DaysInMonth[month-1];
}

t->month = month; // 1..12
t->mday = day + 1; // 1..31
}
/*******************************************************************************
* Function Name  : struct_to_counter
* Description    : calculates second-counter from populated time-struct
* Input          : Pointer to time-struct
* Output         : none
* Return         : counter-value (unit seconds, 0 -> 1.1.2000 00:00:00),
*  Based on code from "LalaDumm" found in the microcontroller.net forum.
*******************************************************************************/
static uint32_t struct_to_counter( const RTC_t *t )
{
uint8_t i;
uint32_t result = 0;
uint16_t idx, year;

year = t->year;

/* Calculate days of years before */
result = (uint32_t)year * 365;
if (t->year >= 1) {
result += (year + 3) / 4;
result -= (year - 1) / 100;
result += (year - 1) / 400;
}

/* Start with 2000 a.d. */
result -= 730485UL;

/* Make month an array index */
idx = t->month - 1;

/* Loop thru each month, adding the days */
for (i = 0; i < idx; i++) {
result += DaysInMonth[i];
}

/* Leap year? adjust February */
if (year%400 == 0 || (year%4 == 0 && year%100 !=0)) {
;
} else {
if (t->month > 1) {
result--;
}
}

/* Add remaining days */
result += t->mday;

/* Convert to seconds, add all the other stuff */
result = (result-1) * 86400L + (uint32_t)t->hour * 3600 +
(uint32_t)t->min * 60 + t->sec;

return result;
}
/*******************************************************************************
* Function Name  : rtc_gettime
* Description    : populates structure from HW-RTC, takes DST into account
* Input          : None
* Output         : time-struct gets modified
* Return         : always true/not used
*******************************************************************************/
void rtc_gettime (RTC_t *rtc)
{
uint32_t t;
t = ((uint32_t)RTC->CNTH << 16) | RTC->CNTL;
counter_to_struct( t, rtc ); // get non DST time
adjustDST( rtc );
}

/*******************************************************************************
* Function Name  : SetCounterRTC
* Description    : sets the hardware-counter
* Input          : new counter-value
* Output         : None
* Return         : None
*******************************************************************************/
 void SetCounterRTC(uint32_t cnt)
{
/* Change the current time */
RTC->CRL |= RTC_CRL_CNF;// заходим в режим конфигурации
  RTC->CNTH = cnt>>16;
RTC->CNTL = cnt;
RTC->CRL &= ~RTC_CRL_CNF; // выходим из режима конфигурации
}

/*******************************************************************************
* Function Name  : rtc_settime
* Description    : sets HW-RTC with values from time-struct, takes DST into
*                  account, HW-RTC always running in non-DST time
* Input          : None
* Output         : None
* Return         : not used
*******************************************************************************/
void rtc_settime (const RTC_t *rtc)
{
uint32_t cnt;
volatile uint16_t i;
RTC_t ts;
cnt = struct_to_counter( rtc ); // non-DST counter-value
counter_to_struct( cnt, &ts );  // normalize struct (for weekday)
if ( isDST( &ts ) ) cnt -= 60*60; // Subtract one hour
    SetCounterRTC( cnt );
}


void RTC_setup_SPL(void)
{

  /* Allow access to Backup Registers */
  PWR_BackupAccessCmd(ENABLE);

//  if(BKP_ReadBackupRegister(BKP_DR1) != CONFIGURATION_DONE)
//  {
    /* Enable Backup and Power Interface Peripheral Clocks */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR, ENABLE);

    /* Backup Domain Reset */
    BKP_DeInit();

#ifdef USE_LSE_FOR_RTC

    /* Enable 32.768 kHz external oscillator */
    RCC_LSEConfig(RCC_LSE_ON);

    /* Wait for LSE to become ready */
    while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) continue;

/////////////////////////////////////////////////////////////////////
//// When 'USE_LSE_FOR_RTC' defined, code stops in previous call ////
//// whilst waiting for LSERDY flag to assert.                   ////
/////////////////////////////////////////////////////////////////////

    /* Set LSE as RTC clock source */
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

#elif defined USE_LSI_FOR_RTC

    /* Enable 32.000kHz internal oscillator */
    RCC_LSICmd(ENABLE);

    /* Wait until LSI is ready */
    while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) continue;

    /* Select LSI as RTC Clock Source */
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

#endif

    /* RTC Enabled */
    RCC_RTCCLKCmd(ENABLE);

    /* Wait for RTC registers synchronisation */
    RTC_WaitForSynchro();

/////////////////////////////////////////////////////////////////////
//// When 'USE_LSI_FOR_RTC' defined, code stops in previous call ////
//// whilst waiting for RSF flag to assert.                      ////
/////////////////////////////////////////////////////////////////////

    /* Wait for last RTC operation to finish */
    RTC_WaitForLastTask();
//------------------------------------------------------------------------------
// }
}

Комментариев нет:

Отправить комментарий