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

STM32LL库教程之RTC连续闹钟

[复制链接]
海迹天涯 发布时间:2019-1-9 18:11
     在项目中使用STM32RTC闹钟过程中遇到几个问题,百思不得其解,在百度搜索中也没有找到相关内容于是决定打开数据手册深入学习下这个RTC。以往虽然也有使用过RTC这个外设,不过都是拿来主义,导致这次遇到点问题就懵逼了

   先用神器配置CUBE一下:
1.png
2.png
3.png
4.png
然后点一下齿轮生成代码。
RTC初始化代码,做了一点小改动:
void MX_RTC_Init(void)
{
  LL_RTC_InitTypeDef RTC_InitStruct;
  LL_RTC_TimeTypeDef RTC_TimeStruct;
  LL_RTC_DateTypeDef RTC_DateStruct;
       
        LL_RTC_AlarmTypeDef RTC_AlarmStruct;
  /* Peripheral clock enable */
//  LL_RCC_EnableRTC();
       
//        if(LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR0) != 0x32F2)
//        {

                        /**Initialize RTC and set the Time and Date
                        */
                RTC_InitStruct.HourFormat = LL_RTC_HOURFORMAT_24HOUR;
                RTC_InitStruct.AsynchPrescaler = 127;
                RTC_InitStruct.SynchPrescaler = 255;
                LL_RTC_Init(RTC, &RTC_InitStruct);

                        /**Initialize RTC and set the Time and Date
                        */
               
                RTC_TimeStruct.Hours = 12;
                RTC_TimeStruct.Minutes = 50;
                RTC_TimeStruct.Seconds = 40;
                LL_RTC_TIME_Init(RTC, LL_RTC_FORMAT_BIN, &RTC_TimeStruct);

                RTC_DateStruct.WeekDay = LL_RTC_WEEKDAY_MONDAY;
                RTC_DateStruct.Month = LL_RTC_MONTH_JANUARY;
                RTC_DateStruct.Year = 19;
                LL_RTC_DATE_Init(RTC, LL_RTC_FORMAT_BIN, &RTC_DateStruct);

                 LL_RTC_BAK_SetRegister(RTC,LL_RTC_BKP_DR0,0x32F2);
                 
                if(LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR0) != 0x32F2)
                {
                        LL_RTC_BAK_SetRegister(RTC,LL_RTC_BKP_DR0,0x32F2);
                }
    /**Initialize RTC and set the Time and Date
    */

                if(LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR0) != 0x32F2)
                {
                        LL_RTC_BAK_SetRegister(RTC,LL_RTC_BKP_DR0,0x32F2);
                }
//  }
       
        /* RTC interrupt Init */
        NVIC_SetPriority(RTC_IRQn, 0);
        NVIC_EnableIRQ(RTC_IRQn);
        /* RTC Alarm Interrupt Configuration: EXTI configuration */
  LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_17);
  LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_17);
               
//        RTC_AlarmStruct.AlarmTime.Hours =  12;
        RTC_AlarmStruct.AlarmTime.Minutes =  51;
//        RTC_AlarmStruct.AlarmTime.Seconds =  0;
//        RTC_AlarmStruct.AlarmTime.TimeFormat =  LL_RTC_HOURFORMAT_24HOUR;
//        RTC_AlarmStruct.AlarmDateWeekDay = 1;
//        RTC_AlarmStruct.AlarmDateWeekDaySel = LL_RTC_ALMA_DATEWEEKDAYSEL_DATE;
        RTC_AlarmStruct.AlarmMask = LL_RTC_ALMA_MASK_DATEWEEKDAY|LL_RTC_ALMA_MASK_HOURS|LL_RTC_ALMA_MASK_SECONDS;//LL_RTC_ALMA_MASK_NONE|LL_RTC_ALMA_MASK_MINUTES;
        LL_RTC_ALMA_Init(RTC,LL_RTC_FORMAT_BIN,&RTC_AlarmStruct);
  LL_RTC_DisableWriteProtection(RTC);       
        LL_RTC_ALMA_Enable(RTC);
        LL_RTC_ClearFlag_ALRA(RTC);
        LL_RTC_EnableIT_ALRA(RTC);
        LL_RTC_EnableWriteProtection(RTC);
}
RTC的闹钟中断是内部连接到外部中断控制器的,所以使能了还要记得使能外部中断线路和设置中断方式,手册上写的闹钟中断使用17号且只能配置成上升沿
5.png 6.png

时间走到设置的闹钟时间后就会进入中断了
void RTC_IRQHandler(void)
{
        if(LL_RTC_IsEnabledIT_ALRA(RTC))
        {
                if(LL_RTC_IsActiveFlag_ALRA(RTC))
                {
                          LL_RTC_DisableWriteProtection(RTC);       
                                LL_RTC_ALMA_Disable(RTC);
                                LL_RTC_ClearFlag_ALRA(RTC);
                                LL_RTC_EnableWriteProtection(RTC);       
                          LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_17);
                          rtc_flag = 1;
                }
        }

}

这里需要注意使用库函数操作RTC后一般都会使能写保护寄存器,所以到中断后先取消写保护然后关闭闹钟A并清除闹钟A的中断标志和17号外部中断标志,这里我用了一个 rtc_flag代表进入了闹钟中断,在主程序中检测到这个标志后设置新的闹钟时间(这里关闭闹钟是为了后面重新设置闹钟,因为不关闭闹钟是无法重新设置闹钟的,我之前出错就是没有看数据手册导致闹钟只能第一次进中断)。

在主程序中重新设置新的闹钟:

void RTC_AlarmA_Callback()
{
        LL_RTC_AlarmTypeDef RTC_AlarmStruct;

//        RTC_AlarmStruct.AlarmTime.Hours =  12;
        RTC_AlarmStruct.AlarmTime.Minutes =  52;
//        RTC_AlarmStruct.AlarmTime.Seconds =  0;
//        RTC_AlarmStruct.AlarmTime.TimeFormat =  LL_RTC_HOURFORMAT_24HOUR;
//        RTC_AlarmStruct.AlarmDateWeekDay = 1;
//        RTC_AlarmStruct.AlarmDateWeekDaySel = LL_RTC_ALMA_DATEWEEKDAYSEL_DATE;
        RTC_AlarmStruct.AlarmMask = LL_RTC_ALMA_MASK_DATEWEEKDAY|LL_RTC_ALMA_MASK_HOURS|LL_RTC_ALMA_MASK_SECONDS;//LL_RTC_ALMA_MASK_NONE|LL_RTC_ALMA_MASK_MINUTES;
        LL_RTC_ALMA_Init(RTC,LL_RTC_FORMAT_BIN,&RTC_AlarmStruct);
        LL_RTC_DisableWriteProtection(RTC);       
        LL_RTC_ALMA_Enable(RTC);
        LL_RTC_ClearFlag_ALRA(RTC);
        LL_RTC_EnableWriteProtection(RTC);
}

这里设置了闹钟时间后记得重新使能闹钟A,最后再使能一下写保护,防止意外操作改变RTC里面的数据。只要每次进入中断后读出当前时间并设置新的闹钟时间,就能连续的通过闹钟中断做需要准时做的事情了。

  总结一下,RTC设置时间日期寄存器的时候不是直接设置,而是需要先进入到初始化模式才能设置,设置完成后退出初始化模式开始重新按照设置的时间计时,设置闹钟中断的时候要记得先取消写保护,并且要在闹钟关闭的情况下写入闹钟时间,写入完成后开启闹钟。设置对应的闹钟外部中断线就OK啦。就这样吧,有没写到的下次补充。


STM32L071_LL_RTC.rar

下载

10.75 MB, 下载次数: 336

收藏 评论10 发布时间:2019-1-9 18:11

举报

10个回答
STMCU-管管 回答时间:2019-1-22 13:31:34
谢谢分享
sa090843 回答时间:2019-1-22 16:54:25
感謝分享
五哥1 回答时间:2019-1-23 01:49:55
谢谢,这个又学了些东西
烤猪 回答时间:2019-6-30 13:29:53
感谢
engerHi 回答时间:2019-7-3 16:26:55
谢谢楼主分享!
frank171 回答时间:2019-7-4 09:15:11
很仔细了,谢谢分享
zhouxb 回答时间:2019-7-4 14:58:54
好厉害的样子
sym_cool 回答时间:2019-12-6 20:45:20
大神,我参考了您的代码成功实现了stm32l051的RTC闹钟唤醒待机模式,请问您代码中把LL_RCC_EnableRTC();注释了,这个作用是什么呢
zhenshanmcu 回答时间:2020-3-18 13:30:56
我也看看研究下。
过去痕迹 回答时间:2022-7-29 15:29:30
t同样遇到了问题 不过我是G0系列

所属标签

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