STM32F10x RTC闹钟无效不触发的原因和解决方案

STM32F10x RTC闹钟无效不触发的原因和解决方案

本篇文章希望通过自己解决RTC闹钟的问题经验帮助到您。

RTC闹钟原理

STM32F10x系列的RTC闹钟不同于STM32L系列,只有一个计数器。需要外部有一个RTC作为时钟晶振,由于RTC寄存器属于备份域(所谓备份域就是寄存器可以在电池供电状态下仍然保持活跃,这样即使没有外部电源,依靠电池供电是,时钟仍然会继续工作),所以在时钟配置是,需要使能PWR和BKP的时钟源,并正确初始化响应的寄存器。
RTC工作原理
从上图可以看出,如果配置好时钟后,RTC_CNT会自动开始计数,如果需要设置闹钟,那么设置RTC_ALR到一个未来的RTC_CNT值(上图标志1处),那么当相等的时候,就会产生一个RTC_Alarm信号,如果此时ALRIE(闹钟使能标志),那么ALRF置位(上图位置2),信号就到位图上位置3,如果NVIC正确配置,那么NVIC将会产生中断。

如何通过调试快速定位问题

第一步,检查中断标志是否使能
检查NVIC的RTC Global Interrupt的Enable状态是否设置。
Keil 调试状态下的NVIC寄存器使能状态
如果上面没有使能,那么RTC的闹钟中断是不会产生的,这是RTC闹钟的是否产生中断的最后一关。

第二步,检查RTC寄存器的状态
如果RTC->CRH->ARLIE没有设置,则很闹钟功能没有使能,很大可能的原因是设置RTC的时候,RTC是无效的。一般情况下查看RTC.CRL.RTOFF的状态十分为设置状态(1),如果不是,那么就是RTC初始化出现了问题,导致写寄存器无效。
在这里插入图片描述
请注意,这个RTOFF非常重要,如果不是这个状态,那么表明RTC寄存器操作失败,中断就不用考虑了
RTOFF没有置位一般就是在RTC初始化过程中没有合理使用指令导致初始化进入了一个未知的状态。RTC寄存器的操作有一套流程,必须按照这个流程才可以正确访问寄存器,因此,如果中断产生不了,请仔细核对初始化代码
下图是RTC初始化的流程:
RTC初始化流程
在STM32F10x的基础库中,RTC_WaitForLastTask就是等待RTOFF到1.
设置CNF位在基础库的函数中都有正确设置,所以无需再进行设置。

可用最简单代码

int rtc_main(){
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
	PWR_BackupAccessCmd(ENABLE);
	BKP_DeInit ();
	RCC_LSEConfig(RCC_LSE_ON);  // Enable LSE
	while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET){}
	RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
	RCC_RTCCLKCmd(ENABLE);
	RTC_WaitForSynchro(); // 这里需要等待RTC时钟可用
	
	// 这是操作RTC的寄存器(RTC_PRL, RTC_CNT, RTC_ALR)需要等待的流程
	RTC_WaitForLastTask(); 
	RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */
	RTC_WaitForLastTask();
	
	// 使能RTC Global Interrupt中断
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;			
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;	
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;		
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;		
	NVIC_Init(&NVIC_InitStructure);
	
	RTC_WaitForLastTask();
	RTC_SetAlarm(RTC_GetCounter() + 60);
	RTC_WaitForLastTask();
	RTC_ITConfig(RTC_IT_ALR, ENABLE); // 使能ALRIE
	while(1){}
}
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用 STM32F10X RTC 实时时钟的计数代码示例: ```c #include "stm32f10x.h" #include "stm32f10x_rtc.h" void RTC_Configuration(void); int main(void) { RTC_Configuration(); while (1) { RTC_TimeTypeDef RTC_TimeStruct; RTC_DateTypeDef RTC_DateStruct; RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct); RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct); // 访问 RTC 时间和日期结构体以获取实时计数值 uint32_t rtc_count = RTC_GetCounter(); // 将实时计数值显示到 LCD 或串口等外设上 } } void RTC_Configuration(void) { // 使能 PWR 和 BKP 外设时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); // 使能写入保护 PWR_BackupAccessCmd(ENABLE); // 检查备份寄存器是否有效,如果无效则初始化 RTC if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5) { RCC_LSEConfig(RCC_LSE_ON); // 使能外部低速晶体振荡器 (LSE) // 等待 LSE 稳定 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET); RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); // 选择 LSE 作为 RTC 时钟源 RCC_RTCCLKCmd(ENABLE); // 使能 RTC 时钟 RTC_WaitForSynchro(); // 等待 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); BKP_WriteBackupRegister(BKP_DR1, 0xA5A5); // 标记备份寄存器已经被初始化 } else { RTC_WaitForSynchro(); // 等待 RTC 同步完成 } } ``` 在上述代码中,我们首先定义了一个 `RTC_Configuration` 函数,它用于初始化 RTC。在此函数中,我们首先使能了 PWR 和 BKP 外设时钟,并使能了写入保护。然后,我们检查备份寄存器是否有效,如果无效则初始化 RTC。在 RTC 初始化期间,我们使用外部低速晶体振荡器 (LSE) 作为 RTC 时钟源,并设置 RTC 的分频器以获得 1 秒时钟。最后,我们使用 `BKP_WriteBackupRegister` 函数在备份寄存器中标记 RTC 已经被初始化。 在 `main` 函数中,我们使用 `RTC_GetTime` 和 `RTC_GetDate` 函数获取 RTC 的时间和日期,然后使用 `RTC_GetCounter` 函数获取实时计数值,并将其显示到外设上。 请注意,上述代码仅提供了一个 RTC 实现的基本示例。你需要根据你的具体应用程序要求对其进行修改和完善。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值