RTC实时时钟

这篇具有很好参考价值的文章主要介绍了RTC实时时钟。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.概述

1.1概念

RTC实时时钟通常是指一个集成电路,RTC本质上是一个独立的定时器,通常情况下需要外接一个32.768KHZ的晶振和匹配电容(10~33pf),由于时间是不停止的,为了满足这一要求,所以RTC实时时钟有两种供电方式:

1)在设备正常运行的时候,RTC实时时钟模块是由MCU主电源进行供电。

2)在主电源停止供电的时候,RTC实时时钟由备份电源(纽扣电池)来进行供电,保证当MCU停止供电的情况下,RTC不受影响,保持正常工作。

1.2时间基准

1)基于Windows操作系统:1900年1月1日00:00:00

2)基于Linux操作系统:1970年1月1日00:00:00

2.RTC模块(stm32f40x)

2.1简介

STM32F40x实时时钟(RTC)模块是一个独立的BCD码定时器/计数器,除了可以正常的提供日历功能外,还可以对MCU进行唤醒。并且在MCU复位后,RTC的寄存器是不允许正常访问的(无法对RTC寄存器进行写操作,但可以进行读操作寄存器)。

2.2特性

(1)可以直接提供,秒,分钟,小时(12/24小时制)、星期几、日期、月份、年份的日历

(2)具有闹钟功能,并且可以对闹钟进行日期编程。

(3)具有自动唤醒单元,可以周期性的更新事件显示

(4)RTC模块的中断源为:闹钟A,闹钟B,唤醒,时间戳以及入侵检测

(5)RTC模块具有独立备份区域,可以对发生入侵事件的时间进行保存。

2.3配置

2.3.1 RTC写保护

1)、在系统复位后,需要把电源控制寄存器(PWR_CR)的DBP位置1,以使能RTC寄存器的写访问。

2)、上电复位后,需要早通过向写保护寄存器(RTC_WPR)写入0XCA和0x53,来解除寄存器的写保护,写入一个错误的数值(除了0xCA和0x53)会再次激活写保护。

2.3.2日历初始化和配置

1)、首先需要把初始化状态寄存器(RTC_ISR)中的INIT位置1,进入初始化模式,在次模式下,日历计数器将停止工作并且寄存器中的值是可以被更新的。

2)、配置为初始化模式后,RTC寄存器不能立即进入初始化状态,所以在配置为初始化模式后,必须轮询等待初始化寄存器(RTC_ISR)中的INIT位置1,才可以更新时间和日期。

3)、设置RTC_PRER寄存器中的同步预分频器和异步预分频器,把时钟的频率设置为1HZ。

4)、设置RTC_TR,RTC_DR寄存器中的时间和日期,并在RTC_CR寄存器中的FMT位设置时间的格式(12小时制或24小时制)

5)、对初始化寄存器(RTC_ISR)中的INIT位清0则退出初始化模式,当初始化模式序列完成后,日历开始计数。

2.3.3 RTC闹钟配置

1)、把控制寄存器(RTC_CR)中的闹钟A和闹钟B的使能位清零,关闭闹钟A和闹钟B。

2)、轮询等待初始化状态寄存器(RTC_ISR)寄存器中的闹钟写入标志位置1,进入闹钟的编程模式。

3)、根据需要,对闹钟A寄存器(RTC_ALRMAR)和闹钟B寄存器(RTC_ALRMBR)的闹钟值和产生闹钟的条件进行编译。

4)、把控制寄存器(RTC_CR)中的闹钟A(ALRAE)和闹钟B(ALRBE)的使能位置1,使能闹钟A和闹钟B。

5)、设置闹钟中断。

6)、编写闹钟中断服务函数。

2.3.4 读取日历

由于日历和时间寄存器都存在影子寄存器,所以在读取时间和日历值之前,必须保证影子寄存器的数据和上层寄存器的值同步(等待日历和时间标志位被置1,RTC_ISR[5]),才能读取时间和日历寄存器。

3、寄存器

3.1 RTC 时间寄存器 (RTC_TR)

存放RTC模块的时间数据,存储方式是以BCD码的格式来存储。

rtc,实时音视频,Powered by 金山文档

3.2 RTC 日期寄存器 (RTC_DR)

存放RTC模块的日期数据,存储方式是以BCD码的格式来存储。

rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档

3.3 RTC 控制寄存器 (RTC_CR)

设置RTC模块的工作模式

rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档

3.4 RTC 初始化和状态寄存器 (RTC_ISR)

存放RTC模块的初始化状态标志位

rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档

3.5 RTC 预分频器寄存器 (RTC_PRER)

存放RTC模块预分频值,这个寄存器包含异步预分频器和同步预分频器。如果更改其中一个分频值,都必须对异步和同步预分频器单独操作一次。

rtc,实时音视频,Powered by 金山文档

3.6 RTC 唤醒定时器寄存器 (RTC_WUTR)

存放唤醒计数重装载值。

rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档

3.7 RTC 闹钟 A 寄存器 (RTC_ALRMAR)

存放闹钟A的闹钟值,存储方式都是以BCD码存储。

rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档

3.8 RTC 闹钟 B 寄存器 (RTC_ALRMBR)

存放闹钟B的闹钟值,存储方式都是以BCD码存储。

rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档

3.9 RTC 写保护寄存器 (RTC_WPR)

解除RTC模块的写保护,以及激活写保护。

rtc,实时音视频,Powered by 金山文档

3.10 RTC 备份寄存器 (RTC_BKPxR)

后备区域存储器,用户可对这些寄存器写入数据或者读出数据,可以通过在备份寄存器中写入国定的数据来判断芯片是否是第一次使用RTC,在系统复位后运行RTC初始化时,提示是否需要配置时间。

rtc,实时音视频,Powered by 金山文档

3.11 电源控制寄存器(PWR_CR)

这个寄存器再使用RTC模块时,只使用到了第8位(DBP)。

rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档

3.12 RCC 备份域控制寄存器 (RCC_BDCR)

RTC模块时钟源选择以及使能RTC模块时钟。文章来源地址https://www.toymoban.com/news/detail-841735.html

rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档
rtc,实时音视频,Powered by 金山文档

4、例程

#include "rtc.h"

/*
函数名称:u8 Rtc_Init(void)
函数功能:RTC 初始化
函数形参:无
函数返回值:1----失败;0-----成功
*/

char *time = __TIME__;
char *date = __DATE__;
char *month[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
_time my_time;
u8 year1,month1,day1;
u8 buff1[9];

u8 Rtc_Init(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    u32 temp = 0;


    RCC->APB1ENR |= 1 <<28;//开启电源接口时钟
    PWR->CR  |= 1 << 8;//开启备份域访问
    
    //选择时钟源
    RCC->BDCR &= ~(3 << 8);
    RCC->BDCR |= 1 << 8;//选择外部低速时钟
    RCC->BDCR |= 1 << 0;//开启外部低速时钟使能
    
    //等待外部时钟就绪
    while(!(RCC->BDCR & (1 << 1)))
    {
        temp++;
        TIM3_us(1);
        if(temp >= 100000)
        {
            return 1;//起振失败
        }
    }
    
    RCC->BDCR |= 1 << 15;//开启RTC时钟使能
    
    RTC_WaitForLastTask();//等待标志位RTOFF置1(等待上次写操作完成)
    RTC_EnterConfigMode();//进入配置模式
    
    RTC_SetPrescaler(32768-1);      //设置预分频系数
    //获取时间
    my_time.hour = (time[0] - '0') * 10 + (time[1] - '0');
    my_time.min = (time[3] - '0') * 10 + (time[4] - '0');
    my_time.sec = (time[6] - '0') * 10 + (time[7] - '0');
    //获取日期
    my_time.year = (date[9] - '0') * 10 + (date[10] - '0') + 2000;
    if(date[4] !=  ' ')
    {
        my_time.day = (date[4] - '0') * 10 + (date[5] - '0');
    }
    else
    {
        my_time.day = (date[5] - '0');
    }
    
    for(u8 i = 1;i <= 12;i++)
    {
        if(strncmp(date,month[i - 1],3) == 0)
        {
            my_time.mon = i;
            break;
        }
    }
    year1 = (date[9] - '0') * 10 + (date[10] - '0');
    month1 = my_time.mon;
    day1 = my_time.day;
    //设置时间
    RTC_Set_Time(my_time.year,my_time.mon,my_time.day,my_time.hour,my_time.min,my_time.sec);
    
    RTC_WaitForLastTask();//等待写操作完成
    RTC_ExitConfigMode();//退出配置模式
    printf(" RTC 初始化成功\r\n");

    RTC_WaitForSynchro();//等待 RTC 与 APB1 同步


    NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    //设置为秒中断
    RTC_ITConfig(RTC_IT_SEC,ENABLE);
    
    return 0;
}

void RTC_IRQHandler(void)
{
    if(RTC_GetITStatus(RTC_IT_SEC) != RESET)
    {
        RTC_ClearITPendingBit(RTC_IT_SEC);
        RTC_Get_Time();
        sprintf((char *)buff1,"  %d-%d %d:%d:%d ",month1,day1,my_time.hour,my_time.min,my_time.sec);
        OLED_String_Disp(0,0,(char *)buff1 );
        printf("date:%d-%d-%d %d:%d:%d\r\n",my_time.year,month1,day1,my_time.hour,my_time.min,my_time.sec);
    }
}

/*******************************************************************
* 函数名: Is_Leap_Year()
* 功能描述 : 判断年份是否为闰年
* 返回值说明: 1:闰年 0:平年
*******************************************************************/
u8 Is_Leap_Year(u16 year)
{ 
    if(year%4==0) //必须能被 4 整除
    { 
        if(year%100==0) 
        { 
            if(year%400==0)return 1;//如果以 00 结尾,还要能被 400 整除 

            else return 0; 
        }else return 1; 
    }else return 0;
}
/*******************************************************************
* 函数名: RTC_Set_Time()
* 功能描述 : 设置时间
* 返回值说明: 0:成功;其他:失败
*******************************************************************/
const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};//平年每个月的天数
u8 RTC_Set_Time(u16 year,u8 month,u8 day,u8 hour,u8 min,u8 sec)
{
    u16 i;
    u32 second_cnt=0;
    if(year<1970||year>2099) return 1;
    /********************计算年份共有多少秒*****************************/
    for(i=1970;i<year;i++)
    {
        //闰年 366 天
        if(Is_Leap_Year(i)) 
        {
            second_cnt+=31622400;
        }    
        //平年 365 天
        else 
        {
            second_cnt+=31536000;
        }
    }
    /********************计算月份共有多少秒*****************************/
    for(i=0;i<(month-1);i++) //把前面月份的秒钟数相加
    {
        second_cnt+=(u32)mon_table[i]*86400;//月份秒钟数相加
        if(Is_Leap_Year(i)&&i==1)
        {
            second_cnt+=86400;//闰年 2 月份增加一天的秒钟数 
        }    
        
    }
    /********************计算日,周,时,分,秒共有多少秒*****************************/
    second_cnt+=(day-1)*86400;
    second_cnt+=hour*3600;
    second_cnt+=min*60;
    second_cnt+=sec;
    //设置时钟
    RTC_WaitForLastTask(); //等待上次写寄存器操作完成
    RTC_SetCounter(second_cnt);
    
    RTC_WaitForLastTask();
    return 0;
}
/*******************************************************************
* 函数名: RTC_Get_Time()
* 功能描述 : 获取时分秒,年月日
*******************************************************************/
void RTC_Get_Time(void)
{
    u8 t;
    u32 day_cnt;
    u32 temp;
    u32 second_cnt=0;
    second_cnt = RTC_GetCounter();//得到计数器中的值(秒钟数)
    day_cnt=second_cnt/86400;//计算当前共有多少天
    /******************计算共有多少年*********************/
    my_time.year =1970;
    while(day_cnt>=365)
    {
        if(Is_Leap_Year(my_time.year))day_cnt-=366;
        else day_cnt-=365;
        my_time.year +=1;
    }
    /******************计算剩下的秒中共有多少月*********************/
    t=0;
    while(day_cnt>=mon_table[t])
    {
        if((Is_Leap_Year(my_time.year))&&(t==1))day_cnt-=(mon_table[t]+1);
        else day_cnt-=mon_table[t];
        t++;
    }
    temp=second_cnt%86400;
    my_time.mon =t+1;
    my_time.day =day_cnt+1;
    my_time.hour=temp/3600;
    my_time.min =(temp%3600)/60;
    my_time.sec =(temp%3600)%60;
}

到了这里,关于RTC实时时钟的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • RTC实时时钟源码分析

    1.先来看一下RTC的配置过程  2.RTC源码讲解 我们的工程中加入了 rtc.c 源文件和 rtc.h头文件,同时,引入了 stm32f10x_rtc.c 和 stm32f10x_bkp.c 库文件。 说明,首先是 RTC_Init,其代码如下: 该函数用来初始化 RTC 时钟,但是只在第一次的时候设置时间,以后如果重新上电/复位都不会再

    2024年02月05日
    浏览(40)
  • 实时时钟 RTC(2)

    RTC 使能与停止 RTC 上电后立即启动,不可关闭,软件应在32K 晶体振荡器完全起振后再设置当前时间;在晶体振荡器起振之前芯片使用内部环振计时,偏差较大。 RTC 时间设置 软件可以在任意时刻直接设置RTC 时间寄存器;由于设置时间寄存器的操作与RTC 走时为异步操作关系,

    2024年02月06日
    浏览(32)
  • STM32-RTC实时时钟

    目录 RTC实时时钟 功能框图 UNIX时间戳 初始化结构体 RTC时间结构体 RTC日期结构体 RTC闹钟结构体 进入和退出配置函数 实验环节1:显示日历 常规配置 RTC配置 测试环节 实验现象 实验环节2:闹钟 常规配置 RTC配置 测试环节 实验现象 STM32的RTC外设,实质上是一个 掉电后还继续运

    2024年02月06日
    浏览(37)
  • 嵌入式——实时时钟(RTC)

    目录 一、初识RTC 1.简介 2.特性 3.后备寄存器和RTC寄存器特性 二、RTC组成 1.相关寄存器 (1)控制寄存器高位(RTC_CRH) (2)控制寄存器低位(RTC_CRL) (3)预分频装载寄存器高位(RTC_PRLH) (4)预分频裝载寄存器低位(RTC_PRLL) (5)计数器寄存器高位(RTC_CNTH) (6)计数器

    2024年02月19日
    浏览(22)
  • 【STM32】RTC(实时时钟)

    本质:计数器 RTC中断是外部中断(EXTI) 当VDD掉电的时候,Vbat可以通过电源---实时计时 STM32的RTC外设(Real Time Clock),实质是一个   掉电   后还继续运行的定时器。从定时器的角度来说,相对于通用定时器TIM外设,它十分简单, 只有很纯粹的计时和触发中断的功能 ;但从

    2024年02月03日
    浏览(40)
  • STM32——RTC实时时钟

    Unix 时间戳(Unix Timestamp)定义为从UTC/GMT的1970年1月1日0时0分0秒开始所经过的秒数,不考虑闰秒 时间戳存储在一个秒计数器中,秒计数器为32位/64位的整型变量 世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间 底层使用秒计数器可以节省硬件设计电路,

    2024年01月23日
    浏览(32)
  • STM32--RTC实时时钟

    Unix 时间戳是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒 。 时间戳存储在一个秒计数器中,秒计数器为32位/64位的整型变量。 世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间。 GMT : GMT(Greenwich Mean Time), 格林威治平时(也称格林

    2024年02月10日
    浏览(37)
  • STM32-RTC实时时钟详解

    RTC的本质很简单,就是一个时钟经过精确分频最后得到的一个1Hz的时钟,也可以说是计数器,其他大部分功能都是基于这个计数器设计的数字逻辑。 本文讲的RTC是基于STM32F030来讲的,相比与F1系列的RTC来说,M0的将很多原本需要软件实现的功能硬件化了,使用起来更加便利。

    2024年02月04日
    浏览(34)
  • 【STM32学习】实时时钟 —— RTC

    STM32RTC实时时钟实验讲解,从入门到放弃 【STM32】RTC休眠唤醒(停机模式)、独立看门狗开启状态下 关于STM32使用RTC唤醒停止模式的设置 RTC(Real Time Clock):实时时钟,是指可以像时钟一样输出实际时间的电子设备,一般会是集成电路,因此也称为时钟芯片。总之,RTC只是个能靠电

    2024年02月01日
    浏览(36)
  • STM32-实时时钟RTC-2

                                     

    2024年01月20日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包