豆皮 - 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当中。

详细工程见压缩包。
RTC.rar (399.2 KB)
[/tr][/tr][/tr]
1

评分人数

  • aleyn

谢谢马七的教程,很详细。

TOP

支持一下,很详细

TOP

学习了,谢谢楼主分享

TOP

欧也 顶马七好文
我有一個夢想 擁有一大片土地 做個小地主 每天帶著一群狗奴才去調戲良家婦女....

TOP

谢谢!我也顶一下!

TOP

谢谢马七的教程,很详细。

谢谢马七的教程,很详细。

TOP

我们项目也需要用到RTC,楼主给了我们很好的建议,谢谢

TOP

啥也不说了,顶
http://shop35738797.taobao.com/

TOP

TOP

不错,顶一下

TOP

谢谢分享啊!

谢谢分享啊!

TOP

谢谢lz的分享!

TOP

谢谢lz好东东啊

TOP

支持一下,很详细

TOP

支持,很好

TOP

支持一下!那你的时钟是怎样仿真的啊!

你的时钟是怎样仿真的啊! 请教一下!

TOP

好好学习!

TOP

好像用迅雷下载附件经常出问题啊

TOP

好好学习!

TOP

很是实用的一个功能。

TOP

都很不错

都很不错

TOP

很好!学习学习!

TOP

EK-STM32上用的是12.5p?

TOP

yao le
xiexie

TOP

好。。。。

TOP

学习了!

TOP

学习学习学习学习

学习学习学习学习

TOP

学习了,顶一个~~~~

TOP

先收藏了

TOP

Review opelc.org on alexa.com