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

【零基础学习STM32】第十讲:RTC实时时钟实验——显示日期

[复制链接]
kkhkbb 发布时间:2018-3-22 10:15
本帖最后由 kkhkbb 于 2018-3-22 10:38 编辑

一、概述
1、实时时钟定
      实时时钟(RTC)是一个独立的BCD定时器/计数器。RTC提供一个日历时钟和两个可编程闹钟中断,以及一个具有中断功能的周期性可编程唤醒标志。RTC还包含用于管理低功耗模式的自动唤醒单元。
      两个32位寄存器包含二进码十进位格式(BCD)的秒、分钟、小时(12或24小时制)、星期几、日期、月份和年份。此外,还可以提供二进制格式的亚秒值。
     系统可以自动将月份的天数补偿位28、29(闰年),30和31天。并且还可以进行夏令时的补偿。
     其他32位寄存器还包括可编程的闹钟亚秒、秒、分钟、小时、星期几和日期。此外,还可以使用数字校准功能对晶振精度的偏差进行补偿。
     上电复位后,所有RTC寄存器都会受到保护,以防止可能的非正常写访问。
     无论器件状态如何(运行模式、低功耗模式或处于复位状态),只要电源电压保持在工作范围内,RTC使不会停止工作。
2、实时时钟主要特性
      RTC的主要特性如下:
  • 包含亚秒、秒、分钟、小时(12/24小时制)、星期几、日期、月份和年份的日期。
  • 软件可编程的夏令时补偿。
  • 两个具有中断功能的可编程闹钟。可通过任意日历字段的组合驱动闹钟。
  • 自动唤醒单元,可周期性地生成标志以触发自动唤醒中断。
  • 参考时钟检测:可使用更加精确的第二时钟源(50Hz或60Hz)来提高日历的精确度。
  • 利用亚秒级移位特性与外部时钟实现精确同步。
  • 可屏蔽中断/事件:
         —  闹钟A
         —  闹钟B
         —  唤醒中断
         —  时间戳
         —  入侵检测
  • 数字校准电路(周期性计数器调整)。
        —  精度为5ppm。
        —  精度为0.95ppm, 在数秒钟的校准窗口中获得。
  • 用于时间保存的时间戳功能(1个事件)。
  • 入侵检测:
       —  2个带可配置过滤器和内部上拉的入侵事件。
  • 20个备份寄存器(80字节)。发生入侵检测事件时,将复位备份寄存器。
  • 复用功能输出(RTC_OUT),可选择以下两个输出之一:

      — RTC_CALIB:512Hz或1Hz时钟输出(LSE频率为32.768kHZ)。可通过将RTC_CR寄存器中的COE【23】位置1来使能此输出。该输出可连接到器件RTC_AF1功能。
      — RTC_ALARM(闹钟A、闹钟B或唤醒)。可通过配置RTC_CR寄存器的OSEL【1:0】位选择此输出。该输出可连接到器件RTC_AF1功能。
  • RTC复用功能输入:

     — RTC_TS:时间戳事件检测。该输入可连接到器件RTC_AF1和RTC_AF2功能。
     — RTC_TAMP1:TAMPER1 事件检测。该输入可连接到器件RTC_AF1和RTC_AF2功能。
     — RTC_TAMP2:TAMPER2 事件检测。
     — RTC_REFIN:参考时钟输入(通常为市电,50Hz或60Hz)。
二、硬件电路
1、时钟源
      iCore3异构双核心工控板采用32.768K无源晶体为系统提供RTC实时时钟,其电路连接图如下所示。32.768KHz外部无源晶体连接 OSC32_INOSC32_OUT两引脚之间,为获得稳定的频率必须加两个电容构成外部震荡电路。
图10_0.png
10_0 外部振荡电路
2、备用电源
     RTC实时时钟在iCore3电路中具有备用电源,时刻保证时钟通电。
图10_1.png
10_1 备用电池电路

三、实验原理
       STM32的实时时钟(RTC)是一个独立的定时器,有一组连续计数的计时器,通过软件来对其进行相关的配置,可以提供时钟功能,通过修改计数器的值可以调整时钟,最终通过串口在终端显示时间。
四、源代码
1、主函数
  1. /*
  2. * Name                : main
  3. * Description         : ---
  4. * Author              : ysloveivy.
  5. *
  6. * History
  7. * --------------------
  8. * Rev                 : 0.00
  9. * Date                : 11/23/2015
  10. *
  11. * create.
  12. * --------------------
  13. */
  14. int main(void)
  15. {
  16.         int i;
  17.         RTC_TimeTypeDef rtc_time;
  18.         RTC_DateTypeDef rtc_date;
  19.         int second_bak = 0;
  20.         led.initialize();
  21.         LED_RED_ON;
  22.         rtc.initialize();
  23.         usart4.initialize(115200);
  24.         usart4.printf("\x0c");                           //清屏        
  25.         usart4.printf("\033[1;32;40m");           //设置字体终端为绿色
  26.         usart4.printf("\r\n\r\nhello! I am iCore3!\r\n\r\n\r\n");
  27.         while(1){
  28.         for(i = 0;i < 1000000;i++);
  29.         //读取RTC日期和时间
  30.         RTC_GetTime(RTC_Format_BIN,&rtc_time);
  31.         RTC_GetDate(RTC_Format_BIN,&rtc_date);
  32.         //当秒数据与备份不一致时,向终端打印时间/日期
  33.         if(second_bak != rtc_time.RTC_Seconds){
  34.         usart4.printf("  %02d:%02d:%02d  ",rtc_time.RTC_Hours,rtc_time.RTC_Minutes,rtc_time.RTC_Seconds);
  35.         usart4.printf("20%02d-%02d-%02d  \r",rtc_date.RTC_Year,rtc_date.RTC_Month,rtc_date.RTC_Date);\
  36.         second_bak = rtc_time.RTC_Seconds;         //秒数据备份
  37.                 }
  38.         }
  39. }
复制代码
2、RTC初始化
  1. /*
  2. * Name               : initialize
  3. * Description        : ---
  4. * Author             : ysloveivy.
  5. *
  6. * History
  7. * -------------------
  8. * Rev                : 0.00
  9. * Date               : 11/23/2015
  10. *
  11. * create.
  12. * -------------------
  13. */
  14. static int initialize(void)
  15. {
  16.                               //判断读到的备份寄存器的值与写入的值是否一样
  17.         if(RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x32F2){
  18.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);   
  19.                                                                //使能PWR时钟
  20.                 PWR_BackupAccessCmd(ENABLE);
  21. RCC_BackupResetCmd(ENABLE);
  22.                 RCC_BackupResetCmd(DISABLE);
  23.                 RCC_LSEConfig(RCC_LSE_ON);                                  //LSE 开启   
  24. while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) ==RESET);          //检查指定的RCC标志位设置与否,等待低速晶振就绪
  25.                 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);       //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟   
  26.                 RCC_RTCCLKCmd(ENABLE);                                 //使能RTC时钟
  27. RTC_WaitForSynchro();                                            
  28.                                                       //等待APB1和RTC等时钟同步
  29.                 rtc_set_time(13,57,12,RTC_H12_PM);                         //设置时间
  30.                 rtc_set_date(15,11,28,6);                        //设置日期
  31.                 RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2);       //向备份寄存器中写入数值
  32.         }
  33.         return 0;
  34. }
  35. /*
  36. * Name               : initialize
  37. * Description        : ---
  38. * Author             : ysloveivy.
  39. *
  40. * History
  41. * -------------------
  42. * Rev                : 0.00
  43. * Date               : 11/23/2015
  44. *
  45. * create.
  46. * -------------------
  47. */
  48. static int rtc_set_time(unsigned char hour,unsigned char min,unsigned char sec,unsigned char ampm)
  49. {
  50.         //设置时间
  51.         RTC_TimeTypeDef RTC_TimeTypeInitStructure;
  52.         RTC_TimeTypeInitStructure.RTC_Hours=hour;
  53.         RTC_TimeTypeInitStructure.RTC_Minutes=min;
  54.         RTC_TimeTypeInitStructure.RTC_Seconds=sec;
  55.         RTC_TimeTypeInitStructure.RTC_H12=ampm;
  56.         RTC_SetTime(RTC_Format_BIN,&RTC_TimeTypeInitStructure);
  57.         return 0;
  58. }
复制代码
3、RTC配置介绍
  1. static int initialize(void)
  2. {
  3.                                                                                                       //判断读到的备份寄存器的值与写入的值是否一样
  4.         if(RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x32F2){
  5.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);   
  6.                                                                                                                   //使能PWR时钟
  7.                 PWR_BackupAccessCmd(ENABLE);
  8. RCC_BackupResetCmd(ENABLE);
  9.                 RCC_BackupResetCmd(DISABLE);
  10.                 RCC_LSEConfig(RCC_LSE_ON);                                //LSE 开启   
  11. while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) ==RESET);     //检查指定的RCC标志位设置与否,等待低速晶振就绪
  12.                 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);     //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟   
  13.                 RCC_RTCCLKCmd(ENABLE);           //使能RTC时钟
  14. RTC_WaitForSynchro();                                            
  15.                 //等待APB1和RTC等时钟同步
  16.                 rtc_set_time(13,57,12,RTC_H12_PM);                //设置时间
  17.                 rtc_set_date(15,11,28,6);                                  //设置日期
  18.                 RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2);  //向备份寄存器中写入数值
  19.         }
  20.         return 0;
  21. }
  22. static int rtc_set_date(unsigned char year,unsigned char month,unsigned char date,unsigned char week)
  23. {
  24.         //设置日期
  25.         RTC_DateTypeDef RTC_DateTypeInitStructure;
  26.         RTC_DateTypeInitStructure.RTC_Date=date;
  27.         RTC_DateTypeInitStructure.RTC_Month=month;
  28.         RTC_DateTypeInitStructure.RTC_WeekDay=week;
  29.         RTC_DateTypeInitStructure.RTC_Year=year;
  30.         RTC_SetDate(RTC_Format_BIN,&RTC_DateTypeInitStructure);
  31.         return 0;
  32. }
复制代码
4、结构体介绍

  1. /**
  2.   * @brief  RTC Init structures definition  
  3.   */
  4. typedef struct
  5. {
  6.   uint32_t RTC_HourFormat;        指定RTC小时格式,
  7. 这个参数可以是@ref rtc_hour_format的值。
  8.   uint32_t RTC_AsynchPrediv;      指定RTC异步预分值,
  9. 此参数必须设置为低于0x7F的值。
  10.   uint32_t RTC_SynchPrediv;       指定RTC同步预分值,
  11. 此参数必须设置为低于0x7FFF的值。
  12. }RTC_InitTypeDef;
  13. /**
  14.   * @brief  RTC Time structure definition  
  15.   */
  16. typedef struct
  17. {
  18.   uint8_t RTC_Hours;        指定RTC时间小时,此参数必须设置为0-12范围内的值。如果选择RTC_HourFormat_12,则为0-23。该RTC_HourFormat_24被选中。
  19.   uint8_t RTC_Minutes;             指定RTC时间分钟,
  20. 此参数必须设置为0-59范围内值。
  21.   uint8_t RTC_Seconds;             指定RTC时间秒,
  22. 此参数必须设置为0-59范围内的值。
  23.   uint8_t RTC_H12;                  指定RTC AM/PM时间,
  24. 这个参数可以是@ref rtc_am_pm_definition的值。
  25. }RTC_TimeTypeDef;
  26. /**
  27.   * @brief  RTC Date structure definition  
  28.   */
  29. typedef struct
  30. {
  31.   uint8_t RTC_WeekDay;           指定RTC日期工作日,这个参数可以是@refrtc_weekday_definition的值。
  32.   uint8_t RTC_Month;             指定RTC日期月(BCD格式),这个参数可以是@ref rtc_month_date_definition的值。
  33.   uint8_t RTC_Date;               指定RTC日期,此参数必须设置为1-31范围内的值。
  34.   uint8_t RTC_Year;               指定RTC日期年,此参数必须设置为0-99范围内的值。
  35. }RTC_DateTypeDef;
  36. /**
  37.   * @brief  RTC Alarm structure definition  
  38.   */
  39. typedef struct
  40. {
  41.   RTC_TimeTypeDef RTC_AlarmTime;     指定RTC警报时间成员。
  42.   uint32_t RTC_AlarmMask;             指定RTC报警面具,这个参数可以是@ref rtc_alarmmask_definition 的值。
  43.   uint32_t RTC_AlarmDateWeekDaySel;  指定RTC警报是在日期或工作日,
  44. 这个参数可以是@ref rtc_alarmdateweekday_definition的值。
  45.   uint8_t RTC_AlarmDateWeekDay;      指定RTC报警日期/工作日。
  46. 如果选择了警报日期,则该参数。
  47. 必须设置为1-31范围内的值。
  48. 如果选择了闹钟工作日,这个。
  49. 参数可以是@ref rtc_weekday_definition的值。
  50. }RTC_AlarmTypeDef;
复制代码

五、实验现象

      在终端屏幕上可以看到显示的时间和日期(如下图所示)。

图10_2.png

图10_3 实验现象图

六、代码包下载

     网盘:https://pan.baidu.com/s/1jHuZcnc



















收藏 评论1 发布时间:2018-3-22 10:15

举报

1个回答
yangzhi3963 回答时间:2018-9-10 12:13:48
真不错,学习一下。

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

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