查看: 12326|回复: 7

STM32F4 Discovery RTC

[复制链接]
  • TA的每日心情
    慵懒
    2017-7-30 06:34
  • 签到天数: 1257 天

    连续签到: 2 天

    [LV.10]以坛为家III

    发表于 2013-8-20 17:08:33 | 显示全部楼层 |阅读模式
    分享到:
    STM32F4DiscoveryRTC调试手记
    实现功能:配置RTC实现计时功能,并通过唤醒中断输出当前时间。
    一、硬件改动
    本次调试使用32768Hz晶振,而STM32F4Discovery上并未焊接该晶振,于是硬件需要作出几个改动:
    1.       pic1.jpg
    焊接晶振X3 32768Hz(负载电容为6pFC16C27 6pF
    2.       pic2.jpg
    VBAT直接接到VDD上了,而RTC需要电池供电支持,因而需要拆掉R26,并在VBAT那个焊盘接电池正极
    硬件改动效果图:
    IMG_20130820_114707-2.jpg
    二、所使用的库函数
    在本次实验中,主要使用了stm32f4xx_pwr.c,stm32f4xx_rcc.c, stm32f4xx_rtc.c中的函数,下面对部分函数进行简单的介绍:
    stm32f4xx_pwr.c
    PWR_BackupAccessCmd:通过位带实现设置PWR_CR[8] DBP,该位用于使能/失能RTCRTC备份寄存器及备份SRAM的访问。
    stm32f4xx_rcc.c
    RCC_LSEConfig:实现对RCC_BDCR寄存器的设置,主要是对[2]LSEBYP[0]LSEON进行设置。这里用于启动32768Hz晶振。
    RCC_RTCCLKConfig:实现对RCC_BDCR[9:8]RTCSEL设置,用于选择RTC时钟的时钟源。同时,可能对RCC_CFGR[20:16]RTCPRE设置(使用HSE作为RTC时钟时设置)。
    RCC_RTCCLKCmd:位带操作实现对RCC_BDCR[15]RTCEN设置,用于使能/失能RTC
    stm32f4xx_rtc.c
    首先先看三个结构体:
    typedef struct
    {
    uint32_t RTC_HourFormat;   /*!<Specifies the RTC Hour Format.
                                 This parameter canbe a value of @ref RTC_Hour_Formats */
      
    uint32_t RTC_AsynchPrediv; /*!< Specifies the RTC AsynchronousPredivider value.
                                 This parametermust be set to a value lower than 0x7F*/
      
    uint32_t RTC_SynchPrediv;  /*!<Specifies the RTC Synchronous Predivider value.
                                 This parametermust be set to a value lower than 0x7FFF */
    }RTC_InitTypeDef;
    此结构体用于RTC_Init,即RTC初始化。
    其中,RTC_HourFormat影响RTC_CR[6] FMT:时钟格式,该位影响时钟的表达方式:AM/PM24小时表达方式。
    RTC_AsynchPredivRTC_SynchPrediv则影响RTC_PRER寄存器的值,
    RTC_AsynchPrediv影响[22:16]PREDIV_A[6:0],该值决定ck_apre的频率。
    ck_apre = RTCCLK/(PREDIV_A + 1)
    RTC_SynchPrediv影响[14:0]PREDIV_S,该值决定ck_spre频率。
    ck_spre = ck_apre/( PREDIV_S + 1)
    因此处采用32768Hz晶振,为生成1Hz时钟,故使用:
    RTC_InitStructure.RTC_SynchPrediv = 0xFF;
    RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
    typedef struct
    {
    uint8_t RTC_Hours;    /*!<Specifies the RTC Time Hour.
                            This parameter must be set to a valuein the 0-12 range
                            if theRTC_HourFormat_12 is selected or 0-23 range if
                            the RTC_HourFormat_24is selected. */
    uint8_t RTC_Minutes;  /*!<Specifies the RTC Time Minutes.
                            This parameter must beset to a value in the 0-59 range. */
      
    uint8_t RTC_Seconds;  /*!<Specifies the RTC Time Seconds.
                            This parameter must beset to a value in the 0-59 range. */
    uint8_t RTC_H12;      /*!<Specifies the RTC AM/PM Time.
                            This parameter can be avalue of @ref RTC_AM_PM_Definitions */
    }RTC_TimeTypeDef;
    typedef struct
    {
    uint8_t RTC_WeekDay; /*!< Specifies the RTC Date WeekDay.
                            This parameter can be avalue of @ref RTC_WeekDay_Definitions */
      
    uint8_t RTC_Month;   /*!<Specifies the RTC Date Month (in BCD format).
                            This parameter can be avalue of @ref RTC_Month_Date_Definitions */
    uint8_t RTC_Date;     /*!< Specifies the RTC Date.
                            This parameter must beset to a value in the 1-31 range. */
      
    uint8_t RTC_Year;     /*!<Specifies the RTC Date Year.
                            This parameter must beset to a value in the 0-99 range. */
    }RTC_DateTypeDef;
    上述两个结构体用于保存时间或日期,格式可以为BCD码或二进制数,注意年份RTC_Year的取值范围为0-99
    下面是RTC部分函数。
    RTC_InitRTC初始化
    RTC_EnterInitMode:用于设置RTC_ISRRTC初始化和状态寄存器)[7]INIT初始化模式,在初始化模式下,RTC_TRRTC_CRRTC_PRER均可修改。计时停止直至INIT复位。
    RTC_ExitInitMode:复位RTC_ISR[7]INIT
    时间配置及获取函数:
    ErrorStatus RTC_SetTime(uint32_tRTC_Format, RTC_TimeTypeDef* RTC_TimeStruct); void RTC_GetTime(uint32_tRTC_Format, RTC_TimeTypeDef* RTC_TimeStruct);
    ErrorStatus RTC_SetDate(uint32_tRTC_Format, RTC_DateTypeDef* RTC_DateStruct); void RTC_GetDate(uint32_tRTC_Format, RTC_DateTypeDef* RTC_DateStruct);
    这几个函数实现对RTC_TRRTC_DR的访问获得当前时间及日期。最终,存入这两个寄存器的值为BCD码。而这些函数第二个参数的结构体中所存入的值可以为BCD码,也可以为二进制数,其格式由第一个参数(RTC_Format_BIN/RTC_Format_BCD)指定。
    唤醒中断相关函数:
    RTC_WakeUpClockConfig:影响RTC_CR[2:0]WUCKSEL,确定唤醒时钟ck_wut的时钟源。
    RTC_SetWakeUpCounter:设置RTC_WUTR[15:0]WUT,当WUTE=1时,WUTF标志位每隔(WUT+1)ck_wut时钟周期置位。
    RTC_WakeUpCmd:影响RTC_CR[10]WUTE唤醒时钟使能位。
    备份寄存器:
    STM32F1中是在stm32f10x.bkp.c中实现,这里由RTC实现了。
    RTC_WriteBackupRegisterRTC_ReadBackupRegister实现对相应备份寄存器的读写。
    中断相关:
    RTC_ITConfig:影响RTC_CR[15]TSIE时间戳中断使能、[14]WUTIE唤醒时钟中断使能、[13-12]ALRA(B)IE:闹铃A/B中断使能。
    三、初始化流程及代码
    初始化流程大致如下:
    1) 使能时钟,配置RTC时钟及分频比,获得1Hz的ck_spre时钟。
    2) 配置NVIC相关参数
    3) 唤醒中断配置。因此处需要实现秒中断,故采用ck_spre时钟作为ck_wut时钟源,唤醒时钟计数器设置为0,则可实现秒中断。
    static void RTC_Configuration(void)
    {
           RTC_InitTypeDefRTC_InitStructure;
      /*Enable PWR and BKP clocks */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
      /*Allow access to BKP Domain */
    PWR_BackupAccessCmd(ENABLE);
      /*Enable LSE */
    RCC_LSEConfig(RCC_LSE_ON);
      /*Wait till LSE is ready */
    while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
      {}
      /*Select LSE as RTC Clock Source */
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
      /*Enable RTC Clock */
    RCC_RTCCLKCmd(ENABLE);
      /*Wait for RTC registers synchronization */
    RTC_WaitForSynchro();
          
           /*RTC Init */
           RTC_InitStructure.RTC_HourFormat= RTC_HourFormat_24;   //24 hour format
           //32768/ (1 + 0x7F) = 32768 /128 = 256Hz,
           //256/ (1 + 0xFF) = 1Hz, This is the calender frequecy~
           RTC_InitStructure.RTC_SynchPrediv= 0xFF;
           RTC_InitStructure.RTC_AsynchPrediv= 0x7F;
           if(RTC_Init(&RTC_InitStructure) == ERROR)
                  printf("\r\nRTCinit failed");
           else
                  printf("\r\nRTCinit success");
          
           /*NVIC configuration */
    NVIC_Configuration();
          
           RTC_WakeUpCmd(DISABLE);     //important
      //Configure the RTC WakeUp Clock source: CK_SPRE (1Hz)
      RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits);
    RTC_SetWakeUpCounter(0x0);
           RTC_WakeUpCmd(ENABLE);
           RTC_ClearITPendingBit(RTC_IT_WUT);
           RTC_ITConfig(RTC_IT_WUT,ENABLE);
          
    }
    中断配置流程见RM009023.5RTC interrupt
    使能唤醒中断初始化序列:
    1) 配置并使能EXTI Line22进入中断模式并选择上升沿触发。
    2) 在NVIC中配置RTC_WKUP_IRQ
    3) 配置RTC来产生RTC唤醒时钟事件
    static void NVIC_Configuration(void)
    {
    NVIC_InitTypeDef NVIC_InitStructure;
           EXTI_InitTypeDefEXTI_InitStructure;
          
           /*EXTI Configuration */
           EXTI_ClearITPendingBit(EXTI_Line22);
           EXTI_InitStructure.EXTI_Line= EXTI_Line22;
           EXTI_InitStructure.EXTI_Mode= EXTI_Mode_Interrupt;
           EXTI_InitStructure.EXTI_Trigger= EXTI_Trigger_Rising;
           EXTI_InitStructure.EXTI_LineCmd= ENABLE;
           EXTI_Init(&EXTI_InitStructure);
      /*Configure one bit for preemption priority */
      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
      /*Enable the RTC Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    }
    实验结果如下
    result.jpg
    RTC还有许多功能,如闹铃、时间戳等,有待大家去发掘^ ^

    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2018-2-22 19:39
  • 签到天数: 316 天

    连续签到: 1 天

    [LV.8]以坛为家I

    发表于 2013-8-20 22:31:57 | 显示全部楼层
    沙发!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2016-2-27 20:05
  • 签到天数: 181 天

    连续签到: 1 天

    [LV.7]常住居民III

    发表于 2013-8-21 10:39:01 | 显示全部楼层
    呵呵,刚弄过
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2017-7-30 06:34
  • 签到天数: 1257 天

    连续签到: 2 天

    [LV.10]以坛为家III

     楼主| 发表于 2013-8-22 11:17:42 | 显示全部楼层
    {:soso_e113:}            
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2014-6-11 09:35
  • 签到天数: 15 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    发表于 2013-9-30 15:02:03 | 显示全部楼层
    我懒得改硬件了直接用的LSI时钟
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2017-5-12 10:32
  • 签到天数: 295 天

    连续签到: 1 天

    [LV.8]以坛为家I

    发表于 2013-9-30 15:27:48 | 显示全部楼层
    顶一个~~~~~~~~~~~~~~·
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2015-8-24 16:06
  • 签到天数: 51 天

    连续签到: 1 天

    [LV.5]常住居民I

    发表于 2013-11-14 23:03:26 | 显示全部楼层
    我记得有个片子叫ds1802可以完成这个功能,想问一下楼主,你的时钟初始值是如何配置的?谢谢。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2017-7-30 06:34
  • 签到天数: 1257 天

    连续签到: 2 天

    [LV.10]以坛为家III

     楼主| 发表于 2013-11-14 23:43:36 | 显示全部楼层
    luoxiao 发表于 2013-11-14 23:03
    我记得有个片子叫ds1802可以完成这个功能,想问一下楼主,你的时钟初始值是如何配置的?谢谢。 ...

    调用RTC_SetTime和RTC_SetDate实现
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /5 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-12-24 10:27 , Processed in 0.195615 second(s), 29 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.