2017-04-04 80 views
3

STM32F469I-DISCO 보드에서 RTC를 초기화하려고합니다. 내가 아직 배우기 때문에 HAL API로 게임을 시도했는데, 그 때까지 레지스터로 직접 플레이 할 수있는이 마이크로 컨트롤러에 대한 충분한 이해를 얻을 때까지 몇 가지 프로젝트를 수행 할 수있었습니다.STM32 RTC 초기화 중 타임 아웃

어쨌든 내 코드는 HAL 레이어와 시스템 클럭 (8 MHz HSE 발진기를 통해 180 MHz)을 직접로드 할 수있는 CubeF4의 STM32F469I-DISCO 템플릿을 사용합니다.

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

은 "RTC_ISR_INITF은"매크로이다 (stm32f4xx_hal_rtc.h에서 0xFFFFFFFF로 값 #DEFINE)이다 : (0x1U < < RTC_ISR_INITF_Pos) 여기서 RTC_ISR_INITF_Pos는 6U이며 (#define)

"&"작업이 0이 아니라고 말하는 것이 잘못 되었습니까?

이 TIMEOUT 조건이 발생하는 이유는 무엇입니까?

미리 감사드립니다.

답변

3

좋은 밤 이후에 문제가 해결되었습니다. SystemClock_Config() 루틴에서 LSE Clock을 초기화하는 것을 잊어 버렸습니다 ... 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 스튜디오와 이후 테스트. 그리고 그것은 잘 작동했습니다 (이전에는 없었습니다).

불편을 끼쳐 드려 죄송합니다.