08 STM32 - RTC

8.1 RTC简介

实时时钟 (RTC) 是一个独立的 BCD 定时器/计数器。RTC 提供一个日历时钟、两个可编程闹钟中断,以及一个具有中断功能的周期性可编程唤醒标志。RTC 还包含用于管理低功耗模式的自动唤醒单元。
两个 32 位寄存器包含二进码十进数格式 (BCD) 的秒、分钟、小时(12 或 24 小时制)、星期几、日期、月份和年份。此外,还可提供二进制格式的亚秒值。系统可以自动将月份的天数补偿为 28、29(闰年)、30 和 31 天。并且还可以进行夏令时补偿。其它 32 位寄存器还包含可编程的闹钟亚秒、秒、分钟、小时、星期几和日期。还可以根据需要设置闹钟。
此外,还可以使用数字校准功能对晶振精度的偏差进行补偿。上电复位后,所有 RTC 寄存器都会受到保护,以防止可能的非正常写访问。无论器件状态如何(运行模式、低功耗模式或处于复位状态),只要电源电压保持在工作范围内,RTC 便不会停止工作。
RTC中断的wakeup引脚可以唤醒MCU,比如当MCU在低功耗状态下或者休眠之类的状态下,通过引脚的Wakeup功能可以将MCU唤醒,让MCU进入正常的工作状态。

8.2 RTC应用代码

// RTC 初始化
uint8_t RtcInit(void)
{
    RTC_InitTypeDef RTC_InitStructure;
    u16 retry = 0X1FFF;  // 超时时间
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); // 使能PWR时钟
    PWR_BackupAccessCmd(ENABLE);    // 使能后备寄存器访问 

    if(RTC_ReadBackupRegister(RTC_BKP_DR0)!=0x5050)        //是否第一次配置?
    {
        RCC_LSEConfig(RCC_LSE_ON); // 开启LSE 
        while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)    // 等待低速晶振就绪
        {
            retry++;
            delay_ms(10);
        }
        if(retry==0) return 1;        // LSE 开启失败. 

        RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);     //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟    
        RCC_RTCCLKCmd(ENABLE);    //使能RTC时钟 

        RTC_InitStructure.RTC_AsynchPrediv = 0x7F;//RTC异步分频系数(1~0X7F)
        RTC_InitStructure.RTC_SynchPrediv  = 0xFF;//RTC同步分频系数(0~7FFF)
        RTC_InitStructure.RTC_HourFormat   = RTC_HourFormat_24;//RTC设置为,24小时格式
        RTC_Init(&RTC_InitStructure);

        RTC_Set_Time(8,0,0,RTC_H12_AM);    //设置时间
        RTC_Set_Date(24,5,1,1);        //设置日期

        RTC_WriteBackupRegister(RTC_BKP_DR0,0x5050);    //标记已经初始化过了
    }
    return 0;
}

 // 获取实时时间
RTC_TimeTypeDef RtcGetTime()
{
    RTC_TimeTypeDef RTC_TimeStruct;
    RTC_GetTime(RTC_Format_BIN,&RTC_TimeStruct);
    return RTC_TimeStruct;
}

//设置闹钟时间(按星期闹铃,24小时制)
//week,hour,min,sec:周几,时,分,秒
void RtcSetAlarmA(uint8_t week,uint8_t hour,uint8_t min,uint8_t sec)
{ 
    EXTI_InitTypeDef   EXTI_InitStructure;
    RTC_AlarmTypeDef RTC_AlarmTypeInitStructure;
    RTC_TimeTypeDef RTC_TimeTypeInitStructure;

    RTC_AlarmCmd(RTC_Alarm_A,DISABLE);//关闭闹钟A 

    RTC_TimeTypeInitStructure.RTC_Hours=hour;//小时
    RTC_TimeTypeInitStructure.RTC_Minutes=min;//分钟
    RTC_TimeTypeInitStructure.RTC_Seconds=sec;//秒
    RTC_TimeTypeInitStructure.RTC_H12=RTC_H12_AM;

    RTC_AlarmTypeInitStructure.RTC_AlarmDateWeekDay=week;//星期
    RTC_AlarmTypeInitStructure.RTC_AlarmDateWeekDaySel=RTC_AlarmDateWeekDaySel_WeekDay;//按星期闹
    RTC_AlarmTypeInitStructure.RTC_AlarmMask=RTC_AlarmMask_None;//精确匹配星期,时分秒
    RTC_AlarmTypeInitStructure.RTC_AlarmTime=RTC_TimeTypeInitStructure;
    RTC_SetAlarm(RTC_Format_BIN,RTC_Alarm_A,&RTC_AlarmTypeInitStructure);

    RTC_ClearITPendingBit(RTC_IT_ALRA);//清除RTC闹钟A的标志
    EXTI_ClearITPendingBit(EXTI_Line17);//清除LINE17上的中断标志位 

    RTC_ITConfig(RTC_IT_ALRA,ENABLE);//开启闹钟A中断
    RTC_AlarmCmd(RTC_Alarm_A,ENABLE);//开启闹钟A 
    

    EXTI_InitStructure.EXTI_Line = EXTI_Line17; // LINE17
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // 中断事件
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发 
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE17
    EXTI_Init(&EXTI_InitStructure);//配置 
    

    NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_IRQn; 
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; // 抢占优先级1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; // 子优先级2
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  // 使能外部中断通道
    NVIC_Init(&NVIC_InitStructure);  //配置
}

//RTC闹钟中断服务函数
void RTC_Alarm_IRQHandler(void)
{    
    if(RTC_GetFlagStatus(RTC_FLAG_ALRAF)==SET) // ALARM A中断
    {
        RTC_ClearFlag(RTC_FLAG_ALRAF); // 清除中断标志
    }
    EXTI_ClearITPendingBit(EXTI_Line17); //清除中断线17的中断标志                                              
}

//cnt:自动重装载值.减到0,产生中断.
void RTC_Set_WakeUp(u32 wksel,u16 cnt)
{
    EXTI_InitTypeDef   EXTI_InitStructure;

    RTC_WakeUpCmd(DISABLE);      // 关闭WAKE UP
    RTC_WakeUpClockConfig(wksel);// 唤醒时钟选择
    RTC_SetWakeUpCounter(cnt);   // 设置WAKE UP自动重装载寄存器

    RTC_ClearITPendingBit(RTC_IT_WUT);   // 清除RTC WAKE UP的标志
    EXTI_ClearITPendingBit(EXTI_Line22); // 清除LINE22上的中断标志位
    RTC_ITConfig(RTC_IT_WUT,ENABLE); // 开启WAKE UP 定时器中断
    RTC_WakeUpCmd( ENABLE);          // 开启WAKE UP 定时器 

    EXTI_InitStructure.EXTI_Line = EXTI_Line22;         // LINE22
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // 中断事件
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发 
    EXTI_InitStructure.EXTI_LineCmd = ENABLE; // 使能LINE22
    EXTI_Init(&EXTI_InitStructure);           // 配置

    NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn; 
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; // 抢占优先级1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; // 子优先级2
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能外部中断通道
    NVIC_Init(&NVIC_InitStructure); // 配置
}


//RTC WAKE UP中断服务函数
void RTC_WKUP_IRQHandler(void)
{    
    if(RTC_GetFlagStatus(RTC_FLAG_WUTF)==SET)//WK_UP中断?
    { 
        RTC_ClearFlag(RTC_FLAG_WUTF);    //清除中断标志
    }
    EXTI_ClearITPendingBit(EXTI_Line22);//清除中断线22的中断标志                                 
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值