0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

STM32 RTC实时时钟(二)

冬至子 来源:纷纭杂谈 作者:CY_CHEN 2023-07-22 15:43 次阅读

上次实验完成了对实时时钟的基本功能——计时的实验,这次在计时的基础上对RTC的可编程闹钟的功能进行测试。

RTC 单元提供两个可编程闹钟,即闹钟 A 和闹钟 B。

可通过将 RTC_CR 寄存器中的 ALRAE 和 ALRBE 位置 1 来使能可编程闹钟功能。如果日历亚秒、秒、分钟、小时、日期或日分别与闹钟寄存器RTC_ALRMASSR/RTC_ALRMAR 和RTC_ALRMBSSR/RTC_ALRMBR 中编程的值相匹配,则 ALRAF 和 ALRBF 标志会被置为1。可通过 RTC_ALRMAR 和 RTC_ALRMBR 寄存器的 MSKx 位以及 RTC_ALRMASSR 和RTC_ALRMBSSR 寄存器的 MASKSSx 位单独选择各日历字段。可通过 RTC_CR 寄存器中的 ALRAIE 和 ALRBIE 位使能闹钟中断。

闹钟 A 和闹钟 B(如果已通过 RTC_CR 寄存器中的位 OSEL[0:1] 使能)可连接到 RTC_ALARM输出。可通过 RTC_CR 寄存器的 POL 位配置 RTC_ALARM 极性。

要对可编程的闹钟(闹钟 A 或闹钟 B)进行编程或更新,必须执行类似的步骤:

  1. 将 RTC_CR 寄存器中的 ALRAE 或 ALRBE 位清零以禁止闹钟 A 或闹钟 B。
  2. 轮询 RTC_ISR 寄存器中的 ALRAWF 或 ALRBWF 位,直到其中一个置 1,以确保闹钟寄存器可以访问。大约需要 2 个 RTCCLK 时钟周期(由于时钟同步)。
  3. 编程闹钟 A 或闹钟 B 寄存器(RTC_ALRMASSR/RTC_ALRMAR 或 RTC_ALRMBSSR/RTC_ALRMBR)。
  4. 将 RTC_CR 寄存器中的 ALRAE 或 ALRBE 位置 1 以再次使能闹钟 A 或闹钟 B。

注意:约 2 个 RTCCLK 时钟周期(由于时钟同步)后,将执行对 RTC_CR 寄存器的更改。

写程序前先简单了解下闹钟相关的寄存器:

RTC闹钟A寄存器 (RTC_ALRMAR)

图片

位 31 MSK4:闹钟 A 日期掩码 (Alarm A date mask)

0:如果日期/日匹配,则闹钟 A 置 1

1:在闹钟 A 比较中,日期/日无关

位 30 WDSEL:星期几选择 (Week day selection)

0:DU[3:0] 代表日期的个位

1:DU[3:0] 代表星期几。DT[1:0] 为无关位。

位 29:28 DT[1:0]:日期的十位(BCD 格式)

位 27:24 DU[3:0]:日期的个位或日(BCD 格式)

位 23 MSK3:闹钟 A 小时掩码 (Alarm A hours mask)

0:如果小时匹配,则闹钟 A 置 1

1:在闹钟 A 比较中,小时无关

位 22 PM :AM/PM 符号 (AM/PM notation)

0:AM 或 24 小时制

1:PM

位 21:20 HT[1:0]:小时的十位(BCD 格式)

位 19:16 HU[3:0]:小时的个位(BCD 格式)

位 15 MSK2:闹钟 A 分钟掩码 (Alarm A minutes mask)

0:如果分钟匹配,则闹钟 A 置 1

1:在闹钟 A 比较中,分钟无关

位 14:12 MNT[2:0]:分钟的十位(BCD 格式)

位 11:8 MNU[3:0]:分钟的个位(BCD 格式)

位 7 MSK1:闹钟 A 秒掩码 (Alarm A seconds mask)

0:如果秒匹配,则闹钟 A 置 1

1:在闹钟 A 比较中,秒无关

位 6:4 ST[2:0]:秒的十位(BCD 格式)

位 3:0 SU[3:0]:秒的个位(BCD 格式)

闹钟B寄存器RTC_ALRMBR与闹钟A寄存器RTC_ALRMAR的寄存器功能一样,这里不再进行介绍。

RTC闹钟配置函数和中断处理函数

void RTC_AlarmConfig(u8 Alarm_sel,u8 Alarm_set,u8 Alarm_day,u8 Alarm_hour,u8 Alarm_minute)
{
  u32 prigroup = 0;
  u32 priority = 0;
  u32 temp = 0;

  //1.解除保护
  //写密钥:先写0xca,再写0x53
  RTC- >WPR  =  0XCA;
  RTC- >WPR  = 0X53;

  switch(Alarm_set)
  {
    case SPECIAL_DAY:
      temp |= Alarm_day< < 24;  //设置具体星期
      break;

    case WORK_DAY:
    case ALL_DAY:
      temp |= (u32)(1< < 31);
      break;

    case DISABLE_DAY:
      break;
  }

  temp |= 1< < 30;                //用星期来匹配
  temp |= ((Alarm_hour/10)< < 4  |  (Alarm_hour%10))< < 16 | 1< < 23;
  temp |= ((Alarm_minute/10)< < 4  |  (Alarm_minute%10))< < 8 | 1< < 15;
  temp |= 1< < 7;

  //关闭闹钟,等待闹钟可写入
  if(Alarm_sel == ALARM_A)
  {
    RTC- >CR  &= ~(1< < 8);
    while((RTC- >ISR & (1< < 0)) == 0){}
    RTC- >ALRMAR = temp;
    RTC- >CR |= 1< < 8;      //开启闹钟A
    //开闹钟A的中断
    RTC- >CR |= 1< < 12;
    //清中断标记
    RTC- >ISR &= ~(1< < 8);  
  }
  else if(Alarm_sel == ALARM_B)
  {
    RTC- >CR  &= ~(1< < 9);
    while((RTC- >ISR & (1< < 1)) == 0){}
    RTC- >ALRMBR = temp;
    RTC- >CR |= 1< < 9;    //开启闹钟B
    //开闹钟B的中断
    RTC- >CR |= 1< < 13;      
    //清中断标记
    RTC- >ISR &= ~(1< < 9);
  }

  //闹钟中断对应于外部中断线,因此要设置外部中断线(17)
  EXTI- >IMR  |= 1< < 17;
  EXTI- >RTSR  |= 1< < 17;      //闹钟中断需设置为上升沿
  //清中断标记
  EXTI- >PR  |= 1< < 17;

  prigroup = NVIC_GetPriorityGrouping();
  priority = NVIC_EncodePriority(prigroup,1,2);
  NVIC_SetPriority(RTC_Alarm_IRQn,priority);
  NVIC_EnableIRQ(RTC_Alarm_IRQn);

  switch(Alarm_set)
  {
    case SPECIAL_DAY:
      break;

    case WORK_DAY:
      temp = (RTC- >DR  &  0x0000e000) >>13;
      if(temp  >5)
      {
        if(Alarm_sel == ALARM_A)
          RTC- >CR  &= ~(1< < 8);
        else if(Alarm_sel == ALARM_B)
          RTC- >CR  &= ~(1< < 9);
      }
      else
      {
        if(Alarm_sel == ALARM_A)
          RTC- >CR  |= 1< < 8;
        else if(Alarm_sel == ALARM_B)
          RTC- >CR  |= 1< < 9;
      }
      break;

    case ALL_DAY:
      break;

    case DISABLE_DAY:
      if(Alarm_sel == ALARM_A)
          RTC- >CR  &= ~(1< < 8);
      else if(Alarm_sel == ALARM_B)
          RTC- >CR  &= ~(1< < 9);
      break;
  }

  //2. 再次保护
  RTC- >WPR  = 0XFF;          //写任意值,再次保护
}


//中断处理
void RTC_Alarm_IRQHandler()
{
  EXTI- >PR  |= 1< < 17;
  //中断处理
  if(RTC- >ISR & (1< < 8))
  {
    RTC- >ISR  &= ~(1< < 8);
    //闹钟A中断处理
    LED_Toggle(DS1);
  }
  else if(RTC- >ISR & (1< < 9))
  {
    RTC- >ISR  &= ~(1< < 9);
    //闹钟B中断处理
  }
}

由于闹钟的编写比较简单,这里就不多加描述了,接下来编写主函数进行测试。

#include "stm32f4xx.h"
#include "usart.h"
#include "delay.h"
#include "stdio.h"
#include "RTC.h"
#include "led.h"


typedef struct
{
  u8 shi;
  u8 fen;
  u8 miao;
  u8 nian;
  u8 yue;
  u8 ri;
  u8 xingqi;
}TIME_Typedef;
TIME_Typedef time = {1};


int main()
{
  LED_Init();
  Usart1_Init(115200);
  RTC_Init(23,59,50,19,7,9,2);
  RTC_AlarmConfig(ALARM_A,SPECIAL_DAY,3,0,0);

  while(1)
  {
    time.shi    =    ((RTC- >TR  &  0x300000) >>20)*10  +  ((RTC- >TR  &  0xf0000) >>16);
    time.fen    =    ((RTC- >TR  &  0x7000) >>12)*10  +  ((RTC- >TR  &  0xf00) >>8);
    time.miao    =    ((RTC- >TR  &  0x70) >>4)*10  +  (RTC- >TR  &  0xf);


    printf("%d:%d:%drn",time.shi,time.fen,time.miao);

    Delay_ms(1000);
  }
}

初始时间设为23:59:50,闹钟时间设为0:0:0。运行程序,经过10秒钟后,闹钟进入中断,LED灯实现翻转,RTC闹钟实验测试成功。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    30

    文章

    5028

    浏览量

    117719
  • 计时器
    +关注

    关注

    1

    文章

    395

    浏览量

    32156
  • 中断处理
    +关注

    关注

    0

    文章

    92

    浏览量

    10890
  • BCD编码
    +关注

    关注

    0

    文章

    7

    浏览量

    6003
  • RTC
    RTC
    +关注

    关注

    2

    文章

    484

    浏览量

    65438
收藏 人收藏

    评论

    相关推荐

    STM32 RTC实时时钟(一)

    STM32处理器内部集成了实时时钟控制器(RTC),因此在实现实时时钟功能时,无须外扩时钟芯片即可构建
    的头像 发表于 07-22 15:41 2859次阅读
    <b class='flag-5'>STM32</b> <b class='flag-5'>RTC</b><b class='flag-5'>实时时钟</b>(一)

    什么是实时时钟RTC)?如何更改RTC的时间?

    什么是实时时钟RTC)?实时时钟RTC)的基本功能是什么?实时时钟RTC)晶体误差的主要来
    发表于 07-19 08:44

    RTC实时时钟简介

    RTC实时时钟1. RTC实时时钟简介2. 硬件设计3. 软件设计3.1 STM32CubeMX设置3.2 MDK-ARM编程4. 下载验证
    发表于 08-18 06:55

    如何去实现STM32实时时钟RTC的时间计算部分

    STM32实时时钟RTC是什么?STM32实时时钟RTC是由哪些部分组成的?如何去实现
    发表于 11-22 06:33

    如何去使用STM32实时时钟RTC

    实时时钟RTC是什么?如何去使用STM32实时时钟RTC呢?有哪些注意事项?
    发表于 11-22 08:05

    RTC是什么?RTC实时时钟实验

    文章目录前言一、RTC是什么?RTC实时时钟实验1.引入库2.读入数据总结前言前面我们说了OLED实验,是一个比较好的显示测试代码的方法。现在我们学习关于
    发表于 01-13 07:19

    STM32 RTC实时时钟(库函数)

    发表于 02-11 10:59 23次下载

    STM32F2技术培训_实时时钟_RTC

    STM32F2 技术培训_实时时钟_RTC
    发表于 12-03 17:35 0次下载

    STM32F0xx_ RTC实时时钟配置详细过程

    STM32F0xx_RTC实时时钟配置详细过程
    的头像 发表于 04-07 11:50 7835次阅读
    <b class='flag-5'>STM32</b>F0xx_ <b class='flag-5'>RTC</b><b class='flag-5'>实时时钟</b>配置详细过程

    STM32 RTC实时时钟资料下载

    电子发烧友网为你提供STM32 RTC实时时钟资料下载的电子资料下载,更有其他相关的电路图、源代码、课件教程、中文资料、英文资料、参考设计、用户指南、解决方案等资料,希望可以帮助到广大的电子工程师们。
    发表于 04-16 08:48 33次下载
    <b class='flag-5'>STM32</b> <b class='flag-5'>RTC</b><b class='flag-5'>实时时钟</b>资料下载

    浅谈RTC实时时钟特征与原理

    一、RTC实时时钟特征与原理 查看STM32中文手册 16 实时时钟RTC)(308页) RTC
    的头像 发表于 06-30 15:54 1.1w次阅读

    STM32CubeMX | 40 - 实时时钟RTC的使用(日历和闹钟)

    STM32CubeMX | 40 - 实时时钟RTC的使用(日历和闹钟)
    发表于 11-23 18:06 18次下载
    <b class='flag-5'>STM32</b>CubeMX | 40 - <b class='flag-5'>实时时钟</b><b class='flag-5'>RTC</b>的使用(日历和闹钟)

    stm32f4 RTC实时时钟解析

    中应用最为广泛的消费类电子产品之一。它为人们提供精确的实时时间,或者为电子系统提供精确的时间基准,目前实时时钟芯片大多采用精度较高的晶体振荡器作为时钟源。对于STM32F的
    发表于 12-04 18:06 19次下载
    <b class='flag-5'>stm32</b>f4 <b class='flag-5'>RTC</b><b class='flag-5'>实时时钟</b>解析

    STM32CubeMX系列|RTC实时时钟

    RTC实时时钟1. RTC实时时钟简介2. 硬件设计3. 软件设计3.1 STM32CubeMX设置3.2 MDK-ARM编程4. 下载验证
    发表于 12-24 19:15 16次下载
    <b class='flag-5'>STM32</b>CubeMX系列|<b class='flag-5'>RTC</b><b class='flag-5'>实时时钟</b>

    基于STM32单片机RTC实时时钟使用库文件设计

    基于STM32单片机RTC实时时钟使用库文件设计源代码
    发表于 04-26 14:28 2次下载