STM32 RTC实时时钟(二)

发布者:HeavenlyWonder最新更新时间:2024-02-27 来源: elecfans关键字:STM32  RTC  实时时钟 手机看文章 扫描二维码
随时随地手机看文章

上次实验完成了对实时时钟的基本功能——计时的实验,这次在计时的基础上对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)进行编程或更新,必须执行类似的步骤:


将 RTC_CR 寄存器中的 ALRAE 或 ALRBE 位清零以禁止闹钟 A 或闹钟 B。

轮询 RTC_ISR 寄存器中的 ALRAWF 或 ALRBWF 位,直到其中一个置 1,以确保闹钟寄存器可以访问。大约需要 2 个 RTCCLK 时钟周期(由于时钟同步)。

编程闹钟 A 或闹钟 B 寄存器(RTC_ALRMASSR/RTC_ALRMAR 或 RTC_ALRMBSSR/RTC_ALRMBR)。

将 RTC_CR 寄存器中的 ALRAE 或 ALRBE 位置 1 以再次使能闹钟 A 或闹钟 B。

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


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


RTC闹钟A寄存器 (RTC_ALRMAR)

44efa15d4874d6051738d65fe5a8b78f_wKgZomS7iJuAAOKwAAAvX0kDxLA561.jpg

位 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闹钟实验测试成功。


关键字:STM32  RTC  实时时钟 引用地址:STM32 RTC实时时钟(二)

上一篇:基于STM32单片机的电子称设计
下一篇:基于STM32模拟UART串口通信

推荐阅读最新更新时间:2024-11-07 20:53

STM32处理器存储空间布局解析
一、Cortex-M3支持最大4GB的存储空间,其地址映射关系如下图 二、存储器映射实例:256KB Flash 48KB SRAM IROM1为片上程序存储器,即片上集成的Flash存储器,对该处理器Flash大小为256KB,即0x40000 IRAM1为片上数据存储器,即片上集成的SRAM存储器,对该处理器Flash大小为48KB,即0xC000 片上SRAM的起始地址是0x20000000,这是由Cortex-M3内核决定的,从0x20000000开始的512KB存储空间内都可以SAM,即所谓的 大框架 ,但具体的SRAM大小由半导体厂商来决定,因为SRAM成本较高一般容量都不是很大。 代码区的起始地址范
[单片机]
<font color='red'>STM32</font>处理器存储空间布局解析
STM32的ADC的原理与使用
一、ADC的原理及定义 Analog-to-Digital Converter的缩写。中文译名:模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。其实就是一个取样、量化、编码的一个过程。 典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。比如电量、光照传感器等常用。 ---------------------------------------------------------------------------------------------------------------------------------------------------------
[单片机]
<font color='red'>STM32</font>的ADC的原理与使用
STM32 的gpio mode set 详解
最近在看数据手册的时候,发现在Cortex-M3里,对于GPIO的配置种类有8种之多: (1)GPIO_Mode_AIN 模拟输入 (2)GPIO_Mode_IN_FLOATING 浮空输入 (3)GPIO_Mode_IPD 下拉输入 (4)GPIO_Mode_IPU 上拉输入 (5)GPIO_Mode_Out_OD 开漏输出 (6)GPIO_Mode_Out_PP 推挽输出 (7)GPIO_Mode_AF_OD 复用开漏输出 (8)GPIO_Mode_AF_PP 复用推挽输出 对于刚入门的新手,我想这几个概念是必须得搞清楚的,平时接触的最多的也就是推挽输出、开漏输出、上拉输入这三种,但一直未曾对这些做过归纳。因此,在这里做一个总
[单片机]
<font color='red'>STM32</font> 的gpio mode set 详解
STM32 按键EXTI方式 使用ST3.0.0库
把IO配置为 EXTI中断的步骤: 1:使能EXTI Line时钟和第二功能时钟。 2:配置EXTI Line中断优先级(NVIC) 3:配置EXTI Line IO (哪个引脚,输入模式,初始化) 4:把引脚配置为EXTI Line的中断源(GPIO操作),配置IO口的工作模式 5:配置EXTI Line的工作模式。 ============================================================================== 例如: GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStruc
[单片机]
编写STM32项目遇到的报错
1.Undefined symbol SystemInit(未定义符号SystemInit) 新建项目并编译后遇到以下的错误: ..OutputLED.axf: Error: L6218E: Undefined symbol SystemInit (referred from startup_stm32f429_439xx.o). 错误分析:从括号里面的内容可以知道:这个错误在 startup_stm32f0xx.o 这个文件里面被提及到,所以我们只需要在工程里面找到对应的.s或者.c文件即可(此错误对应的文件为startup_stm32f429_439xx.s)。 这个文件是STM32的启动文件,在此文件中可以找
[单片机]
编写<font color='red'>STM32</font>项目遇到的报错
关于stm32跑马灯的程序
stm32的寄存器比较多,难于记忆,所以官方封装了两套库函数。一个是标准库,不过在F7上官方没有更新,以后可能不再维护了。另一个则是HAL库,HAL库的程序可移植性比较高,而且基本上不用和寄存器打交道,不懂硬件的小白也可以轻松学习。 由于用的正点原子的stm32F767,正点原子用的mdk5的方式新建工程,不是特别喜欢。加上现在关于HAL库的中文资料较少,不过原子,野火,硬石,微雪而已。而用Cubemx来开发F7甚至关于stm32移植的更是少之又少。当然折腾也是必不可少的了,我决定用stm32cubeMx + sw4stm32的方式开发,由于技术不熟个别地方可能还是会用到mdk5,还望谅解。 下边就详细讲解下关于stm32
[单片机]
关于<font color='red'>stm32</font>跑马灯的程序
意法半导体的芯片获HTEC穿戴式心脏记录仪采用
横跨多重电子应用领域、全球领先的半导体供应商意法半导体(STMicroelectronics,简称ST;纽约证券交易所代码:STM)拥有性能强大的STM32微控制器,可保证HTEC穿戴式心电图记录仪(ECG recorder, electrocardiogram recorder)能够长时间持续运行,远程监测心脏健康状况。 全球有数百万名不同年龄段的患者受到心律不齐或心跳异常等不同类型心脏疾病的困扰。通过及时准确的诊断,多数心律失常症状均能够被有效治疗,并能将死亡率降至最低。标准Holter动态心律监视器必须在记录后第二天早晨交给医生,以检查病患过去24小时的心率状况,而基于STM32的3导(3-lead)心电图记录
[医疗电子]
STM32红牛开发板非固件库控制LED
摘要 STM32红牛开发板上的5个LED,接在GPIOF6~10脚,输出低电平时,LED亮。这样我们设置GPIOF的相关寄存器,让其输出低电平就可以让LED亮。因为没有用到ST提供的固件库,所以是直接对寄存器的内存地址读写,即对一个指向该地址的指针变量进行读写。并且该变量必须为易变型的,即用volatile定义,这样是为了告诉编译器不要去优化这个变量,导致其它一些寄存器的数据变化。GPIOx是挂载在APB2高速外设总线上的,最大频率是72MHZ,所以我们除了了打开HSE(外部高速时钟)并关闭内部高速时钟(开机默认选择了HSI)外,还要打开APB2总线的时钟。 一、寄存器地址映射 外设的基址PERI
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved