RTC

作者: 你的优先级最高 | 来源:发表于2018-01-16 22:35 被阅读0次

    下面的程序根据固件库进行修改,变成自己想要的程序,包含RTC秒中断以及闹钟中断,由于嵌入式竞赛板没有外加晶振,所以使用内部低速时钟LSI

    下面的程序不能进行年月计时,只能在一天之内进行计时,如果要进行长时间计时,那么就得考虑闰年,还要考虑一月是31,30还是29或28天。应对比赛来说就够了

    (2018/1/22加)今天添加一点小窍门,利用数组对时间的时、分、秒进行
    存储,这样就不用定义三个变量了,闹钟时间使用相同的方式比较好,这样写程序会更快;

    配置步骤(原子教程)

    1) 使能电源时钟和备份区域时钟。
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);//PWR是电池时钟
    2) 取消备份区写保护。//原子点的视频有断电恢复断电时间的功能
    PWR_BackupAccessCmd(ENABLE); //使能 RTC 和后备寄存器访问
    3) 复位备份区域,开启外部低速振荡器。

    BKP_DeInit();//复位备份区域
    RCC_LSEConfig(RCC_LSE_ON);// 开启外部低速振荡器
    

    4) 选择 RTC 时钟,并使能。

    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //选择 LSE 作为 RTC 时钟,
    RCC_RTCCLKSource_LSI//选择的是低速时钟
    RCC_RTCCLKSource_HSE_Div128// HSE 的 128 分频
    

    5) 设置 RTC 的分频,以及配置 RTC 时钟。

    在进行 RTC 配置之前首先要打开允许配置位(CNF),库函数是:
    RTC_EnterConfigMode();/// 允许配置
    在配置完成之后,千万别忘记更新配置同时退出配置模式,函数是:
    RTC_ExitConfigMode();//退出配置模式, 更新配置
    设置 RTC 时钟分频数, 库函数是:
    void RTC_SetPrescaler(uint32_t PrescalerValue);
    这个函数只有一个入口参数,就是 RTC 时钟的分频数,很好理解。
    然后是设置秒中断允许, RTC 使能中断的函数是:
    void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);
    这个函数的第一个参数是设置秒中断类型,这些通过宏定义定义的。 对于使能秒中断方法是:
    RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能 RTC 秒中断
    

    6) 更新配置,设置 RTC 中断分组。

    在设置完时钟之后,我们将配置更新同时退出配置模式,这里还是通过 RTC_CRH 的 CNF
    来实现。 库函数的方法是:
    RTC_ExitConfigMode();//退出配置模式,更新配置
    void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data);//写入后备寄存器
    

    7) 编写中断服务函数

    void RTC_IRQHandler(void)
    {
        if (RTC_GetITStatus(RTC_IT_SEC) != RESET)//秒中断
        {
            RTC_ClearITPendingBit(RTC_IT_SEC);//清除中断标志位
        }
        if(RTC_GetITStatus(RTC_IT_ALR)!=RESET)//闹钟中断
        {
            RTC_ClearITPendingBit(RTC_IT_ALR);
            AlarmFlag = 1;
        }
    }
    

    第六届省赛代码“电压测量监控设备

    #include "include.h"
    #include "rtc.h"
    #include "lcd.h"
    
    #define HH 23  //时
    #define MM 59  //分
    #define SS 55  //秒
    
    u32 THH = 0, TMM = 0, TSS = 0;
    
    _Bool TimeDisplay = 0;
    _Bool AlarmFlag = 0;//闹钟中断
    /**
      * @说明     配置RTC
      * @参数     None
      * @返回值   None
      */
    void RTC_Configuration(void)
    {
        /* Enable PWR and BKP clocks */
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
    
        PWR_BackupAccessCmd(ENABLE);
        BKP_DeInit();
        RCC_LSICmd(ENABLE);
        /* Wait till LSE is ready */
        while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);
        
        RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
        RCC_RTCCLKCmd(ENABLE);
    
        RTC_WaitForSynchro();
        RTC_WaitForLastTask();
        /* Enable the RTC Second */
        RTC_ITConfig(RTC_IT_SEC, ENABLE); //秒中断
        RTC_WaitForLastTask();
    
        RTC_ITConfig(RTC_IT_ALR, ENABLE); //闹钟中断
        RTC_WaitForLastTask();
        /* Set RTC prescaler: set RTC period to 1sec */
        RTC_SetPrescaler(39999); /* RTC period = RTCCLK/RTC_PR = (40 KHz)/(39999+1) */
        /* Wait until last write operation on RTC registers has finished */
        RTC_WaitForLastTask();
        
        RTC_SetCounter(HH*3600+MM*60+SS);//设置初始时间
        RTC_WaitForLastTask();
        RTC_SetAlarm(0); //设置闹钟时间
        RTC_WaitForLastTask();
        NVIC_Configuration();//中断优先级
    }
    
    /**
      * @说明     显示当前时间
      * @参数     TimeVar:RTC Counter值
      * @返回值   None
      */
    
    uint8_t text[20];
    void Time_Display(u32 TimeVar)
    {
        
              /* 23:59:59 */
        if (RTC_GetCounter() == 23*3600+59*60+59)
        {
            RTC_SetCounter(0x0);
            RTC_WaitForLastTask();
        }
        /* Compute  hours */
        THH = TimeVar / 3600;
        /* Compute minutes */
        TMM = (TimeVar % 3600) / 60;
        /* Compute seconds */
        TSS = (TimeVar % 3600) % 60;
    
        sprintf(text,"   T: %0.2d:%0.2d:%0.2d",THH, TMM, TSS);
        LCD_DisplayStringLine(Line5,text);
    }
    
    /**
      * @说明     配置中断向量控制器
      * @参数     None
      * @返回值   None
      */
    void NVIC_Configuration(void)
    {
        NVIC_InitTypeDef NVIC_InitStructure;
    
    //  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
        /* Enable the RTC Interrupt */
        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);
    }
    void RTC_IRQHandler(void)
    {
        if (RTC_GetITStatus(RTC_IT_SEC) != RESET)//秒中断
        {
            RTC_ClearITPendingBit(RTC_IT_SEC);
            TimeDisplay = 1;  //时间更新标志置位
            /* Wait until last write operation on RTC registers has finished */
            RTC_WaitForLastTask();
            
        }
        if(RTC_GetITStatus(RTC_IT_ALR)!=RESET)//闹钟中断发生
        {
            RTC_ClearITPendingBit(RTC_IT_ALR);
            AlarmFlag = 1;//送出标志位
        }
    }
    

    相关文章

      网友评论

          本文标题:RTC

          本文链接:https://www.haomeiwen.com/subject/cbieoxtx.html