基于正点原子的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:%dn",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
{
if(Is_Leap_Year(t))seccount+=31622400;
else seccount+=31536000;
}
smon-=1;
for(t=0;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
{
if(Is_Leap_Year(t))seccount+=31622400;
else seccount+=31536000;
}
smon-=1;
for(t=0;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和5050m
如果程序报错很可能是以下
没有添加蜂鸣器源文件和头文件
主函数没有初始化蜂鸣器
基于正点原子的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:%dn",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
{
if(Is_Leap_Year(t))seccount+=31622400;
else seccount+=31536000;
}
smon-=1;
for(t=0;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
{
if(Is_Leap_Year(t))seccount+=31622400;
else seccount+=31536000;
}
smon-=1;
for(t=0;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和5050m
如果程序报错很可能是以下
没有添加蜂鸣器源文件和头文件
主函数没有初始化蜂鸣器
举报