STM32的实时时钟(RTC)是一个独立的定时器,是用来获取时间的。在蓝桥杯嵌入式比赛中也是比较常考的一个知识点。配置起来较为简单,也可以直接复制考场提供的固件库中的例程。
在进行RTC配置前,我们需要从固件库添加几个文件,添加方法在串口配置中有详细说明。
stm32f10x_rtc.c是关于RTC的库函数,stm32f10x_bkp.c是关于备份寄存器的库函数,stm32f10x_pwr.c是关于电源控制的库函数。
RTC配置代码如下:
void RTC_Init(u8 HH,u8 MM,u8 SS)
{
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;//RTC全局中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
PWR_BackupAccessCmd(ENABLE);//使能后备寄存器访问
BKP_DeInit();//复位备份区域 //复位备份区域
RCC_LSICmd(ENABLE);//使能LSI时钟
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == 0);//检查指定的RCC标志位设置值与否
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);//设置RTC时钟
RCC_RTCCLKCmd(ENABLE);//使能RTC时钟
RTC_WaitForSynchro();//等待APB1时钟与RTC时钟同步
RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能RTC秒中断
RTC_WaitForLastTask();
RTC_SetPrescaler(40000-1);//设置分频
RTC_WaitForLastTask();
RTC_SetCounter(HH * 3600 + MM * 60 + SS);//设置初始时间
RTC_WaitForLastTask();
}
1.使能电源时钟和备份区域时钟:配置任何东西,第一件事使能时钟。我们要访问RTC和备份区域就必须先使能电源时钟和备份区域时钟。
2.设置RTC中断:调用NVIC_Init函数即可。
3.取消备份区写保护:要向备份区域写入数据,就要先取消备份区域写保护,否则后面无法对RTC进行读写。
4.复位备份区域,开启内部低速时钟:蓝桥杯嵌入式开发板上,我们只能使用LSI时钟源。
5.选择RTC时钟,并使能:相关函数在stm32f10x_rcc.c中。
6.等待APB1时钟与RTC时钟同步
7.RTC秒中断使能
8.设置RTC时钟分频数:LSI时钟频率约为40KHz,RTC需要1Hz的时钟,所以需要进行40000-1分频。
9.设置初始时间:其实就是设置RTC的计数值,时间与计数值之间是需要换算的。
接下来就要编写中断服务函数,写在stm32f10x_it.c中,代码如下:
extern u8 RTC_Flag;
void RTC_IRQHandler(void)
{
if(RTC_GetFlagStatus(RTC_IT_SEC) == 1)
{
RTC_ClearITPendingBit(RTC_IT_SEC);
RTC_Flag = 1;//时间更新标志位
if(RTC_GetCounter() == 86400)
{
RTC_SetCounter(0);
RTC_WaitForLastTask();
}
}
}
在秒钟中断产生的时候,清除中断标志位,把时间更新标志位置1(用于在主函数计算时间并显示),当满足一天的时间,需要吧计数值清零。
主函数代码:
#include "stm32f10x.h"
#include "rtc.h"
#include "lcd.h"
#include "stdio.h"
u32 TimingDelay = 0;
void Delay_Ms(u32 nTime);
u8 RTC_Flag=0;
u32 Time_Total=0;
u8 Hour=0,Min=0,Sec=0;
u8 str[20];
//Main Body
int main(void)
{
SysTick_Config(SystemCoreClock/1000);
RTC_Init(23,59,55);
STM3210B_LCD_Init();
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
while(1)
{
if(RTC_Flag)
{
Time_Total = RTC_GetCounter(); //获取RTC寄存器值
Hour = Time_Total / 3600; //时
Min = Time_Total % 3600 / 60; //分
Sec = Time_Total % 3600 % 60; //秒
RTC_Flag = 0; //RTC标志位清空
sprintf((char*)str,"%02d:%02d:%02d",Hour,Min,Sec);
LCD_DisplayStringLine(Line2,str);
}
}
}
//1ms延时函数
void Delay_Ms(u32 nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
主函数中做的工作很简单,就是把获取的计数值分解为时、分、秒,并在LCD上显示出来。