作者:马一飞 QQ:791729359
在学习过程中有什么问题可以联系
(原本资料是以网盘的方式公开提供给任何蓝桥杯爱好者进行下载的,但是最近临近蓝桥杯考试,遇到了很多伸手党,我无偿给爱好者们解答学习上的问题,回复得比较慢居然还有同学来说我这样那样,所以决定不再随意提供自己写的源码和资料。博主已经开始参加工作了,也不是闲着没事干盯着电脑手机为你们服务。记住,不要成为伸手党,要自己多动手实现。)
RTC实际上就是实时时钟,如果接触过单片机的同学也许你听过DS1302实时时钟模块,实际上就是拿来获取时间的,STM32把RTC集成在了芯片内部,它内部具有专门的实时时钟单元,不需要外接其他模块。
那么我们这里就来讲解一下蓝桥杯RTC如何进行配置。在配置前我们还需要包含四个库函数进来。
Bkp里是关于备份寄存器的库函数,pwr里是关于电源管理的库函数。在初始化RTC时候,我们首先要先使能pwr时钟和bkp时钟。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR,ENABLE);
PWR_BackupAccessCmd(ENABLE);
BKP_DeInit();
我们配置的是RTC,我们为什么还要配置电源管理与备份寄存器呢?我们可以看一stm32f1中文参考手册RTC章节
可以看到,我们要使能bkp后,才能对RTC进行访问。
同时,备份寄存器又是收到pwr(电源管理)控制的,因此我们要在pwr中使能Backup寄存器。这一步是非常关键的,如果缺少了这一步,那么后面的RTC读写将会失败。
我们还得对RTC中断进行初始化。
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); //使能RTC中断
我们可以看一下数据手册,RTC的时钟源是怎么选择的。
那么很重要的一点来了,我们蓝桥杯嵌入式板子,只能使用LSI时钟源,据官方说明是用不了其他时钟源的,所以这点是非常重要的。接下来我们直接看代码。
RCC_LSICmd(ENABLE); //使能LSI时钟
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); //选择LSI作为时钟源
RCC_RTCCLKCmd(ENABLE); //使能RTC时钟
这三个函数的原型在RCC库函数都能找到。
第一步先把LSI时钟使能,第二部把RTC的时钟选择为LSI作为时钟源,第三部使能RTC时钟。
RTC_WaitForSynchro(); //等待APB1时钟与RTC时钟同步
RTC_WaitForLastTask();
RTC_SetPrescaler(40000 - 1); //设置分频
RTC_WaitForLastTask(); //等待操作完成
RTC_SetCounter(3600 * HH + 60 * MM + SS); //设置初始时间
RTC_WaitForLastTask();
RTC_ITConfig(RTC_IT_SEC,ENABLE);//秒中断使能
RTC_WaitForLastTask();
1. 先等待APB1时钟与RTC时钟同步
2. 设置RTC分频系数,为什么要选择40000-1,因为我们的RTC选择的是LSI作为时钟源,我们首先得看一下LSI的时钟频率
LSI时钟频率大约40KHZ,RTC需要1HZ的时钟,因此需要40000-1分频。
3. 设置初始时间。(这个时间是按照BCD码来存储的,可以简单的理解成,是按秒数来储存的,因此小时,分,都得化为秒,相加在一起)
4. 秒中断使能。
在中断函数里:
void RTC_IRQHandler(void)
{
u32 Times;
if(RTC_GetITStatus(RTC_IT_SEC) == 1)
{
RTC_ClearITPendingBit(RTC_IT_SEC);
RTC_Flag = 1;
Times = RTC_GetCounter();
RTC_WaitForLastTask();
if(Times == (24 * 3600))
{
RTC_SetCounter(0);
RTC_WaitForLastTask();
}
}
}
每次进入到秒中断,我们都另RTC_Flag = 1;然后再主函数里读取对应的时间并显示到LCD上观察。同时我们还得对RTC时间进行判断,如果RTC时间计数到24小时的时候,我们要清零重新开始计数。
在主函数中:
if(RTC_Flag)
{
RTC_Flag = 0;
TimeVal = RTC_GetCounter();
hour = TimeVal / 3600;
min = TimeVal % 3600 / 60;
sec = TimeVal % 3600 % 60;
sprintf((char*)string,"TIME:%.2d:%.2d:%.2d ",hour,min,sec);
LCD_DisplayStringLine(Line3, string);
}
我们就可以读取RTC的时间,并把时间分解为时、分、秒,小时到LCD上。
以往年的赛题分析,RTC在蓝桥杯比赛中考的几率还是蛮大的,而且配置也不难。因此希望大家能够理解并吃透它。
把程序烧录到CT117E开发板中的现象:
(以上仅属于个人观点)