2017-04-04 242 views
3

我正試圖在STM32F469I-DISCO開發板上初始化RTC。由於我仍在學習,所以我嘗試使用HAL API來完成一些項目,直到有一天我能夠充分理解這個微控制器直接使用寄存器。初始化過程中STM32 RTC超時

無論如何,我的代碼使用CubeF4的STM32F469I-DISCO模板,它允許直接加載HAL層和系統時鐘(通過8 MHz HSE振盪器的180 MHz)。

爲了初始化RTC,我遵循了UM1725 : Description of STM32F4 HAL and LL drivers中給出的指示。第715頁,第55.2.4節,您有使用HAL_RTC API的說明。

而第一點說,有必要啓用「RTC域訪問」。這一點在上面的章節中解釋(55.2.3,同一頁)。

我做了要求做的事情。這裏是我的代碼(簡化,我只讓RTC Init部分和系統時鐘配置):

#include "main.h" 

RTC_HandleTypeDef rtcHandle; 
RTC_InitTypeDef rtcInit; 
RTC_TimeTypeDef rtcTime; 
RTC_DateTypeDef rtcDate; 

static void SystemClock_Config(void); 
static void Error_Handler(void); 


int main(void) 
{ 
    HAL_Init(); 
    SystemClock_Config(); 

    ////////////////// RTC 

    HAL_PWR_EnableBkUpAccess(); 
    __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE); 
    __HAL_RCC_RTC_ENABLE(); 

    rtcInit.HourFormat = RTC_HOURFORMAT_24; 
    rtcInit.AsynchPrediv = 0x7F; 
    rtcInit.SynchPrediv = 0xFF; 
    rtcInit.OutPut = RTC_OUTPUT_DISABLE; 
    rtcInit.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; 
    rtcInit.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; 

    rtcHandle.Instance = RTC; 
    rtcHandle.Init = rtcInit; 

    HAL_RTC_Init(&rtcHandle); 

    rtcTime.Hours = 12; 
    rtcTime.Minutes = 30; 
    rtcTime.Seconds = 40; 

    rtcDate.WeekDay = RTC_WEEKDAY_WEDNESDAY; 
    rtcDate.Month = RTC_MONTH_APRIL; 
    rtcDate.Date = 4; 
    rtcDate.Year= 17; 


    HAL_RTC_SetTime(&rtcHandle, &rtcTime, RTC_FORMAT_BCD); 

    while (1) 
    { 

    } 
} 

static void SystemClock_Config(void) 
{ 
    RCC_ClkInitTypeDef RCC_ClkInitStruct; 
    RCC_OscInitTypeDef RCC_OscInitStruct; 

    /* Enable Power Control clock */ 
    __HAL_RCC_PWR_CLK_ENABLE(); 

    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); 

    /* Enable HSE Oscillator and activate PLL with HSE as source */ 
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; 
    RCC_OscInitStruct.HSEState = RCC_HSE_ON; 
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; 
#if defined(USE_STM32469I_DISCO_REVA) 
    RCC_OscInitStruct.PLL.PLLM = 25; 
#else 
    RCC_OscInitStruct.PLL.PLLM = 8; 
#endif /* USE_STM32469I_DISCO_REVA */ 
    RCC_OscInitStruct.PLL.PLLN = 360; 
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; 
    RCC_OscInitStruct.PLL.PLLQ = 7; 
    RCC_OscInitStruct.PLL.PLLR = 6; 

    if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) 
    { 
    Error_Handler(); 
    } 
    /* Enable the OverDrive to reach the 180 Mhz Frequency */ 
    if(HAL_PWREx_EnableOverDrive() != HAL_OK) 
    { 
    Error_Handler(); 
    } 

    RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); 
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; 
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; 
    if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) 
    { 
    Error_Handler(); 
    } 
} 

/** 
    * @brief This function is executed in case of error occurrence. 
    * @param None 
    * @retval None 
    */ 
static void Error_Handler(void) 
{ 
    /* User may add here some code to deal with this error */ 
    while(1) 
    { 
    } 
} 

#ifdef USE_FULL_ASSERT 

/** 
    * @brief Reports the name of the source file and the source line number 
    *   where the assert_param error has occurred. 
    * @param file: pointer to the source file name 
    * @param line: assert_param error line source number 
    * @retval None 
    */ 
void assert_failed(uint8_t* file, uint32_t line) 
{ 
    /* User can add his own implementation to report the file name and line number, 
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ 

    /* Infinite loop */ 
    while (1) 
    { 
    } 
} 
#endif 

而且它不起作用。經過一些挖掘到最底層後,我設法找到它不起作用的地方。我只是不知道爲什麼。

HAL_RTC_Init()調用返回一個HAL_ERROR狀態。出現此HAL_ERROR是因爲HAL_RTC_Init()調用RTC_EnterInitMode()並返回HAL_TIMEOUT狀態,因爲在期望的時間內沒有達到條件。下面是功能:

HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc) 
{ 
    /* Check the RTC peripheral state */ 
    if(hrtc == NULL) 
    { 
    return HAL_ERROR; 
    } 

    /* Check the parameters */ 
    assert_param(IS_RTC_HOUR_FORMAT(hrtc->Init.HourFormat)); 
    assert_param(IS_RTC_ASYNCH_PREDIV(hrtc->Init.AsynchPrediv)); 
    assert_param(IS_RTC_SYNCH_PREDIV(hrtc->Init.SynchPrediv)); 
    assert_param (IS_RTC_OUTPUT(hrtc->Init.OutPut)); 
    assert_param (IS_RTC_OUTPUT_POL(hrtc->Init.OutPutPolarity)); 
    assert_param(IS_RTC_OUTPUT_TYPE(hrtc->Init.OutPutType)); 

    if(hrtc->State == HAL_RTC_STATE_RESET) 
    { 
    /* Allocate lock resource and initialize it */ 
    hrtc->Lock = HAL_UNLOCKED; 
    /* Initialize RTC MSP */ 
    HAL_RTC_MspInit(hrtc); 
    } 

    /* Set RTC state */ 
    hrtc->State = HAL_RTC_STATE_BUSY; 

    /* Disable the write protection for RTC registers */ 
    __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); 

    /* Set Initialization mode */ 
    if(RTC_EnterInitMode(hrtc) != HAL_OK) 
    { 
    /* Enable the write protection for RTC registers */ 
    __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); 
    /* Set RTC state */ 
    hrtc->State = HAL_RTC_STATE_ERROR; 

    return HAL_ERROR; 
    } 
    else 
    { 
    /* Clear RTC_CR FMT, OSEL and POL Bits */ 
    hrtc->Instance->CR &= ((uint32_t)~(RTC_CR_FMT | RTC_CR_OSEL | RTC_CR_POL)); 
    /* Set RTC_CR register */ 
    hrtc->Instance->CR |= (uint32_t)(hrtc->Init.HourFormat | hrtc->Init.OutPut | hrtc->Init.OutPutPolarity); 

    /* Configure the RTC PRER */ 
    hrtc->Instance->PRER = (uint32_t)(hrtc->Init.SynchPrediv); 
    hrtc->Instance->PRER |= (uint32_t)(hrtc->Init.AsynchPrediv << 16U); 

    /* Exit Initialization mode */ 
    hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT; 

    hrtc->Instance->TAFCR &= (uint32_t)~RTC_TAFCR_ALARMOUTTYPE; 
    hrtc->Instance->TAFCR |= (uint32_t)(hrtc->Init.OutPutType); 

    /* Enable the write protection for RTC registers */ 
    __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); 

    /* Set RTC state */ 
    hrtc->State = HAL_RTC_STATE_READY; 

    return HAL_OK; 
    } 
} 

和:

HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef* hrtc) 
{ 
    uint32_t tickstart = 0U; 

    /* Check if the Initialization mode is set */ 
    if((hrtc->Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET) 
    { 
    /* Set the Initialization mode */ 
    hrtc->Instance->ISR = (uint32_t)RTC_INIT_MASK; 

    /* Get tick */ 
    tickstart = HAL_GetTick(); 

    /* Wait till RTC is in INIT state and if Time out is reached exit */ 
    while((hrtc->Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET) 
    { 
     if((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE) 
     { 
     return HAL_TIMEOUT; 
     } 
    } 
    } 

    return HAL_OK; 
} 

所以,如果我調查很好,問題是,條件: hrtc->實例 - > ISR & RTC_ISR_INITF ==(uint32_t的) RESET的確是 (因爲TIMEOUT條件被提升)。我不明白的是根據上面的函數(EnterInitMode),RTC_ISR_INITF和ISR變量似乎是明確定義的,因此,按位操作值不是0(RESET)。

的 「ISR」 被直接函數定義且是RTC_INIT_MASK(#定義與stm32f4xx_hal_rtc.h 0xFFFFFFFF的值)

的 「RTC_ISR_INITF」 是一個宏:(0x1U < < RTC_ISR_INITF_Pos)其中RTC_ISR_INITF_Pos是6U (#define)定義在stm32f469xx.h

我錯了,如果我說「&」操作不是0?

你知道爲什麼我提出這個TIMEOUT條件嗎?

在此先感謝!

回答

3

在一個美好的夜晚之後,我解決了我的問題。我忘了在SystemClock_Config()例程中初始化LSE時鐘...我只是在SystemClock_Config()中添加下面的代碼。

RCC_OscInitTypeDef RCC_OscInitLSE; 

RCC_OscInitLSE.OscillatorType = RCC_OSCILLATORTYPE_LSE; 
RCC_OscInitLSE.LSEState = RCC_LSE_ON; 

if(HAL_RCC_OscConfig(&RCC_OscInitLSE) != HAL_OK){ 
     Error_Handler(); 
} 

我之後用STM Studio進行測試,以可視化我的變量的演變。它運作良好(以前沒有)。

抱歉給您帶來不便。