STM32小白入门(第13天)-------RTC实时时钟和闹钟事件

一、RTC的概述

RTC就是实时时钟,详细英文 Real Time Clock

STM32小白入门(第13天)-------RTC实时时钟和闹钟事件_第1张图片

二、详细描述

1.使用

STM32小白入门(第13天)-------RTC实时时钟和闹钟事件_第2张图片

2. 中断配置注意事项

STM32小白入门(第13天)-------RTC实时时钟和闹钟事件_第3张图片

STM32小白入门(第13天)-------RTC实时时钟和闹钟事件_第4张图片

三、程序设计

一)RTC唤醒事件

1. RTC的初始化

void rtc_init(void)
{
	/* Enable the PWR clock ,使能电源时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
	
	/* Allow access to RTC,允许访问RTC */
	PWR_BackupAccessCmd(ENABLE);
	

	/* Enable the LSE OSC ,使能外部低速晶振振荡器*/
	RCC_LSEConfig(RCC_LSE_ON);
	
	/* Wait till LSE is ready ,等待外部晶振振荡器准备好*/  
	while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);

	
	/* Select the RTC Clock Source ,选择外部晶振作为RTC的时钟源*/
	RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
	
	
	/* Enable the RTC Clock,使能RTC的时钟 */
	RCC_RTCCLKCmd(ENABLE);
	
	/* Wait for RTC APB registers synchronisation,等待所有的RTC寄存器就绪 */
	RTC_WaitForSynchro();
	
	if (RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x4567)
	{
		/* Configure the RTC data register and RTC prescaler */
		
		/* ck_spre(1Hz) = RTCCLK(LSE) /(uwAsynchPrediv + 1)/(uwSynchPrediv + 1)=32768/(127+1)/(255+1)=1Hz
		
			因为RTC都是以秒作为最小的时间单位
		*/
		my_RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
		my_RTC_InitStructure.RTC_SynchPrediv = 0xFF;
		my_RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;	//24小时格式
		RTC_Init(&my_RTC_InitStructure);

		/* Set the date: Thursday January 11th 2018,2018/01/25 星期四 */
		my_RTC_DateStructure.RTC_Year = 0x18;
		my_RTC_DateStructure.RTC_Month = RTC_Month_January;
		my_RTC_DateStructure.RTC_Date = 0x27;
		my_RTC_DateStructure.RTC_WeekDay = RTC_Weekday_Thursday;
		RTC_SetDate(RTC_Format_BCD, &my_RTC_DateStructure);
		
		/* Set the time to 10h 09mn 15s AM ,早上10:09:15*/
		my_RTC_TimeStructure.RTC_H12     = RTC_H12_PM;
		my_RTC_TimeStructure.RTC_Hours   = 0x21;
		my_RTC_TimeStructure.RTC_Minutes = 0x57;
		my_RTC_TimeStructure.RTC_Seconds = 0x33; 
		
		RTC_SetTime(RTC_Format_BCD, &my_RTC_TimeStructure);  
	
	}
	//关闭唤醒功能
	RTC_WakeUpCmd(DISABLE);
	
	//为唤醒功能选择RTC配置好的时钟源
	RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits);
	
	//设置唤醒计数值为自动重载,写入值默认是0,1->0
	RTC_SetWakeUpCounter(0);
	
	//清除RTC唤醒中断标志
	RTC_ClearITPendingBit(RTC_IT_WUT);
	
	//使能RTC唤醒中断
	RTC_ITConfig(RTC_IT_WUT, ENABLE);

	//使能唤醒功能
	RTC_WakeUpCmd(ENABLE);	
	
	/* 配置外部中断控制线22,实现RTC唤醒*/
	EXTI_ClearITPendingBit(EXTI_Line22);
	EXTI_InitStructure.EXTI_Line = EXTI_Line22;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);
	
	/* 使能RTC唤醒中断 */
	NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	
	/* Indicator for the RTC configuration,写备份寄存器,用于建立判断标志是否要重置RTC的日期与时间 */
	RTC_WriteBackupRegister(RTC_BKP_DR0, 0x4567);
}

2、RTC中断服务程序
void RTC_WKUP_IRQHandler(void)
{
	//检查是否发生了唤醒中断
	if(RTC_GetITStatus(RTC_IT_WUT) != RESET)
	{
		//添加用户代码
		
		//清空相应的标志位
		RTC_ClearITPendingBit(RTC_IT_WUT);
	} 
      EXTI_ClearITPendingBit(EXTI_Line22);
}
//RTC时间设置
//hour,min,sec:小时,分钟,秒钟
//ampm:@RTC_AM_PM_Definitions  :RTC_H12_AM/RTC_H12_PM
//返回值:SUCEE(1),成功
//ERROR(0),进入初始化模式失败  
ErrorStatus RTC_Set_Time(u8 hour,u8 min,u8 sec,u8 ampm)
{
	RTC_TimeTypeDef RTC_TimeTypeInitStructure;
	
	RTC_TimeTypeInitStructure.RTC_Hours = hour;
	RTC_TimeTypeInitStructure.RTC_Minutes = min;
	RTC_TimeTypeInitStructure.RTC_Seconds = sec;
	RTC_TimeTypeInitStructure.RTC_H12 = ampm;
	
	return RTC_SetTime(RTC_Format_BCD, &RTC_TimeTypeInitStructure);
	
}
//RTC日期设置
//year,month,date:年(0~99),月(1~12),日(0~31)
//week:星期(1~7,0,非法!)
//返回值:SUCEE(1),成功
//ERROR(0),进入初始化模式失败 
ErrorStatus RTC_Set_Date(u8 year,u8 month,u8 date,u8 week)
{
	RTC_DateTypeDef RTC_DateTypeInitStructure;
	RTC_DateTypeInitStructure.RTC_Date = date;
	RTC_DateTypeInitStructure.RTC_Month = month;
	RTC_DateTypeInitStructure.RTC_WeekDay = week;
	RTC_DateTypeInitStructure.RTC_Year = year;
	return RTC_SetDate(RTC_Format_BIN,&RTC_DateTypeInitStructure);
}

二)闹钟事件

//设置闹钟时间(按星期闹铃,24小时制)
//week:星期几(1~7) @ref  RTC_Alarm_Definitions
//hour,min,sec:小时,分钟,秒钟
void RTC_Set_AlarmA(u8 week,u8 hour,u8 min,u8 sec)
{ 
	EXTI_InitTypeDef   EXTI_InitStructure;
	RTC_AlarmTypeDef RTC_AlarmTypeInitStructure;
	RTC_TimeTypeDef RTC_TimeTypeInitStructure;
	
	RTC_AlarmCmd(RTC_Alarm_A,DISABLE);//关闭闹钟A 
	
        RTC_TimeTypeInitStructure.RTC_Hours = hour;//小时
	RTC_TimeTypeInitStructure.RTC_Minutes = min;//分钟
	RTC_TimeTypeInitStructure.RTC_Seconds = sec;//秒
	RTC_TimeTypeInitStructure.RTC_H12 = RTC_H12_AM;
  
	RTC_AlarmTypeInitStructure.RTC_AlarmDateWeekDay = week; //星期
	RTC_AlarmTypeInitStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_WeekDay; //按星期闹
	RTC_AlarmTypeInitStructure.RTC_AlarmMask = RTC_AlarmMask_None;    //精确匹配星期,时分秒
	RTC_AlarmTypeInitStructure.RTC_AlarmTime = RTC_TimeTypeInitStructure;
        RTC_SetAlarm(RTC_Format_BIN,RTC_Alarm_A,&RTC_AlarmTypeInitStructure);
 
	
	RTC_ClearITPendingBit(RTC_IT_ALRA);//清除RTC闹钟A的标志
        EXTI_ClearITPendingBit(EXTI_Line17);//清除LINE17上的中断标志位 
	
	RTC_ITConfig(RTC_IT_ALRA,ENABLE);//开启闹钟A中断
	RTC_AlarmCmd(RTC_Alarm_A,ENABLE);//开启闹钟A 
	
	EXTI_InitStructure.EXTI_Line = EXTI_Line17;//LINE17
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发 
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE17
        EXTI_Init(&EXTI_InitStructure);//配置

	NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_IRQn; 
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级1
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
        NVIC_Init(&NVIC_InitStructure);//配置
}

//RTC闹钟中断服务函数
void RTC_Alarm_IRQHandler(void)
{    
	if(RTC_GetFlagStatus(RTC_FLAG_ALRAF)==SET)//ALARM A中断?
	{
		RTC_ClearFlag(RTC_FLAG_ALRAF);//清除中断标志
		printf("ALARM A!\r\n");
	}   
	EXTI_ClearITPendingBit(EXTI_Line17);	//清除中断线17的中断标志 											 
}


你可能感兴趣的:(STM32)