超简单 STM32 RTC闹钟 时钟配置

基于正点原子的RTC时钟
实验效果
LCD屏幕显示 年月日时分秒 设置任意时间 到时间蜂鸣器启动
直接上代码

主函数

简单说 就是初始化各个部件
然后让LED1 闪烁来提示系统的正常运行
显示屏显示实时时间
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"	
#include "usmart.h"	 
#include "rtc.h" 
#include "oled.h"
#include "beep.h" 
 
 int main(void)
 {
     	 
 	u8 t=0;	
	delay_init();	    	 	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	uart_init(115200);	 	//
 	LED_Init();			     //
	LCD_Init();
  OLED_Init();			// 
	OLED_Clear();	 
	usmart_dev.init(SystemCoreClock/1000000);	//
  BEEP_Init(); 	 
	RTC_Init();	  			//
	POINT_COLOR=RED;//
	LCD_ShowString(60,50,200,16,16,"Elite STM32");	
	LCD_ShowString(60,70,200,16,16,"RTC TEST");	
	LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
	LCD_ShowString(60,110,200,16,16,"2015/1/14");		
	//ÏÔʾʱ¼ä
	POINT_COLOR=BLUE;//
	LCD_ShowString(60,130,200,16,16,"    -  -  ");	   
	LCD_ShowString(60,162,200,16,16,"  :  :  ");		    
	while(1)
	{
     								    
		if(t!=calendar.sec)
		{
     
			t=calendar.sec;
			//LCD_ShowNum(60,130,calendar.w_year,4,16);
      OLED_ShowNum(0,2,calendar.w_year,4,16);			
			//LCD_ShowNum(100,130,calendar.w_month,2,16);
      OLED_ShowNum(0,4,calendar.w_month,2,16);		
			//LCD_ShowNum(124,130,calendar.w_date,2,16);
      OLED_ShowNum(0,6,calendar.w_date,2,16);			
			switch(calendar.week)
			{
     
				case 0:
					LCD_ShowString(60,148,200,16,16,"Sunday   ");
					break;
				case 1:
					LCD_ShowString(60,148,200,16,16,"Monday   ");
					break;
				case 2:
					LCD_ShowString(60,148,200,16,16,"Tuesday  ");
					break;
				case 3:
					LCD_ShowString(60,148,200,16,16,"Wednesday");
					break;
				case 4:
					LCD_ShowString(60,148,200,16,16,"Thursday ");
					break;
				case 5:
					LCD_ShowString(60,148,200,16,16,"Friday   ");
					break;
				case 6:
					LCD_ShowString(60,148,200,16,16,"Saturday ");
					break;  
			}
			LCD_ShowNum(60,162,calendar.hour,2,16);									  
			LCD_ShowNum(84,162,calendar.min,2,16);									  
			LCD_ShowNum(108,162,calendar.sec,2,16);
			LED0=!LED0;
		}	
		delay_ms(10);								  
	};  
 }

RTC配置函数
这里说明一下 我的代码是可以直接复制替换的
说下基于原子我修改了哪些
使能了时钟和闹钟中断 之前只使能了时钟(RTC_ITConfig(RTC_IT_SEC|RTC_IT_ALR, ENABLE);)
调用了设置闹钟值的函数(RTC_Alarm_Set(2021,1,13,16,39,59);)


在闹钟中断的函数中 增加了蜂鸣器 启动 BEEP=1;
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "rtc.h" 	
#include "led.h"
#include "beep.h" 

	   
_calendar_obj calendar;
 
static void RTC_NVIC_Config(void)
{
     	
  NVIC_InitTypeDef NVIC_InitStructure;
	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);		
}


u8 RTC_Init(void)
{
     

    u8 temp=0;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);	
	PWR_BackupAccessCmd(ENABLE);	
	if (BKP_ReadBackupRegister(BKP_DR1) != 0x5051)		
		{
     	 			 
		BKP_DeInit();
		RCC_LSEConfig(RCC_LSE_ON);	
		while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET&&temp<250)	
			{
     
			temp++;
			delay_ms(10);
			}
		if(temp>=250)return 1;	    
		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);		  
		RCC_RTCCLKCmd(ENABLE);	
		RTC_WaitForLastTask();	
		RTC_WaitForSynchro();		 
		RTC_ITConfig(RTC_IT_SEC|RTC_IT_ALR, ENABLE);	
		RTC_WaitForLastTask();	
		RTC_EnterConfigMode();
		RTC_SetPrescaler(32767); 
		RTC_WaitForLastTask();	
		RTC_Set(2021,1,13,16,38,59);  
        RTC_Alarm_Set(2021,1,13,16,39,59);			
		RTC_ExitConfigMode(); 
		BKP_WriteBackupRegister(BKP_DR1, 0X5051);	
		}
	else//ϵͳ¼ÌÐø¼Æʱ
		{
     

		RTC_WaitForSynchro();	
		RTC_ITConfig(RTC_IT_SEC, ENABLE);	
		RTC_WaitForLastTask();	
		}
	RTC_NVIC_Config();	    				     
	RTC_Get();	
	return 0; 

}		 				    
 
void RTC_IRQHandler(void)
{
     		 
	if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
	{
     							
		RTC_Get();   
 	}
	if(RTC_GetITStatus(RTC_IT_ALR)!= RESET)
	{
     
		RTC_ClearITPendingBit(RTC_IT_ALR);		  	
	  RTC_Get();				
  	printf("Alarm Time:%d-%d-%d %d:%d:%d\n",calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);
		BEEP=1;
  	} 				  								 
	RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW);		
	RTC_WaitForLastTask();	  	    						 	   	 
}

u8 Is_Leap_Year(u16 year)
{
     			  
	if(year%4==0) //
	{
      
		if(year%100==0) 
		{
      
			if(year%400==0)return 1;  
			else return 0;   
		}else return 1;   
	}else return 0;	
}	 			   
										 
u8 const table_week[12]={
     0,3,3,6,1,4,6,2,5,0,3,5}; 
const u8 mon_table[12]={
     31,28,31,30,31,30,31,31,30,31,30,31};
u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
{
     
	u16 t;
	u32 seccount=0;
	if(syear<1970||syear>2099)return 1;	   
	for(t=1970;t<syear;t++)	
	{
     
		if(Is_Leap_Year(t))seccount+=31622400;
		else seccount+=31536000;			  
	}
	smon-=1;
	for(t=0;t<smon;t++)	   
	{
     
		seccount+=(u32)mon_table[t]*86400;
		if(Is_Leap_Year(syear)&&t==1)seccount+=86400;	   
	}
	seccount+=(u32)(sday-1)*86400;
	seccount+=(u32)hour*3600;
    seccount+=(u32)min*60;	
	seccount+=sec;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);	
	PWR_BackupAccessCmd(ENABLE);	// 
	RTC_SetCounter(seccount);	//
	RTC_WaitForLastTask();	//	
	return 0;	    
}


u8 RTC_Alarm_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
{
     
	u16 t;
	u32 seccount=0;
	if(syear<1970||syear>2099)return 1;	   
	for(t=1970;t<syear;t++)	
	{
     
		if(Is_Leap_Year(t))seccount+=31622400;
		else seccount+=31536000;			 
	}
	smon-=1;
	for(t=0;t<smon;t++)	   
	{
     
		seccount+=(u32)mon_table[t]*86400;
		if(Is_Leap_Year(syear)&&t==1)seccount+=86400;	   
	}
	seccount+=(u32)(sday-1)*86400;
	seccount+=(u32)hour*3600;
    seccount+=(u32)min*60;	 
	seccount+=sec;			    
	//ÉèÖÃʱÖÓ
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);	
	PWR_BackupAccessCmd(ENABLE);	 
	RTC_SetAlarm(seccount);
	RTC_WaitForLastTask();	
	
	return 0;	    
}
u8 RTC_Get(void)
{
     
	static u16 daycnt=0;
	u32 timecount=0; 
	u32 temp=0;
	u16 temp1=0;	  
    timecount=RTC_GetCounter();	 
 	temp=timecount/86400; 
	if(daycnt!=temp)
	{
     	  
		daycnt=temp;
		temp1=1970;	
		while(temp>=365)
		{
     				 
			if(Is_Leap_Year(temp1))
			{
     
				if(temp>=366)temp-=366;
				else {
     temp1++;break;}  
			}
			else temp-=365;	  //ƽÄê 
			temp1++;  
		}   
		calendar.w_year=temp1;
		temp1=0;
		while(temp>=28)
		{
     
			if(Is_Leap_Year(calendar.w_year)&&temp1==1)
			{
     
				if(temp>=29)temp-=29;
				else break; 
			}
			else 
			{
     
				if(temp>=mon_table[temp1])temp-=mon_table[temp1];
				else break;
			}
			temp1++;  
		}
		calendar.w_month=temp1+1;	
		calendar.w_date=temp+1;  	
	}
	temp=timecount%86400;     			   
	calendar.hour=temp/3600;     	
	calendar.min=(temp%3600)/60; 	
	calendar.sec=(temp%3600)%60; 	
	calendar.week=RTC_Get_Week(calendar.w_year,calendar.w_month,calendar.w_date);  
	return 0;
}	 
																						 
u8 RTC_Get_Week(u16 year,u8 month,u8 day)
{
     	
	u16 temp2;
	u8 yearH,yearL;
	
	yearH=year/100;	yearL=year%100;  
	if (yearH>19)yearL+=100;
	temp2=yearL+yearL/4;
	temp2=temp2%7; 
	temp2=temp2+day+table_week[month-1];
	if (yearL%4==0&&month<3)temp2--;
	return(temp2%7);
}			  


小贴士
RTC具有写保护功能 每次操作要修改掉
if (BKP_ReadBackupRegister(BKP_DR1) != 0x5051)
BKP_WriteBackupRegister(BKP_DR1, 0X5051);
这两行代码的值 最简便就是5051和5050变换
如果程序报错 很可能是以下问题
没有添加蜂鸣器源文件和头文件
main函数没有初始化蜂鸣器

你可能感兴趣的:(笔记,c语言,stm32,嵌入式)