原创 RTC应用笔记

2009-11-24 16:56 2926 3 3 分类: MCU/ 嵌入式

https://static.assets-stash.eet-china.com/album/old-resources/2009/11/24/b725abfb-9aee-43ba-9c3b-3b95620e84eb.rar" target=_blank>实质:RTC是一个独立的计数器,其相应的寄存器是在备份区所以掉电也不会丢数据。设置好RTC后就用秒中断来读取器寄存器的值。再换算为年月日就行了。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


STM32RTC实际是一个独立的定时器。
下面将介绍如何使用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备份器的时钟。用于备份模式下。
即系统掉电了,BKPRTC还能继续工作,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:
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /> 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当中。


 


程序

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
3
关闭 站长推荐上一条 /3 下一条