你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

怎么用STM32F103RTC进行时钟的配置

[复制链接]
worldzxw 提问时间:2016-3-4 08:57 /
请问怎么利用STM32F103的RTC进行时钟配置
收藏 评论7 发布时间:2016-3-4 08:57

举报

7个回答
zhangdaijin 回答时间:2016-3-4 10:52:42
原子教程里有
Angel_YY 回答时间:2018-3-7 11:12:31
本帖最后由 Angel_YY 于 2018-3-7 17:18 编辑

以下是原子的RTC试验代码RTC部分,可以参考。完整工程可以参考文尾的附件文件。

  1. #include "sys.h"
  2. #include "delay.h"
  3. #include "usart.h"
  4. #include "rtc.h"                     
  5. //Mini STM32开发板
  6. //RTC实时时钟 驱动代码                        
  7. //正点原子@ALIENTEK
  8. //2010/6/6
  9.            
  10. _calendar_obj calendar;//时钟结构体

  11. static void RTC_NVIC_Config(void)
  12. {        
  13.   NVIC_InitTypeDef NVIC_InitStructure;
  14.         NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;                //RTC全局中断
  15.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;        //先占优先级1位,从优先级3位
  16.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        //先占优先级0位,从优先级4位
  17.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                //使能该通道中断
  18.         NVIC_Init(&NVIC_InitStructure);                //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
  19. }

  20. //实时时钟配置
  21. //初始化RTC时钟,同时检测时钟是否工作正常
  22. //BKP->DR1用于保存是否第一次配置的设置
  23. //返回0:正常
  24. //其他:错误代码

  25. u8 RTC_Init(void)
  26. {
  27.         //检查是不是第一次配置时钟
  28.         u8 temp=0;
  29.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);        //使能PWR和BKP外设时钟   
  30.         PWR_BackupAccessCmd(ENABLE);        //使能后备寄存器访问  
  31.         if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050)                //从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎
  32.                 {                                 
  33.                 BKP_DeInit();        //复位备份区域         
  34.                 RCC_LSEConfig(RCC_LSE_ON);        //设置外部低速晶振(LSE),使用外设低速晶振
  35.                 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET&&temp<250)        //检查指定的RCC标志位设置与否,等待低速晶振就绪
  36.                         {
  37.                         temp++;
  38.                         delay_ms(10);
  39.                         }
  40.                 if(temp>=250)return 1;//初始化时钟失败,晶振有问题            
  41.                 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);                //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟   
  42.                 RCC_RTCCLKCmd(ENABLE);        //使能RTC时钟  
  43.                 RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
  44.                 RTC_WaitForSynchro();                //等待RTC寄存器同步  
  45.                 RTC_ITConfig(RTC_IT_SEC, ENABLE);                //使能RTC秒中断
  46.                 RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
  47.                 RTC_EnterConfigMode();/// 允许配置        
  48.                 RTC_SetPrescaler(32767); //设置RTC预分频的值
  49.                 RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
  50.                 RTC_Set(2015,1,14,17,42,55);  //设置时间        
  51.                 RTC_ExitConfigMode(); //退出配置模式  
  52.                 BKP_WriteBackupRegister(BKP_DR1, 0X5050);        //向指定的后备寄存器中写入用户程序数据
  53.                 }
  54.         else//系统继续计时
  55.                 {

  56.                 RTC_WaitForSynchro();        //等待最近一次对RTC寄存器的写操作完成
  57.                 RTC_ITConfig(RTC_IT_SEC, ENABLE);        //使能RTC秒中断
  58.                 RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
  59.                 }
  60.         RTC_NVIC_Config();//RCT中断分组设置                                                         
  61.         RTC_Get();//更新时间        
  62.         return 0; //ok

  63. }                                                     
  64. //RTC时钟中断
  65. //每秒触发一次  
  66. //extern u16 tcnt;
  67. void RTC_IRQHandler(void)
  68. {                 
  69.         if (RTC_GetITStatus(RTC_IT_SEC) != RESET)//秒钟中断
  70.         {                                                        
  71.                 RTC_Get();//更新时间   
  72.         }
  73.         if(RTC_GetITStatus(RTC_IT_ALR)!= RESET)//闹钟中断
  74.         {
  75.                 RTC_ClearITPendingBit(RTC_IT_ALR);                //清闹钟中断                  
  76.           RTC_Get();                                //更新时间   
  77.           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);//输出闹铃时间        
  78.                
  79.           }                                                                                                   
  80.         RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW);                //清闹钟中断
  81.         RTC_WaitForLastTask();                                                                                          
  82. }
  83. //判断是否是闰年函数
  84. //月份   1  2  3  4  5  6  7  8  9  10 11 12
  85. //闰年   31 29 31 30 31 30 31 31 30 31 30 31
  86. //非闰年 31 28 31 30 31 30 31 31 30 31 30 31
  87. //输入:年份
  88. //输出:该年份是不是闰年.1,是.0,不是
  89. u8 Is_Leap_Year(u16 year)
  90. {                          
  91.         if(year%4==0) //必须能被4整除
  92.         {
  93.                 if(year%100==0)
  94.                 {
  95.                         if(year%400==0)return 1;//如果以00结尾,还要能被400整除            
  96.                         else return 0;   
  97.                 }else return 1;   
  98.         }else return 0;        
  99. }                                    
  100. //设置时钟
  101. //把输入的时钟转换为秒钟
  102. //以1970年1月1日为基准
  103. //1970~2099年为合法年份
  104. //返回值:0,成功;其他:错误代码.
  105. //月份数据表                                                                                         
  106. u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表         
  107. //平年的月份日期表
  108. const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};
  109. u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
  110. {
  111.         u16 t;
  112.         u32 seccount=0;
  113.         if(syear<1970||syear>2099)return 1;           
  114.         for(t=1970;t<syear;t++)        //把所有年份的秒钟相加
  115.         {
  116.                 if(Is_Leap_Year(t))seccount+=31622400;//闰年的秒钟数
  117.                 else seccount+=31536000;                          //平年的秒钟数
  118.         }
  119.         smon-=1;
  120.         for(t=0;t<smon;t++)           //把前面月份的秒钟数相加
  121.         {
  122.                 seccount+=(u32)mon_table[t]*86400;//月份秒钟数相加
  123.                 if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数           
  124.         }
  125.         seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加
  126.         seccount+=(u32)hour*3600;//小时秒钟数
  127.     seccount+=(u32)min*60;         //分钟秒钟数
  128.         seccount+=sec;//最后的秒钟加上去

  129.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);        //使能PWR和BKP外设时钟  
  130.         PWR_BackupAccessCmd(ENABLE);        //使能RTC和后备寄存器访问
  131.         RTC_SetCounter(seccount);        //设置RTC计数器的值

  132.         RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成         
  133.         return 0;            
  134. }

  135. //初始化闹钟                  
  136. //以1970年1月1日为基准
  137. //1970~2099年为合法年份
  138. //syear,smon,sday,hour,min,sec:闹钟的年月日时分秒   
  139. //返回值:0,成功;其他:错误代码.
  140. u8 RTC_Alarm_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
  141. {
  142.         u16 t;
  143.         u32 seccount=0;
  144.         if(syear<1970||syear>2099)return 1;           
  145.         for(t=1970;t<syear;t++)        //把所有年份的秒钟相加
  146.         {
  147.                 if(Is_Leap_Year(t))seccount+=31622400;//闰年的秒钟数
  148.                 else seccount+=31536000;                          //平年的秒钟数
  149.         }
  150.         smon-=1;
  151.         for(t=0;t<smon;t++)           //把前面月份的秒钟数相加
  152.         {
  153.                 seccount+=(u32)mon_table[t]*86400;//月份秒钟数相加
  154.                 if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数           
  155.         }
  156.         seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加
  157.         seccount+=(u32)hour*3600;//小时秒钟数
  158.     seccount+=(u32)min*60;         //分钟秒钟数
  159.         seccount+=sec;//最后的秒钟加上去                             
  160.         //设置时钟
  161.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);        //使能PWR和BKP外设时钟   
  162.         PWR_BackupAccessCmd(ENABLE);        //使能后备寄存器访问  
  163.         //上面三步是必须的!
  164.         
  165.         RTC_SetAlarm(seccount);

  166.         RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成         
  167.         
  168.         return 0;            
  169. }


  170. //得到当前的时间
  171. //返回值:0,成功;其他:错误代码.
  172. u8 RTC_Get(void)
  173. {
  174.         static u16 daycnt=0;
  175.         u32 timecount=0;
  176.         u32 temp=0;
  177.         u16 temp1=0;         
  178.     timecount=RTC_GetCounter();         
  179.         temp=timecount/86400;   //得到天数(秒钟数对应的)
  180.         if(daycnt!=temp)//超过一天了
  181.         {         
  182.                 daycnt=temp;
  183.                 temp1=1970;        //从1970年开始
  184.                 while(temp>=365)
  185.                 {                                 
  186.                         if(Is_Leap_Year(temp1))//是闰年
  187.                         {
  188.                                 if(temp>=366)temp-=366;//闰年的秒钟数
  189.                                 else {temp1++;break;}  
  190.                         }
  191.                         else temp-=365;          //平年
  192.                         temp1++;  
  193.                 }   
  194.                 calendar.w_year=temp1;//得到年份
  195.                 temp1=0;
  196.                 while(temp>=28)//超过了一个月
  197.                 {
  198.                         if(Is_Leap_Year(calendar.w_year)&&temp1==1)//当年是不是闰年/2月份
  199.                         {
  200.                                 if(temp>=29)temp-=29;//闰年的秒钟数
  201.                                 else break;
  202.                         }
  203.                         else
  204.                         {
  205.                                 if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年
  206.                                 else break;
  207.                         }
  208.                         temp1++;  
  209.                 }
  210.                 calendar.w_month=temp1+1;        //得到月份
  211.                 calendar.w_date=temp+1;          //得到日期
  212.         }
  213.         temp=timecount%86400;                     //得到秒钟数              
  214.         calendar.hour=temp/3600;             //小时
  215.         calendar.min=(temp%3600)/60;         //分钟        
  216.         calendar.sec=(temp%3600)%60;         //秒钟
  217.         calendar.week=RTC_Get_Week(calendar.w_year,calendar.w_month,calendar.w_date);//获取星期   
  218.         return 0;
  219. }         
  220. //获得现在是星期几
  221. //功能描述:输入公历日期得到星期(只允许1901-2099年)
  222. //输入参数:公历年月日
  223. //返回值:星期号                                                                                                                                                                                 
  224. u8 RTC_Get_Week(u16 year,u8 month,u8 day)
  225. {        
  226.         u16 temp2;
  227.         u8 yearH,yearL;
  228.         
  229.         yearH=year/100;        yearL=year%100;
  230.         // 如果为21世纪,年份数加100  
  231.         if (yearH>19)yearL+=100;
  232.         // 所过闰年数只算1900年之后的  
  233.         temp2=yearL+yearL/4;
  234.         temp2=temp2%7;
  235.         temp2=temp2+day+table_week[month-1];
  236.         if (yearL%4==0&&month<3)temp2--;
  237.         return(temp2%7);
  238. }      
复制代码

                    
完成工程文件:

实验15 RTC实验.zip

下载

378.13 KB, 下载次数: 16, 下载积分: ST金币 -1

评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

zero99 回答时间:2018-3-7 16:34:24
Angel_YY 发表于 2018-3-7 11:12
以下是原子的RTC试验代码RTC部分,可以参考。完整工程可以参考文尾的附件文件。

#include "sys.h"

谢谢支持,不过如果这样插代码可能看起来更好哦
https://www.stmcu.org.cn/module/forum/thread-612887-1-1.html
Angel_YY 回答时间:2018-3-7 17:17:31
zero99 发表于 2018-3-7 16:34
谢谢支持,不过如果这样插代码可能看起来更好哦
https://www.stmcu.org.cn/module/forum/thread-612887-1-1.h ...

好的,下次一定使用插入代码方式。
zero99 回答时间:2018-3-8 10:39:16
Angel_YY 发表于 2018-3-7 17:17
好的,下次一定使用插入代码方式。

yangzhi3963 回答时间:2018-10-1 10:48:23
下载学习一下,谢谢分享。
orange3719 回答时间:2020-6-29 11:12:56
学习

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版