RTC是实时时钟的简称,可以产生秒、分、时等信息。在蓝桥杯嵌入式比赛中也是比较常考的一个知识点。
RTC初始化讲解
RTC的初始化需要stm32f10x_rtc.c、stm32f10x_rtc.h、stm32f10x_rcc.c、stm32f10x_rcc.h、misc.c、misc.h、stm32f10x_bkp.c、stm32f10x_bkp.h、stm32f10x_pwr.c和stm32f10x_pwr.h。
RTC初始化代码为
/**
* @说明 配置RTC
* @参数 None
* @返回值 None
*/
void RTC_Configuration(void)
{
/* Enable PWR and BKP clocks */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
BKP_DeInit();
RCC_LSICmd(ENABLE);
/* Wait till LSE is ready */
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForSynchro();
RTC_WaitForLastTask();
/* Enable the RTC Second */
RTC_ITConfig(RTC_IT_SEC, ENABLE);
RTC_WaitForLastTask();
/* Set RTC prescaler: set RTC period to 1sec */
RTC_SetPrescaler(39999); /* RTC period = RTCCLK/RTC_PR = (40 KHz)/(39999+1) */
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
RTC_SetCounter(HH*3600+MM*60+SS);
RTC_WaitForLastTask();
}
其中HH、MM、SS表示设置的时、分、秒,在main.c开头定义为
#define HH 10 //时
#define MM 59 //分
#define SS 50 //秒
函数RTC_SetCounter定义在stm32f10x_rtc.c中的第145行,声明在stm32f10x_rtc.c中的第107行。函数RTC_WaitForLastTask定义在stm32f10x_rtc.c中的第207行,声明在stm32f10x_rtc.c中的第111行。
可以参考CT117E嵌入式竞赛板\STM32_MCU\stm32f10x_stdperiph_lib\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\RTC\LSI_Calib中的main.c文件。
源代码为
/**
* @brief Configures the RTC.
* @param None
* @retval None
*/
void RTC_Configuration(void)
{
/* Enable PWR and BKP clocks */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
/* Allow access to BKP Domain */
PWR_BackupAccessCmd(ENABLE);
/* Reset Backup Domain */
BKP_DeInit();
/* Enable the LSI OSC */
RCC_LSICmd(ENABLE);
/* Wait till LSI is ready */
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
{}
/* Select the RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
/* Enable RTC Clock */
RCC_RTCCLKCmd(ENABLE);
/* Wait for RTC registers synchronization */
RTC_WaitForSynchro();
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
/* Enable the RTC Second */
RTC_ITConfig(RTC_IT_SEC, ENABLE);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
/* Set RTC prescaler: set RTC period to 1sec */
RTC_SetPrescaler(40000);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
/* To output second signal on Tamper pin, the tamper functionality
must be disabled (by default this functionality is disabled) */
BKP_TamperPinCmd(DISABLE);
/* Enable the RTC Second Output on Tamper Pin */
BKP_RTCOutputConfig(BKP_RTCOutputSource_Second);
}
只需将函数RTC_SetPrescaler的参数40000改成39999,将最后两个函数改成时钟设置函数。
RTC中断设置
RTC中断设置代码为
/**
* @说明 配置中断向量控制器
* @参数 None
* @返回值 None
*/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* Enable the RTC Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
源代码为
/**
* @brief Configures the nested vectored interrupt controller.
* @param None
* @retval None
*/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* Enable the RTC Interrupt */
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);
/* Enable the TIM5 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
只需将结构体NVIC_InitStructure的元素NVIC_IRQChannelPreemptionPriority 的值改为1。去掉TIM5的中断设置。
RTC中断处理函数改写
RTC的中断处理函数仍然是在stm32f10x_it.c文件中编写。
代码为
/**
* @brief This function handles PPP interrupt request.
* @param None
* @retval None
*/
void RTC_IRQHandler(void)
{
if (RTC_GetITStatus(RTC_IT_SEC) != RESET){
RTC_ClearITPendingBit(RTC_IT_SEC);
TimeDisplay = 1; //时间更新标志置位
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
/* 23:59:59 */
if (RTC_GetCounter() == 0x00015180){
RTC_SetCounter(0x0);
RTC_WaitForLastTask();
}
}
}
函数RTC_GetCounter定义在stm32f10x_rtc.c中的第133行,声明在stm32f10x_rtc.c中的第106行。表示满足一天的时间,需要对时、分、秒全部置零。
源代码为
/**
* @brief This function handles RTC global interrupt request.
* @param None
* @retval None
*/
void RTC_IRQHandler(void)
{
if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
{
/* Clear the RTC Second interrupt */
RTC_ClearITPendingBit(RTC_IT_SEC);
/* Toggle LED1 */
STM_EVAL_LEDToggle(LED1);
/* Enable time update */
TimeDisplay = 1;
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
}
}
其中变量TimeDisplay 为秒数改变标志位,在stm32f10x_it.c定义为
extern uint32_t TimeDisplay;
在main.c中定义为
uint32_t TimeDisplay = 0;
只需将代码STM_EVAL_LEDToggle(LED1);去掉,在if语句内添加判断当前的时间是否达到一天的时间,即24时0分0秒。如果是,则从0时0分0秒开始计算。
RTC时间显示讲解
RTC时间是以秒计算的,即秒数不停的加一,没有分和时的概念,需要进行转换。
RTC时间显示及时分转换的代码为
/**
* @说明 显示当前时间
* @参数 TimeVar:RTC Counter值
* @返回值 None
*/
uint8_t text[20];
void Time_Display(u32 TimeVar)
{
u32 THH = 0, TMM = 0, TSS = 0;
/* Compute hours */
THH = TimeVar / 3600;
/* Compute minutes */
TMM = (TimeVar % 3600) / 60;
/* Compute seconds */
TSS = (TimeVar % 3600) % 60;
sprintf((char *)text,"Time: %0.2d:%0.2d:%0.2d",THH, TMM, TSS);
LCD_DisplayStringLine(Line7,text);
}