STM32 RTC实时时钟 F407 寄存器

RTC介绍

STM32F1:
            RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。
            即在F1系列,RTC的日历部分只有一个32位的寄存器
            该寄存器直接存放 时间戳 的值,即:秒数值 
            想要获取其他时间,想要软件来实现。

STM32F4:
            RTC日历部分包含两个32位的寄存器,分为日期寄存器和时间寄存器
            可直接输出时分秒,星期、月、日、年
             让我们在软件编程时大大降低了难度。

以下是基于F4的RTC内容

RTC说明

                年月日时分秒,自动计算闰年,能区分每个月的天数

理解要点:
       Unix时间戳  从1970年开始每1s计1个数
       BKP备份域 相当于存储器有20个u32的寄存器,断电复位
       BCD     二进制十进数

 BCD:

       4位二进制表示1位十进制中的0~9

           十进制        BCD码

            19 ———- 0x19

 备份域:

       RTC有20个u32的备份域寄存器RTC_BKPxR  即有80个字节空间

      备份域的作用:防止程序重新设置RTC日历时间    

RTC运行:

       RTC控制器及其备份域,只要有供电就可以一直运行

       供电是指有电源,而CPU复位不算掉电源

    当有主供电电路,RTC电源由主电路提供,节省备用电源(纽扣电池)

    当主供电电路断电,RTC在有备用电源的情况下,能够继续运行

RTC框图

RTC时钟源   

       RTC有3个时钟源选择 HSE LSE LSI
       主要选择LSE低速外部时钟
       HSE:为总线提供时钟,而且频率太高
       LSI:时钟频率不稳定

       LSE:外接32.768KHz,专门设计为RTC提供时钟

RTC内部有两个分频器:
                        一个异步分频器 默认128分频
                        一个同步分频器 默认256分频
                       刚好将LSE的32.768KHz 分频 为 1Hz
                        即 1s 计 1个数

RTC实时时钟

1.使能RTC控制器

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

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

  • 时钟源配置选择LSE低速外部时钟
  • 2.RTC时钟源选择:

    RCC 备份域控制寄存器RCC->BDCR

    使能LSE时钟,并等待时钟就绪

    RTCSEL[1:0]直接赋值选择LSE

    不能先清零再配置此位,最后使能RTC时钟

    3.解除RTC寄存器写保护:           

  • 往RTC_WPR寄存器 中写 0xca  再写 0x53
  •             //取消RTC所有寄存器的写保护

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

    4.配置RTC:

            要想改变日历寄存器的时间的值或者分频值

            需要让日历进入初始化模式(日历停止工作)

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

    5.进入初始化模式:

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

            等待是否允许更新(改变)日历值位  INITF

                设置日期和时间寄存器 TD&DR

                退出初始化模式  RTC->ISR 寄存器的INIT位写0

             读取日历:

                 获取 DR和TR的值

                 需要用 两次 同步影子寄存器 来读取

                 因为通过实验测试,一次读两个数据寄存器 数值有误

                 同步步骤:先将同步标志位清零,确保为最新鲜的数据

                 等待同步标志置1,读取数据寄存器

    十进制转BCD码  return  ((dec / 10) << 4) | (dec % 10);

    BCD码转十进制   return  (bcd  >> 4) * 10 + (bcd & 0x0f);

    RTC闹钟

    因此需要配置EXTI控制器的17号中断线

                      使能SYSCFG时钟

                      打开EXTI 17号线中断请求使能

                      EXTI 17 选择上升沿检测

               同样,配置NVIC控制器管理

               中断源:RTC_Alarm_IRQn

               中断服务函数:RTC_Alarm_IRQHandler

           清除中断标志位是 EXTI->PR & (1<<17)

           同时也要清除RTC->ISR & (1<<8)闹钟匹配位

           因为EXTI就是监控 该闹钟匹配位 的 边沿跳变

    RTC实时时钟初始化代码

    /***************************************
    *函数名            :rtc_init
    *函数功能        :RTC初始化配置函数
    *函数参数        :RTC_t time
    *函数返回值    :无
    *函数描述        :
    ****************************************/
    void rtc_init(RTC_t time)
    {
        /*解除RTC控制器和相关寄存器保护*/
        //电源控制器时钟使能
        RCC->APB1ENR |= (1<<28);
        //PWR->CR 的DBP位写1解除RTC控制器控制 
        PWR->CR |= (1<<8);
        
        /*RTC时钟源设置*/
        //开启LSE时钟
        RCC->BDCR |= (1<<0);
        //等待LSE时钟就绪
        while(!(RCC->BDCR & (1<<1)));
        //选择LSE作为RTC时钟源
        RCC->BDCR |= (1<<8);
        //使能RTC时钟
        RCC->BDCR |= (1<<15);
        
        //解除RTC寄存器写保护
        RTC->WPR = 0xca;
        RTC->WPR = 0x53;
        
        /*RTC相关寄存器配置*/
        //选择24小时/天格式
        RTC->CR &= ~(1<<6);
        //日历值取自影子寄存器
        RTC->CR &= ~(1<<5);
        
        //激活RTC寄存器写保护
        RTC->WPR = 0xff;
        
        /*设置初始时间*/
        if(RTC->BKP0R != 0xff)
        {
            rtc_set_time(time);
            RTC->BKP0R = 0xff;
        }
    }

    RTC闹钟初始化函数  及 中断服务函数

    /***************************************
    *函数名            :clockA_init
    *函数功能        :闹钟A初始化函数
    *函数参数        :RTC_t time
    *函数返回值    :无
    *函数描述        :
    ****************************************/
    void clock_init(RTC_t time)
    {
        u32 a_temp;
        
        //解除RTC寄存器写保护
        RTC->WPR = 0xca;
        RTC->WPR = 0x53;
        
        //禁止闹钟
        RTC->CR &= ~(3<<8);
        //闹钟A中断使能
        RTC->CR |= (1<<12);
        //等待允许更新闹钟
        while(!(RTC->ISR & (1<<0)) && !(RTC->ISR & (1<<1)));
        
        //获取日期BCD码
        a_temp = (in_dec_out_bcd(time.day)<<24)     |
                         (in_dec_out_bcd(time.hour)<<16)  |
                         (in_dec_out_bcd(time.min)<<8)        |
                     (in_dec_out_bcd(time.sec));
        
        //设置闹钟A寄存器
        RTC->ALRMAR = a_temp;
        
        /*EXTI控制器配置*/
        //打开SYSCFG时钟
        RCC->APB2ENR |= 1<<14;
        //打开中断请求使能
        EXTI->IMR |= (1<<17);
        //上升沿检测
        EXTI->RTSR |= (1<<17);
        
        /*NVIC*控制器配置*/
        //优先级分组        —-在主函数
        //计算优先级编码值
        u32 pri= NVIC_EncodePriority (5,2,2);
        //设置具体中断源
        NVIC_SetPriority(RTC_Alarm_IRQn, pri);
        //使能NVIC响应通道
        NVIC_EnableIRQ(RTC_Alarm_IRQn);
        
        //使能闹钟A
        RTC->CR |= (1<<8);
        
        //激活RTC寄存器写保护
        RTC->WPR = 0xff;
    }

    /**********************************************
    *函数名            :RTC_Alarm_IRQHandler
    *函数功能        :RTC闹钟中断服务函数
    *函数参数        :无
    *函数返回值    :无
    *函数描述        :
    ***********************************************/
    void RTC_Alarm_IRQHandler(void)
    {
        ///判断是闹钟A信号
        if(EXTI->PR & (1<<17))                         
        {                                                                
            //清除标志位                                            
            EXTI->PR |= (1<<17);
            RTC->ISR &=  ~(1<<8);    
            //执行紧急事件
            LED1_ON;
            printf("延时后\r\n");
            LED2_ON;
            LED1_OFF;      
        }
    }

    作者:汪款学嵌入式

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32 RTC实时时钟 F407 寄存器

    发表回复