一、RTC简介
实时时钟是一个独立的定时器。RTC模块拥有一组连续计数的计数器,在相应软件配置下,可
提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。
RTC模块和时钟配置系统(RCC_BDCR寄存器)处于后备区域,即在系统复位或从待机模式唤醒
后,RTC的设置和时间维持不变。但是在系统复位后,会自动禁止访问后备寄存器和 RTC,
以防止对后备区域(BKP)的意外写操作。所以在要设置时间之前, 先要取消备份区域(BKP)
写保护。
二、RTC主要特性
挑了主要的特性:
1、32位的可编程计数器,可用于较长时间段的测量
2个分离的时钟:用于APB1接口的PCLK1和RTC时钟
3、可以选择以下三种RTC的时钟源:
HSE时钟除以128
LSE振荡器时钟
LSI振荡器时钟
4、2个独立的复位类型:
APB1接口由系统复位;
RTC核心(预分频器、闹钟、计数器和分频器)只能由后备域复位;
5、3个专门的可屏蔽中断:
闹钟中断,用来产生一个软件可编程的闹钟中断。
秒中断,用来产生一个可编程的周期性中断信号(最长可达1秒)。
溢出中断,指示内部可编程计数器溢出并回转为0的状态。
三、功能描述
RTC由两个主要部分组成(参见下图)。第一部分(APB1接口)用来和APB1总线相连。此单元还包
含一组16位寄存器,可通过APB1总线对其进行读写操作。APB1接口由APB1总线时钟驱动,用来与APB1总线接口。
另一部分(RTC核心)由一组可编程计数器组成,分成两个主要模块。第一个模块是RTC的预分频
模块,它可编程产生最长为1秒的RTC时间基准TR_CLK。第二个模块是一个32位的可编程计数器,可被初始化为当前的系统时间。
说白了APB1总线的作用是为RTC模块提供通信和数据传输的通道,使得RTC模块能够与其他外设进行数据交换和通信。且在系统复位后需要控制APB1总线上的RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备接口时钟使能对后备寄存器和RTC的访问
RTC预分频器控制计数频率,RTC_CNT与RTC_ALR值进行对比(和定时器类似)即产生闹钟
四、RTC寄存器描述
1、RTC控制寄存器高位(RTC_CRH)
中断使能。因为在系统复位之后所有的中断都被屏蔽(即此寄存器的所有位都被置为0),如果我们需要开启相应的中断则给相应的中断位置1(执行此操作的前提是RTC_CRL寄存器的标志位RTOFF=0)即对RTC寄存器的写操作完成。
2、RTC控制寄存器低位(RTC_CRL)
此寄存器是RTC模块的一些标志位。第 0 位是秒钟标志位,我们在进入闹钟中断的时候,通过判断这位来决定是不是发生了秒钟中断,此位只能通过软件清除。第3位为寄存器同步标志位,结合RTC框图,只有当寄存器同步后,才可以修改RTC_CRH和RTC_CRL的寄存器的值,否则修改的值无效。第4位是配置标志,即要想RTC寄存器写值时必须将此位置1。第5位,就是等待写操作完成,否则写入的值也无效。
所以RTC寄存器的配置过程应该是这样:
1. 查询RTOFF位,直到RTOFF的值变为’1’(判断写操作是否完成)
2. 置CNF值为1,进入配置模式
3. 对一个或多个RTC寄存器进行写操作
4. 清除CNF标志位,退出配置模式
5. 查询RTOFF,直至RTOFF位变为’1’以确认写操作已经完成。
3、RTC预分频装载寄存器(RTC_PRLH/RTC_PRLL)
RTC_PRLH
RTC_PRLL
这两个寄存器用来配置 RTC 时钟的分频数的,比如我们使用外部 32.768K 的晶振作为时钟的输入频率,那么我们要设置这两个寄存器的值为 32767,以得到一秒钟的计数频率。
4、RTC预分频器余数寄存器(RTC_DIVH / RTC_DIVL)
用户可通过读取RTC_DIV寄存器,以获得预分频计数器的当前值,此寄存器是只读寄存器,其值在RTC_PRL或RTC_CNT寄存器中的值发生改变后,由硬件重新装载。这两个寄存器的作用就是用来获得比秒钟更为准确的时钟,比如可以得到 0.1 秒,或者 0.01 秒等。
5、RTC计数器寄存器 (RTC_CNTH / RTC_CNTL)
RTC_CNT寄存器用来存放计数器的计数值。没过一秒此寄存器加1,可通过读取该寄存器的值来获得当前的时间。
因为没用到闹钟寄存器这里就不介绍了
五、其它寄存器
备份寄存器
数据备份寄存器,即使此寄存器断电依然可以保存数据,通过向此寄存器写入数据,当断电之后读取此寄存器的数据进行判断跳过RTC的初始化环节。
2、APB1 外设时钟使能寄存器(RCC_APB1ENR)和电源控制寄存器(PWR_CR)
系统复位后,对后备寄存器和RTC的访问被禁止,这是为了防止对后备区域(BKP)的意外写操
作。执行以下操作将使能对后备寄存器和RTC的访问:
设置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备接口时钟
设置寄存器PWR_CR的DBP位,使能对后备寄存器和RTC的访问。
3、备份域控制寄存器 (RCC_BDCR)
将LSEON位置1使能外部低速振荡器,判断LSERDY外部LSE是否就绪,最后RTCSEL置为01选择LSE最为RTC的时钟,就完成了对RTC部分对时钟的配置。
在RTC初始化的时候应该将BDRST位置1,清除备份区域
六、主函数代码文章来源:https://www.toymoban.com/news/detail-800375.html
int main(void)
{
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
LED_Init(); //LED端口初始化
OLED_Init(); //初始化OLED
RTC_Init(); //RTC初始化
OLED_ShowString(0,0,"RTC Test",12);
OLED_Refresh_Gram(); //更新显示到OLED
// t=' ';
while(1)
{
switch(calendar.week)
{
case 0:
OLED_ShowString(0,12,"Sunday",12);
break;
case 1:
OLED_ShowString(0,12,"Monday",12);
break;
case 2:
OLED_ShowString(0,12,"Tuesday",12);
break;
case 3:
OLED_ShowString(0,12,"Wednesday",12);
break;
case 4:
OLED_ShowString(0,12,"Thursday",12);
break;
case 5:
OLED_ShowString(0,12,"Friday",12);
break;
case 6:
OLED_ShowString(0,12,"Saturday",12);
break;
default:
break ;
}
OLED_ShowNum(0,24,calendar.hour,2,12);
OLED_ShowString(12,24,":",12);
OLED_ShowNum(18,24,calendar.min,2,12);
OLED_ShowString(30,24,":",12);
OLED_ShowNum(36,24,calendar.sec,2,12);
OLED_ShowNum(0,36,calendar.w_year,4,12);
OLED_ShowString(24,36,"/",12);
OLED_ShowNum(30,36,calendar.w_month,2,12);
OLED_ShowString(42,36,"/",12);
OLED_ShowNum(48,36,calendar.w_date,2,12);
OLED_Refresh_Gram(); //更新显示到OLED
}
}
RTC模块是参考原子哥的,其实大家只要把RTC功能框图和RTC相关寄存器搞熟悉之后RTC模块还是不难的。如果有其它问题可以评论或给我留言文章来源地址https://www.toymoban.com/news/detail-800375.html
到了这里,关于stm32-OLED屏+RTC实现简易实时时钟(下篇)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!