RTC实时显示时间(备份电源 备份域的作用)

发布于:2024-04-14 ⋅ 阅读:(99) ⋅ 点赞:(0)

RTC初始化配置

系统复位后,可通过 PWR 电源控制寄存器 (PWR_CR) 的 DBP 位保护 RTC 寄存器以防止

非正常的写访问。必须将 DBP 位置 1 才能使能 RTC 寄存器的写访问。

上电复位后,所有 RTC 寄存器均受到写保护。通过向写保护寄存器 (RTC_WPR) 写入一个

密钥来使能对 RTC 寄存器的写操作。

要解锁所有 RTC 寄存器(RTC_ISR[13:8]、 RTC_TAFCR 和 RTC_BKPxR 除外)的写保护,

需要执行以下步骤:

1. 将“0xCA”写入 RTC_WPR 寄存器。

2. 将“0x53”写入 RTC_WPR 寄存器。

写入一个错误的关键字会再次激活写保护。

保护机制不受系统复位影响。

总结:

①将电源控制寄存器(PWR->CR)的DBP位写1     //解除RTC控制器和备份寄存器的保护

配置这个寄存器之前,要使能电源控制器时钟 RCC->APB1

②往RTC_WPR 中写 0xca  再写 0x53

取消所有寄存器的写保护

   往RTC_WPR寄存器中随便写一个数据就会再次激活写保护

设置日历寄存器要求

要编程包括时间格式和预分频器配置在内的初始时间和日期日历值,需按照以下顺序操作:

1. 将 RTC_ISR 寄存器中的 INIT 位置 1 以进入初始化模式。在此模式下,日历计数器将停

止工作并且其值可更新。

2、轮询查INITF 判断是否日历真的进入初始化模式  日历是否停止运行

3、设置时间和日期

4、退出初始化模式

总结:

要想改变日历寄存器的时间的值或者分频值,需要让日历进入初始化模式(日历停止工作)

更改完以后,要想日历继续工作,需要退出初始化模式(自由模式)

进入初始化模式

RTC->ISR 寄存器的INIT位写1

检测是否允许更新(改变)日历值位  INITF

设置日期和时间寄存器

退出初始化模式  

RTC->ISR 寄存器的INIT位写0

设置时间和日期程序

{

//进入日历初始化模式

//等待进入初始化模式完成

//设置日期和时间

//退出日历初始化模式

}

读取日历时间和日期

要想读时间和日期,要等待时间和日期同步(加载到影子寄存器),、

如何等待时间和日期同步到影子寄存器

ISR寄存器中RSF位要先清零,然后等待置1,读时间或者日期值.

获取时间和日期

{

        清零同步标志位;

        等待同步标志位置1;

        读取时间寄存器

        清零同步标志位;

        等待同步标志位置1;

        读取日期寄存器;

}

​​​​​​​寄存器

CR:

6位    0 设置时间格式     24小时

5位    0   //更新影子设置

   

ISR:

7位   进入初始化模式   先写1  配置完时间后在复位为0

6位   7位写1后,到用此位等到位1后才可以去编程时间

5位   同步标志,读日历寄存器的时候要看此位是否为1才可以读

PRER

使用默认值   15        256  分频

RTC 写保护寄存器 (RTC_WPR)

0xCA

0x53

TR

DR

BCD码

①什么是BCD码

19------0x19

0x19----19

②如何将用户的时间(十进制)设置到寄存器中

设置时间:把用户设置的十进制时间,转换成相应的BCD码,写入到寄存器中

③如何将寄存器的时间(BCD)给用户(十进制)

获取时间:把寄存器中的BCD码,转换成十进制形式,给到用户

//十进制转BDC码    //设置时间用

参数 : 十进制

返回值:BCD码结果      

13   0x13  

u8 in_dec_out_bcd(u8 dec)  

{

        return  ((dec / 10) << 4) | (dec % 10);

}

//BCD码转十进制  //读时间使用

参数  :BCD码

返回值:十进制

0x13      13   

u8 in_bcd_out_dec(u8 bcd)

{

        return  (bcd  >> 4) * 10 + (bcd & 0x0f);

}        

设置日期和时间

让日历进入初始化模式

等待等待可以改变日期和时间寄存器

将设置的十进制数据转换成BCD码

设置TR 和 DR

退出初始化模式

获取日期和时间

ISR寄存器中RSF位0

等待同步完成(等待ISR寄存器中RSF位自动变为1)

读出日期寄存器的值(BCD码)

将读出的BCD码转换成十进制形式

ISR寄存器中RSF位0

等待同步完成(等待ISR寄存器中RSF位自动变为1)

读出时间寄存器的值(BCD码)

将读出的BCD码转换成十进制形式

打印,显示

备份电源作用是:

芯片断电可以让RTC继续工作,同时备份寄存器不复位

备份寄存器的作用:

防止芯片重新上电后,CUP重置初始时间

#include "rtc.h"


/***********************************************
*函数名    :RTC_init
*函数功能  :RTC初始化配置
*函数参数  :无
*函数返回值:无
*函数描述  :			
************************************************/
void RTC_init(RTC_t time)
{
	/*解除对RTC控制器以及寄存器的写保护*/

		//使能电源控制器时钟
	RCC->APB1ENR |= (1<<28);
		//电源控制寄存器PWR_CR DBP位写1 解除RTC控制器写保护
	PWR->CR |= (1<<8);
		//使能RTC控制器时钟  RCC备份域控制寄存器
	RCC->BDCR |= (1<<0); //使能外部低速时钟
	while(!(RCC->BDCR & (1<<1)));//等待时钟就绪
	RCC->BDCR |= (1<<8);//选择LSE时钟
	RCC->BDCR |= (1<<15);//使能RTC时钟
	 //写入密钥解除RTC寄存器写保护
	RTC->WPR=0xCA;
	RTC->WPR=0x53;
	
	/*配置CR寄存器*/

	RTC->CR &=~(1<<6);//设置24小时格式
	RTC->CR &=~ (1<<5);//取影子寄存器里的值
	
	//操作完寄存器就要进行一次激活写保护
	RTC->WPR=0xff;
	
	/*设置初始时间*/
	
//	if(RTC->BKP0R !=500)  //设置备份域寄存器
//	{
//		/*设置初始时间*/
//		set_time(time);
//		RTC->BKP0R = 500;
//	}
	
		set_time(time);//调用设置时间函数
	
}

/***********************************************
*函数名    :in_dec_out_bcd
*函数功能  :将十进制数据转换成BCD码形式
*函数参数  :u8 dec
*函数返回值:u8
*函数描述  :设置时间时候使用			
************************************************/
u8 in_dec_out_bcd(u8 dec)
{
	return ((dec/10)<<4) | (dec%10);
}




/***********************************************
*函数名    :set_time
*函数功能  :设置时间函数
*函数参数  :RTC_t time
*函数返回值:无
*函数描述  :			
************************************************/
void set_time(RTC_t time)
{
	u32 temp_tr=0;
	u32 temp_dr=0;
		//解除寄存器保护
	RTC->WPR=0xCA;
	RTC->WPR=0x53;
		//进入日历寄存器进入初始化模式 ISR
	RTC->ISR |= (1<<7);
		//等待初始化结束 也就是允许更新日历寄存器
	while(!(RTC->ISR & (1<<6)));
		//设置时间和日历(10进制转bcd码)
	temp_tr=(in_dec_out_bcd(time.h))<<16 | 
					(in_dec_out_bcd(time.m))<<8  |      
					(in_dec_out_bcd(time.s));
	temp_dr=(in_dec_out_bcd(time.year-2000))<<16 | 
					(in_dec_out_bcd(time.week))<<13     | 
        	(in_dec_out_bcd(time.mon))<<8 |
					(in_dec_out_bcd(time.day));
		//设置TR和DR
	RTC->TR = temp_tr;
	RTC->DR = temp_dr;

		//退出日历初始化模式
	RTC->ISR &=~(1<<7);
		//激活写保护(操作完寄存器就要进行一次激活写保护)
	RTC->WPR=0xff;	
	
}



/***********************************************
*函数名    :in_bcd_out_dec
*函数功能  :将BCD码形式数据转换成十进制
*函数参数  :u8 bcd
*函数返回值:u8
*函数描述  :获取时间使用	
************************************************/
u8 in_bcd_out_dec(u8 bcd)
{
	return (bcd>>4)*10 + (bcd & 0x0f);
}




/***********************************************
*函数名    :get_time
*函数功能  :获取时间函数
*函数参数  :无
*函数返回值:RTC_t
*函数描述  :			
************************************************/
RTC_t get_time(void)
{
	RTC_t t;
	
	u32 temp_tr=0;
	u32 temp_dr=0;
		 //解除寄存器保护
	RTC->WPR=0xCA;
	RTC->WPR=0x53;	
		 //ISR寄存器中的RSF位0(同步清零)
	RTC->ISR &=~(1<<5);
		 //等待同步完成
	while(!(RTC->ISR & (1<<5)));
		 //读出时间寄存器的值(bcd码)
	temp_tr=RTC->TR;

		 //ISR寄存器中的RSF位0(同步清零)
	RTC->ISR &=~(1<<5);	
		 //等待同步完成
	while(!(RTC->ISR & (1<<5)));	
		 //读出日期寄存器的值(bcd码)
	temp_dr=RTC->DR;
	
			 //获取时间数据 将读出的BCD码转10进制
	t.h=in_bcd_out_dec(temp_tr>>16);
	t.m=in_bcd_out_dec(temp_tr>>8);
	t.s=in_bcd_out_dec(temp_tr);
			//获取时间数据 将读出的BCD码转10进制
	t.year=in_bcd_out_dec(temp_dr>>16)+2000;
	t.week=in_bcd_out_dec((temp_dr>>13)&0x07);
	t.mon=in_bcd_out_dec((temp_dr>>8)&0x1f);
	t.day=in_bcd_out_dec(temp_dr);

//	t.year = in_bcd_out_dec(temp_dr >> 16) + 2000;
//	t.week = in_bcd_out_dec((temp_dr & 0xe000) >> 13);
//	t.mon = in_bcd_out_dec((temp_dr & 0x1f00) >> 8);
//	t.day = in_bcd_out_dec(temp_dr>> 0);
	
		 //激活写保护
	RTC->WPR=0xff;	 
	
	return t;
		
}








设置好设置时间函数、获取时间函数后 通过定时中断可以实现1s打印一次时间


网站公告

今日签到

点亮在社区的每一天
去签到