STM32F4-DISCO 学习之 RTC

/ 0评 / 0

马上又来放假了,继续再来写,关于RTC的驱动,这个可简单了.一来没103那个坑爹的,二来之前已经给板子加装过电池.

https://www.lijingquan.net/2015/09/01/add-vbat-for-f4-discovery/

首先要粗略说一下RTC的特性,他用电池供电时候,就可以工作,在主电源失效情况下都没什么压力,但是外部电池是给LSE供电,所以功耗敏感时候需要注意设计,RTC还能保持一些BKP寄存器的值不变,这个还是靠VBAT的电池啊.虽然只有那么几个寄存器,但也是很足够的了.另外RTC是靠32.768kHz进行分频,直到等于1Hz的.另外可以设置闹铃,定点起来工作.

首先初始化时候要把LSE打开,而LSE只要打开一次,只要你的电池还工作,然后设置分频.一般按照以下思路:

1)判断时钟打开情况.

2)进行相关设置或者直接跳过.

的程序应该是这样的的,切记初始化函数不能是RTC_Init()哦,因为...冲突,当然,你是C++,你可以实现重载是另一回事.

uint8_t IRTC_Init(void)
{
    RTC_InitTypeDef RTC_InitStructure;
    uint16_t retry = 0X1FFF;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//使能PWR时钟
    PWR_BackupAccessCmd(ENABLE);	//使能后备寄存器访问
    if(RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x5055)		//是否第一次配置?
    {
        RCC_LSEConfig(RCC_LSE_ON);//LSE 开启
        while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)	//检查指定的RCC标志位设置与否,等待低速晶振就绪
        {
            retry++;
            Delay(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(23, 59, 56, RTC_H12_AM);	//设置时间
        RTC_Set_Date(14, 5, 5, 1);		//设置日期
        RTC_WriteBackupRegister(RTC_BKP_DR0, 0x5055);	//标记已经初始化过了
    }
    return 0;
}

只要把分频配置好,RTC就会自己一秒一秒的开始计时.当然,如果你的分频不是例子中的值,那可不是1秒哦,我们做实验时候,可以把这个值调整一下.另外F4闹钟设置也非常简单哦,只需要给RTC_AlarmTypeInitStructure填上合适的数值,就可以了,然后记得开中断,闹钟来了就中断了.大致如下:

    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的周期中断,相当于RTC_SetWakeUpCounter执行一下全OK了,所以也不介绍了.主要的,还是放个程序,一看就知道.

RTC实验

试验效果:

QQ图片20150912174529

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注