timer - STM32 RTC 初始化期间超时

标签 timer stm32 real-time-clock

我正在尝试在 STM32F469I-DISCO 板上初始化 RTC。因为我还在学习,所以我尝试使用 HAL API,它允许我实现一些项目,直到我对这个微 Controller 有足够的了解以直接使用寄存器。

无论如何,我的代码使用来自 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->Instance->ISR & RTC_ISR_INITF == (uint32_t)RESET 为真
一直(因为 TIMEOUT 条件被引发)。我不明白的是,根据上面的函数(EnterInitMode),RTC_ISR_INITF 和 ISR 变量似乎被明确定义,因此按位运算值不是 0(RESET)。

“ISR”在函数中直接定义,是RTC_INIT_MASK(#define with 0xFFFFFFFF value in stm32f4xx_hal_rtc.h)

“RTC_ISR_INITF”是一个宏:(0x1U << RTC_ISR_INITF_Pos) 其中 RTC_ISR_INITF_Pos 是 6U (#define) 在 stm32f469xx.h 中定义

如果我说 "&"操作不是 0 ,我错了吗?

你知道为什么我提出这个 TIMEOUT 条件吗?

提前致谢 !

最佳答案

经过一个美好的夜晚,我解决了我的问题。我忘记在 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 进行了测试,以可视化我的变量的演变。它运行良好(以前没有)。

带来不便敬请谅解。

关于timer - STM32 RTC 初始化期间超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43210417/

相关文章:

memory - Stm32f4内存跳转

c - 如何将命令行参数传递给半托管程序?

c - STM32F4 HAL I2C只发送地址

javascript - 如何在pubnub发布和订阅方法中显示实时时钟

linux - PPS : how to adjust system clock from PPS?

javascript - 如何在 javascript/Jquery 中重置计时器?

java - 单击按钮时清除 JLabel 中的文本

c# - 处理 WaitOne 函数卡住的定时器回调

java - 如何在java中点击按钮时使用计时器

STM32F429为什么我读不到RTC?