STM32-(27):RTC实时时钟

上一篇:STM32-(26):RCC内部结构与原理分析 下一篇:STM32-(28):ADC模数转换(理论分析)

实时时钟的缩写是RTC(Real_Time Clock)

实时时钟是一个独立的定时器。RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期

RTC由两个主要部分组成。第一部分(APB1接口)用来和APB1总线相连。此单元还包含一组16位寄存器,可通过APB1总线对其进行读写操作。APB1接口以APB1总线时钟为时钟。

另一部分(RTC核)由一系列可编程计数器组成,分成两个主要模块:

第一个模块是RTC的预分频模块,它可编程产生最长为1秒的RTC时间基准TR_CLK,RTC的预分频模块包含了一个20位的可编程分频器(RTC预芬频器)。在每个TR_CLK周期中,如果在RTC_CR寄存器中设置了相应允许位,则RTC卢生一个中断(秒中断)。

第二个模块是一个32位的可编程的计数器,它可以被初始化为当前的系统时间。系统时间以TR_CLK速度增长并与存储在RTC_ALR寄存器中的可编程的时间相比较,如果RTC_CR控制寄存器设置了相应允许位则比较匹配时将产生一个闹钟中断。

在这里插入图片描述

分析

RTCCLK 外部低速时钟信号进来,先进入 RTC_DIV(分频器),RTC_PRL是装载器,然后得到一个 TR_CLK的信号,这个信号严格来说是 1s来一次,产生精确的秒信号,秒信号一路可以通过 RTC_Second,产生一个 RTC_CR 的标志位 SECF,当 SECIE 打开了(这个相当于一个开关,这个信号灯额中断允许位,表示允许秒信号输入),(SECF和SECIE是与的关系)就会产生一个中断;秒信号也可以输入到后面的 RTC_CNT计数器,这个计数器可以进行32位(2的32次方)的编程控制,当计数器寄存器的值达到设定的值就会产生 RTC_Overflow 信号,后面的 OWIE 如果打开,也会产生中断;如果设定的 RTC_ALR的值(报警),当计数器寄存器的值等于报警相关寄存器设定值,就会产生闹钟信号 RTC_Alarm,同时 ALRIE 打开,就会产生中断。这三种信号产生的中断就会进入下方的 NVIC INTERRUPT CONTRCLLER(中断控制器),相当于强制让CPU处理这个中断信号。 RTC_Alarm 和 WKUP_pin是或的关系,有任何一个信号,就会产生中断或者 进入 EXIT FROM ,就是从 常置状态跳出 ,唤醒CPU的意思;上方一整个灰色阴影区域表示这块区域的工作不是由VCC电源直接供电的(当然也可以由VCC供电),当VCC电源无效的时候或者说CPU没有工作的时候,是由后备电池供电的,这个区域称为“后备区”,系统在断电复位的情况下,不会影响后备区。比如手机电脑关机开机后,时间显示总是正确的。

主要特性

**可编程的预分频系数:**分频系数最髙为220
32位的可编程计数器,可用于较长命间段的测量。
2个单独的时钟,用于APB1接口的PCLK1和RTC时钟(此时的RTC时钟必须小于PCLK1时钟的四分之一以上)
2种独立的复位类型:
APB1接口由系统复位
RTC只能由后备域复位
3个专门的可屏蔽中断 :
闹钟中断,用来产生一个软件可编程的闹钟中断。
秒中断,用来产生一个可编程的周期性中断信号
溢出中断,检测内部可编程计数器溢出并回转为0的状态。

RTC 的一些设置是保存在后备域中的: RTC_PRL,RTC_ALR,RTC_CNT 和 RTC_DIV 寄存器。
这些寄存器器仅能通过备份域复位信号复位,不受系统复位或电源复位的影响。

备份域复位

当以下事件中之一发生时,产生备份区域复位。

  1. 软件复位,备份区域复位可由设置备份区域控制寄存器 RCC _ BDCR 中的 BDRST 位产生。
  2. 在 VDD 和 VBAT 两者掉电的前提下, VDD 或 VBAT 上电将引发备份区域复位。
对相关寄存器操作流程

要对 RTC_PRL . RTC_CNT . RTC_ALR 寄存器进行写操作, RTC 必须进入配置模式。通过对 RTC_CRL寄存器中的 CNF 位置位使 RTC 进入配置模式。另外,对 RTC 的任何寄存器的写操作都必须在前一次写操作结束以后进行。要使用软件来查询当前的状态,同可通过查询 RTC_CR 寄存器中的 RTOFF状态位来判断 RTC 寄存器是否处于更新中,仅当 RTOFF 状态位是“1”时,RTC 寄存器可以写入新的值。

配置过程:
  1. 查询 RTOFF 位,直到 RTOFF 的值变为“ 1 ”
  2. 置 CNF 值 为1 , 进入配置模式
  3. 对一个或多个 RTC 寄存器进行写操作
  4. 清除 CNF 标志位,退出配置模式
  5. 查询 RTOFF,直至RTOFF位变为“1”以确认写操作已经完成。

仅当 CNF 紅志位被清除时.写操作才能进行,这个过程至少需要3个 RTCCLK 周期

RTC相关寄存器

RTC_CRH

在这里插入图片描述
OWIE:允许溢出中断位
0:屏蔽(不允许)溢出中断
1:允许溢出中断

ALRIE:允许闹钟中断
0:屏蔽(不允许)闹钟中断
1:允许闹钟中断

SECIE:允许秒中断
0:屏蔽(不允许)秒中断
1:允许秒中断

RTC_CRL

在这里插入图片描述
RTOFF: RTC操作关闭
RTC模块利用这位来指示对其寄存器进行的最后一次操作的状态,指示操作是否完成。若此位为0,则无法对任何的RTC寄存器进行写操作。此位为只读位。
0:上一次对RTC寄存器的写操作仍在进行;
1:上一次对RTC寄存器的写操作已经完成。

CNF:配置标志
此位必须由软件置1以进入配置模式,从而允许向RTC_CNT、RTC_ALR或RTC_PRL寄存器写入数据。只有当此位在被置1后,并重新由软件清0后,才会执行写操作。
0:退出配置模式(开始更新RTC寄存器);
1:进入配置模式。

RSF:寄存器同步标志
每当RTC_CNT寄存器和RTC_DIV寄存器由软件刷新或清0时,此位由硬件置1。在APB1复位后,或APB1时钟停止后,此位必须由软件清0。要进行任何的读操作之前,用户程序必须等待这位被硬件置1,以确保RTC_CNT、RTC_ALR或RTC_PRL已经被同步。
0:寄存器尚未被同步;
1:寄存器已经被同步。

OWF:溢出标志
当32位可编程计数器溢出时,此位由硬件置1。如果RTC_CRH寄存器中OWIE=1,则产生中断。此位只能由软件清0。对此位写1是无效的。
0:无溢出;
1:32位可编程计数器溢出。

ALRF:闹钟标志
当32位可编程计数器达到RTC_ALR寄存器所设置的门限值,此位由硬件置1。如果RTC_CRH寄存器中ALRIE=1,则产生中断。此位只能由软件清0。对此位写1是无效的。
0:无闹钟;
1:有闹钟。

SECF:秒标志
当32位可编程预分频器溢出时,此位由硬件置1,RTC计数器递增。因此,此标志为分辨率可编程的RTC计数器提供一个周期性的信号(通常为1秒)。如果RTC_CRH寄存器中SECIE=1,则产生中断。此位只能由软件清除。对此位写“1”是无效的。
0:秒标志条件不成立;
1:秒标志条件成立。

RTC 计数器寄存器 (RTC_CNTH / RTC_CNTL)

RTC核有一个32位可编程的计数器,可通过两个16位的寄存器访问。计数器以预分频器产生的TR_CLK时间基准为参考进行计数。RTC_CNT寄存器用来存放计数器的计数值。他们被RTC_CR上的位RTOFF写保护,并且如果RTOFF值是1的话,允许写操作。在高或低寄存器(RTC_CNTH或RTC_CNTL)上的写操作,能够直接装载到相应的可编程计数器,并且重新装载RTC预分频器。当进行读操作时,直接返回计数器内的计数值(系统时间)。

RTC 闹钟寄存器(RTC_ALRH/RTC_ALRL )

当可编程计数器的值与RTC_ALR中的32位值相等时,即触发一个闹钟事件,并且产生RTC闹钟中断。此寄存器被RTC_CR寄存器里的RTOFF位写保护,如果RTOFF值是1时,允许写操作。

相关库函数

在这里插入图片描述
在这里插入图片描述

代码块

main.c

/*Includes----------------------------------*/
#include"stm32f10x_lib.h"		//包含所用的头文件
#include<stdio.h>

//----------------外部函数的声明------------------------------
extern void SMG_Init(void);
extern void SMG_Display(u32 data,u8 dot);  //数码管函数的声明(包含SPI函数的声明)
extern void RTC_Configuration(void);
//---------------------函数的声明---------------------------
void Delay_Ms(u16 time);
void RCC_Configuration(void);
void NVIC_Configuration(void);

extern vu8 Count;

/* Private functions ---------------------------------------------------------*/ 
/*******************************************************************************
* Function Name  : main
* Description    : Main program.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
int main(void)
{
	#ifdef DEBUG
		debug();
	#endif
   RCC_Configuration();
   RTC_Configuration();
   SMG_Init();
   NVIC_Configuration();

   while(1)
   {
   		SMG_Display(Count,3);	
   }

}

/*******************************************************************************
* Function Name  : Delay_Ms
* Description    : delay 1 ms.
* Input          : time (ms)
* Output         : None
* Return         : None
*******************************************************************************/
void Delay_Ms(u16 time)  //延时函数
{ 
	u16 i,j;
	for(i=0;i<time;i++)
  		for(j=10000;j>0;j--);
}
 /*******************************************************************************
* Function Name  : RCC_Configuration
* Description    : Configures the different system clocks.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RCC_Configuration(void)
{
	//-----------使用外部RC晶振-----------------
	RCC_DeInit();			//初始化为缺省值状态
	RCC_HSEConfig(RCC_HSE_ON);	
	while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);

	FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
	FLASH_SetLatency(FLASH_Latency_2);

	RCC_HCLKConfig(RCC_SYSCLK_Div1);
	RCC_PCLK2Config(RCC_HCLK_Div1);
	RCC_PCLK1Config(RCC_HCLK_Div2);

	RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);
	RCC_PLLCmd(ENABLE);
	while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

	RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
	while(RCC_GetSYSCLKSource()!=0x08);
}

void NVIC_Configuration(void)
{
	NVIC_InitTypeDef	NVIC_InitStructure;
	
#ifdef VECT_TAB_RAM
	NVIC_SetVectorTable(NVIC_VectTab_RAM,0x0);
#else
	NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);
#endif

	//Configure one bit for preemption priority
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQChannel;	//设置RTC中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //设置先优先级为 1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //设置亚优先级为0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	   //中断使能
	NVIC_Init(&NVIC_InitStructure);	 //初始化		
}

RTC.c

/********************************************************************
* 文件 :RTC.c
* 描述 : 实时时钟RTC模块的配置
********************************************************************/
#include"stm32f10x_lib.h"
/*************************************************************************************
**名称		;void RTC_Configuration(void)
**功能		;RTC实时时钟的配置
**入口参数	;无
**出口参数	;无
*************************************************************************************/
void RTC_Configuration(void)
{
	/* Enable PWR and BKP clocks */   //使能APB1外设PWR and BKP 的时钟  (打开电源与后备电源)
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP,ENABLE);
	
	/* Allow access to BKP Domain*/  //允许RTC 和后备寄存器的访问
	PWR_BackupAccessCmd(ENABLE);
	
	/* Reset Backup Domain*/		//将外设BKP的全部 寄存器重设为缺省值
	BKP_DeInit();
	
	/* Enable LSE */				//设置外部低速时钟
   	RCC_LSEConfig(RCC_LSE_ON);
	
	/* Wait till LSE is ready */		//等待外部低速时钟准备好
	while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
	
	/* Select LSE as RTC Clock Source */	//设置LSE为RTC时钟
	RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
	
	/* Enable RTC Clock */				//使能RT时钟
	RCC_RTCCLKCmd(ENABLE);

	/* Wait for RTC registers synchronization *///等待RTC寄存器(RTC_CNT,RTC_ALR and RTC_PRL)与RTC的APB时钟同步
	RTC_WaitForSynchro();

	/* Wait untill last write operation on RTC register has finised *///等待最近一次对RTC的写操作完成
	RTC_WaitForLastTask();

   /* Enable the RTC Second interrup */	//使能RTC的秒中断
   RTC_ITConfig(RTC_IT_SEC,ENABLE);

   /* Wait untill last write operation on RTC register has finised *///等待最近一次对RTC的写操作完成
	RTC_WaitForLastTask();

   /* Set RTC prescaler : set RTC period to 1 sec*/		//设置RTC预分频的值 为32767,则计数频率 = (32.768 KHz)/(32767+1) = 1Hz(~1s)
   RTC_SetPrescaler(32767);

    /* Wait untill last write operation on RTC register has finised *///等待最近一次对RTC的写操作完成
	RTC_WaitForLastTask();
			
}

上一篇:STM32-(26):RCC内部结构与原理分析 下一篇:STM32-(28):ADC模数转换(理论分析)
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值