打印
[应用相关]

基于STM32 RTC闹钟时钟配置经验分享

[复制链接]
336|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
flycamelaaa|  楼主 | 2023-5-4 10:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
实验效果
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);
  •         };
  • }


复制代码


使用特权

评论回复
沙发
flycamelaaa|  楼主 | 2023-5-4 10:13 | 只看该作者
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);
  • }


复制代码



使用特权

评论回复
板凳
flycamelaaa|  楼主 | 2023-5-4 10:13 | 只看该作者
小贴士:
RTC具有写保护功能 每次操作要修改掉
if (BKP_ReadBackupRegister(BKP_DR1) != 0x5051)
BKP_WriteBackupRegister(BKP_DR1, 0X5051);
这两行代码的值 最简便就是5051和5050变换
如果程序报错 很可能是以下问题
没有添加蜂鸣器源文件和头文件
main函数没有初始化蜂鸣器

使用特权

评论回复
地板
Wordsworth| | 2024-3-22 07:05 | 只看该作者

从定时器为TIM2,从模式选择为门控模式,触发源选择ITR0,开启定时器2中断。

使用特权

评论回复
5
Clyde011| | 2024-3-22 08:08 | 只看该作者

根据实际需求选择用哪种方式

使用特权

评论回复
6
公羊子丹| | 2024-3-22 09:01 | 只看该作者

每条大电流的地线要短而宽

使用特权

评论回复
7
万图| | 2024-3-22 10:04 | 只看该作者

使能主从模式,触发事件选择为更新事件,不需要开启中断。

使用特权

评论回复
8
Uriah| | 2024-3-22 11:07 | 只看该作者

主从定时的方式占用CPU资源少

使用特权

评论回复
9
帛灿灿| | 2024-3-22 13:03 | 只看该作者

主定时器为TIM1,通道2配置为PWM输出

使用特权

评论回复
10
Bblythe| | 2024-3-22 14:06 | 只看该作者

中断计数的方式实现简

使用特权

评论回复
11
周半梅| | 2024-3-22 16:02 | 只看该作者

多个电容并联

使用特权

评论回复
12
Pulitzer| | 2024-3-22 17:05 | 只看该作者

都可以产生指定个数的PWM脉冲

使用特权

评论回复
13
童雨竹| | 2024-3-22 19:01 | 只看该作者

作为功率开关管和整流器的散热部分

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

528

主题

1720

帖子

0

粉丝