STM32开发板基础教程(十) - RTC初探(转帖)

豆皮 - STM32开发板基础教程(十) - RTC初探(原创)

版权所有 STMFANS 原创,转载请保留出处


http://www.stmfans.com/bbs/viewthread.php?tid=1147&extra=page%3D1



STM32的RTC实际是一个独立的定时器。
下面将介绍如何使用RTC。
我们将头一次牵扯到振源的问题。

首先介绍一下STM32使用的各种振源。
有三种
HSE:  外置晶振
HSI:  内置RC振荡
LSE:  外置RTC振荡(32768居多)

APB1 和 APB2 是经过PLL以后的振荡源。

STM32启动,首先使用的HSI振荡,在确认HSE振荡可用的情况下,才可以转而使用HSE,
当HSE出现问题,STM32可自动切换回HSI振荡,维持工作。
LSE振荡则是专门供RTC使用。

LSE晶振需要特别注意。
STM32非常奇怪,要求使用 6p负载的晶振,
市面买到的时钟晶振,绝大多是是12.5pF的
算是一个不小的bug,
大家做相关开发的时候,要留神。
要买6pF的晶振,配10pF的谐振电容。

由此,马七怀念一下AVR单片机。不用谐振电容都跑的飞,当然是Mega系列。

下面介绍RTC驱动过程。

第一件事情,喂时钟。

RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP|RCC_APB1Periph_PWR, ENABLE);

注意,喂的是什么?不是RTC,是电源管理和BKP备份器的时钟。用于备份模式下。
即系统掉电了,BKP和RTC还能继续工作,RTC继续计时。
那么RTC的时钟呢?前面提到,RTC的时钟,一般用LSE。

第二件事情,初始化RTC

// RTC config
void RTC_configuration()
{
        //Open the BKP
        PWR_BackupAccessCmd(ENABLE);

        BKP_DeInit();

        //RTC use the LSE Clock
        RCC_LSEConfig(RCC_LSE_ON);  //RCC打开了LSE时钟

        //Wait LSE Ready
        while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET);  //等待LSE就绪,一般来说,如果谐振不对,就会死在这里。实

际代码请慎重

        RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //RTC使用时钟,可以使用LSE,也可以使用HSI,也可以使用HSE/128

        RCC_RTCCLKCmd(ENABLE); //RTC的时钟开启

        RTC_WaitForSynchro();  //RTC等待同步,

        RTC_WaitForLastTask();  //这个代码在RTC中常常出现,类似于等待就绪的含义

        // Interrupt Each Second
        RTC_ITConfig(RTC_IT_SEC, ENABLE);  //RTC开中断,RTC中断有三种,秒中断,闹钟中断,溢出中断,很明显他们的作用。秒中断用于即时操作,闹钟中断用于关闭或者唤醒,溢出中断的话,用于复位RTC

        RTC_WaitForLastTask();//

        RTC_SetPrescaler(32767);  //RTC预分频,32768HZ,分为一秒一个振荡,RTC period = RTCCLK/RTC_PR = (32.768

KHz)/(32767+1)

        RTC_WaitForLastTask(); //等待同步
        
}

这样,RTC就启动了。
通过 RTC_GetCounter() 这个函数。读到计数器的值。
既然 一秒增一个。
很容易就可以从 计数器的值,算出确切的时间值。
对于这种时间分量复杂的,我习惯用结构体定义

typedef struct
{
        unsigned char Sec;
        unsigned char Min;
        unsigned char Hour;
        unsigned char Day;
        unsigned char Month;
        unsigned char Year;
}Time_Struct;

// translate seconds to YY::MM:D::HH::MM::SS
Time_Struct read_RTC_time()
{
        unsigned long Time_Value;
        
        Time_Struct TimeStruct;
        
        Time_Value = RTC_GetCounter();

        TimeStruct.Year = Time_Value/(12*30*24*3600);

        TimeStruct.Month = Time_Value/(30*24*3600) - TimeStruct.Year*12;

        TimeStruct.Day = Time_Value/(24*3600) - TimeStruct.Year*12*30 - TimeStruct.Month*30;

        TimeStruct.Hour = Time_Value/3600 - TimeStruct.Year*12*30*24 - TimeStruct.Month*30*24 - TimeStruct.Day*24;

        TimeStruct.Min = Time_Value/60 - TimeStruct.Year*12*30*24*60 - TimeStruct.Month*30*24*60 -

TimeStruct.Day*24*60 - TimeStruct.Hour*60;

        TimeStruct.Sec = Time_Value - TimeStruct.Year*12*30*24*60*60 - TimeStruct.Month*30*24*60*60 -

TimeStruct.Day*24*60*60 - TimeStruct.Hour*60*60 -TimeStruct.Min*60;

        return TimeStruct;
}

当然,也可以在任意时候设置这个时间,手工修改Counter即可。相关函数在工程文件rtc.c当中。

你可能感兴趣的:(工作,struct,360,each)