Регистры RTC не сохраняются при отключении Vbat 3,3 В и VCC

#c #clock #stm32f4discovery #real-time-clock

Вопрос:

В настоящее время я пытаюсь отобразить время и дату с помощью микроконтроллера STM32F407VGTX, однако у меня возникли некоторые проблемы. Основная проблема возникает при переключении с напряжения VDD на напряжение VBAT. Часы сбрасываются, когда этого не должно быть. Действительно, в таблице данных нам сказано, что регистры RTC сбрасываются только в том случае, если два напряжения VBAT и VDD выключены. Я инициализировал время с помощью EtatClock_t RTC_init(void) функции, затем, когда я понижаю напряжение питания, часы автоматически сбрасываются. Тем не менее я следовал порядку запуска часов. Вы нашли решения?

   typedef enum
  {
    FirstInit,
    KO,
    AlreadyInit
  } EtatClock_t;

  typedef struct {
    int tm_sec;
    int tm_min;
    int tm_hour;
    int tm_mday;    //date 
    int tm_mon;     //month
    int tm_year;    //year
    int tm_wday;    
  }rtc_time_t;

EtatClock_t RTC_init(void)
  {
        uint32_t reg32;
        // Enable the PWR peripheral
        RCC->APB1ENR |= RCC_APB1ENR_PWREN;

        // Access to RTC, RTC Backup and RCC CSR registers enabled
        PWR->CR |= PWR_CR_DBP;

        if(RTC->ISR amp; RTC_ISR_INITS)
            return AlreadyInit;

        // Turn on LSE and wait until it become stable
        // Reset LSEON and LSEBYP bits before configuring the LSE ------------------
        // Reset LSEON bit

        reg32 = RCC->BDCR;
        reg32 amp;= ~(RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL | RCC_BDCR_LSERDY | RCC_BDCR_LSEON);
        reg32 |= (1<<RCC_BDCR_RTCSEL_Pos);  // Select LSE as clock source
        RCC->BDCR = reg32 | RCC_BDCR_BDRST; // BDRST reset
        RCC->BDCR = reg32;                  // end of reset
        reg32 |= RCC_BDCR_LSEON;
        RCC->BDCR = reg32;                  // external low-speed oscillator enable

        while(!(RCC->BDCR amp; RCC_BDCR_LSERDY));  // wait for oscillator ready
        RCC->BDCR = reg32 | RCC_BDCR_RTCEN; // RTC clock enable

        // Disable the write protection for RTC registers
        RTC->WPR = 0xCA;
        RTC->WPR = 0x53;
        // Wait for the RTC APB registers synchronization
        if (RTC_WaitForSynchro() != SUCCESS) {
            // Enable the write protection for RTC registers
            RTC->WPR = 0xFF;
            // Access to RTC, RTC Backup and RCC CSR registers disabled
            PWR->CR amp;= ~PWR_CR_DBP;

            return KO;
        }
        // Enter the RTC initialization mode
        if (RTC_EnterInitMode() != SUCCESS) {
            // Enable the write protection for RTC registers
            RTC->WPR = 0xFF;
            // Access to RTC, RTC Backup and RCC CSR registers disabled
            PWR->CR amp;= ~PWR_CR_DBP;

            return KO;
        }
        // Clear RTC CR FMT Bit (24-hour format)
        RTC->CR amp;= ~RTC_CR_FMT;
        // Configure the RTC prescaler
        RTC->PRER = 0x007f00ff; // Asynch = 128, Synch = 256

        // Exit the RTC Initialization mode
        RTC->ISR amp;= ~RTC_ISR_INIT;
        // Enable the write protection for RTC registers
        RTC->WPR = 0xFF;
        // Access to RTC, RTC Backup and RCC CSR registers disabled
        PWR->CR amp;= ~PWR_CR_DBP;

        return FirstInit;
    }
 

Я использую эти две функции ErrorStatus RTC_WaitForSynchro(void) и ErrorStatus RTC_EnterInitMode(void) .

   ErrorStatus RTC_WaitForSynchro(void)
  {

    // Clear the RSF flag
    RTC->ISR amp;= ~RTC_ISR_RSF;

    // Wait the registers to be synchronized
    while (!(RTC->ISR amp; RTC_ISR_RSF));

    return (RTC->ISR amp; RTC_ISR_RSF) ? SUCCESS : ERROR;
  }

  // Enters the RTC Initialization mode
  // return: SUCCESS if RTC is in initialization mode, ERROR otherwise
  // note: write protection to RTC registers must be disabled (RTC_WPR = 0xCA,0x53)
  // note: access to the RTC registers must be enabled (bit DBP set in PWR_CR register)

  ErrorStatus RTC_EnterInitMode(void) {

    if (!(RTC->ISR amp; RTC_ISR_INITF)) {
        // Set the initialization mode
        RTC->ISR = RTC_ISR_INIT;

        // Wait till RTC is in INIT state or timeout
        while (!(RTC->ISR amp; RTC_ISR_INITF));

    return (RTC->ISR amp; RTC_ISR_INITF) ? SUCCESS : ERROR;
  }
 

Для отображения времени и даты я использую эти две функции ErrorStatus RTC_SetDateTime(rtc_time_t *time) и void RTC_GetDateTime(rtc_time_t *time)

  ErrorStatus RTC_SetDateTime(rtc_time_t *time)
  {

    uint32_t TR,DR;

    // Calculate value for time register
    TR =   (((time->tm_hour   / 10) << 20)   ((time->tm_hour   % 10) << 16)  
            ((time->tm_min / 10) << 12)   ((time->tm_min % 10) <<  8)  
            ((time->tm_sec / 10) <<  4)    (time->tm_sec % 10)) ;
             // (time->RTC_H12 << 12)) amp; RTC_TR_RESERVED_MASK;
    // Calculate value for date register
    DR =   ((((time->tm_year-2000)  / 10) << 20)   (((time->tm_year-2000)  % 10) << 16)  
            ((time->tm_mon / 10) << 12)   ((time->tm_mon % 10) <<  8)  
            ((time->tm_mday  / 10) <<  4)    (time->tm_mday  % 10));

    // Access to RTC, RTC Backup and RCC CSR registers enabled
    PWR->CR |= PWR_CR_DBP;
    // Disable the write protection for RTC registers
    RTC->WPR = 0xCA;
    RTC->WPR = 0x53;

    // Enter the RTC initialization mode
    if (RTC_EnterInitMode() == SUCCESS) {
        // Write date and time to the RTC registers
        RTC->TR = TR;
        RTC->DR = DR;

        // Exit the RTC Initialization mode
        RTC->ISR amp;= ~RTC_ISR_INIT;

        // Wait for synchronization if BYPSHAD bit is not set in the RTC_CR register
        TR = SUCCESS;
        if (!(RTC->CR amp; RTC_CR_BYPSHAD)) {
            TR = RTC_WaitForSynchro();
        }
    } else TR = ERROR;

    // Enable the write protection for RTC registers
    RTC->WPR = 0xFF;
    // Access to RTC, RTC Backup and RCC CSR registers disabled
    PWR->CR amp;= ~PWR_CR_DBP;

    return TR;
  }

  // Get current date and time
  // input:
  //   Time - pointer to RTC time structure
  //   Date - pointer to RTC date structure
  // return: date and time in Time and Date structures
  void RTC_GetDateTime(rtc_time_t *time)
  {
    uint32_t TR,DR;

    // Get date and time (clear reserved bits just for any case)
    TR = RTC->TR amp; RTC_TR_RESERVED_MASK;
    DR = RTC->DR amp; RTC_DR_RESERVED_MASK;

    // Convert BCD to human readable format
    time->tm_hour   = (((TR >> 20) amp; 0x03) * 10)   ((TR >> 16) amp; 0x0f);
    time->tm_min = (((TR >> 12) amp; 0x07) * 10)   ((TR >>  8) amp; 0x0f);
    time->tm_sec = (((TR >>  4) amp; 0x07) * 10)    (TR amp; 0x0f);
    time->tm_year    = (((DR >> 20) amp; 0x03) * 10)   (((DR >> 16) amp; 0x0f) 2000);
    time->tm_mon   = (((DR >> 12) amp; 0x01) * 10)   ((DR >>  8) amp; 0x0f);
    time->tm_mday    = (((DR >>  4) amp; 0x03) * 10)    (DR amp; 0x0f);
    time->tm_wday = (DR amp; RTC_DR_WDU) >> 13;
  }
 

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

1. Возможно, вы захотите вместо этого спросить об обмене стеком электротехники , так как это больше похоже на проблему с оборудованием, а не с программированием.