STM32 RTC LSE 初始化失败 卡在 RTC_ICSR_INITF 或者 LSERDY

问题描述

在使用STM32 RTC时钟的时候,想使用外部的32.768K Hz的高精度带温度补偿的 LSE 时钟源。 但是调用MX_RTC_Init()初始化的时候都会卡住。debug进去,可以看到卡住的位置在这里:

  if((hrtc->Instance->ISR & RTC_ISR_INITF) == 0U)
  {
    /* Set the Initialization mode */
    hrtc->Instance->ISR = (uint32_t)RTC_INIT_MASK;

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

背景

使用的是 BL8025T 时钟芯片,此时钟芯片带有温度补偿电路,可以输出带温度补偿的32.768kHz时钟,用这个时钟来做为STM32H753的RTC低速旁路时钟(LSE)。

但是在初始化RTC时,会卡在上述过程中。


解决过程

解决过程花了3天时间,中间进行了大量的排除法,具体过程过于冗余,且我也已经记不清了,只能大概总结几点。

1.新建了一个裸机工程进行对比,发现裸机工程也跑不起来。

2.硬件同事告知可能需要把RTC电池取了,发现取了果然裸机工程可以跑了。 原理是RTC的相关配置会保存在后备寄存器中,只有把RTC电池取了,才会复位这些后备寄存器,普通的掉电复位、软件复位都是不能复位RTC相关寄存器的。

3.即使如此,我的工程还是不能跑,于是大量使用排除法,最终定位了时钟初始化函数,发现跑480MHz 100% 有问题,跑400MHz就只有10%有问题会卡住了。 但是这10%也不行啊,只能继续排除。

4.无意中打示波器发现,32.768kHz信号的电平怎么是4V,STM32不是只能接收3.3V吗? 于是让硬件同事改改,改了之后果然可行了。

最终原因

1.硬件同事给的时钟电平给错了,3.3V给成4V了。
2.RTC电池一直处于有电状态,导致复位时实际上没有复位RTC相关配置,前期调试大量都无效。

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
好的,以下是一个简单的 STM32 RTC 初始化代码示例: ```c #include "stm32f4xx.h" void RTC_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); PWR_BackupAccessCmd(ENABLE); // 使能备份寄存器访问 RCC_LSEConfig(RCC_LSE_ON); // 开启LSE振荡器 while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET); // 等待LSE稳定 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); // 设置RTC时钟源为LSE RCC_RTCCLKCmd(ENABLE); // 开启RTC时钟 RTC_InitTypeDef RTC_InitStruct; RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24; RTC_InitStruct.RTC_AsynchPrediv = 0x7F; RTC_InitStruct.RTC_SynchPrediv = 0xFF; RTC_Init(&RTC_InitStruct); // 初始化RTC RTC_TimeTypeDef RTC_TimeStruct; RTC_TimeStruct.RTC_H12 = RTC_H12_AM; RTC_TimeStruct.RTC_Hours = 0x12; RTC_TimeStruct.RTC_Minutes = 0x30; RTC_TimeStruct.RTC_Seconds = 0x00; RTC_SetTime(RTC_Format_BCD, &RTC_TimeStruct); // 设置RTC时间 RTC_DateTypeDef RTC_DateStruct; RTC_DateStruct.RTC_Date = 0x01; RTC_DateStruct.RTC_Month = RTC_Month_January; RTC_DateStruct.RTC_WeekDay = RTC_Weekday_Monday; RTC_DateStruct.RTC_Year = 0x21; RTC_SetDate(RTC_Format_BCD, &RTC_DateStruct); // 设置RTC日期 } ``` 该代码使用 LSE 振荡器作为 RTC 的时钟源,采用 24 小时制,每秒钟 RTC_CNT 计数器递增 1,ASYNC_PREDIV 和 SYNCH_PREDIV 分别为 0x7F 和 0xFF,最终 RTC 时钟频率为 32768 / (0x7F + 1) / (0xFF + 1) = 1 Hz。同时设置 RTC 的初始时间为 12:30:00,日期为 2021 年 1 月 4 日星期一。 请注意,这只是一个简单的示例代码,实际应用中需要根据具体情况进行调整和优化。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值