RTC

下面的程序根据固件库进行修改,变成自己想要的程序,包含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)