ARM32开发--RTC内置实时时钟

知不足而奋进 望远山而前行


目录

系列文章目录

文章目录

前言

学习目标

学习内容

RTC时钟介绍

RTC结构框图

RTC原理图

RTC时钟电源

RTC的配置流程

RTC时钟

开发流程

RTC初始化

时钟配置

时钟获取

BCD格式转化

完整代码

RTC时钟备份寄存器

总结


前言

在嵌入式系统开发中,实时时钟(RTC)是至关重要的组件,它提供了准确的日期和时间信息,为各种应用场景提供了时间基准。本文将深入探讨RTC的设计原理和初始化过程,帮助您理解RTC在GD32F407上的实现方式以及如何进行初始化、配置和读取时间等操作。


学习目标

  1. 理解原理图RTC设计部分
  2. 掌握初始化RTC
  3. 掌握设置时间
  4. 掌握读取时间

学习内容

RTC时钟介绍

RTC是实时时钟(Real-Time Clock)的缩写。它是一种硬件模块或芯片,用于提供准确的日期和时间信息。

GD32F407上有RTC的外设,它提供了一个包含日期(年/月/日)和时间(时/分/秒/亚秒)的日历功能。除亚秒用二进制码显示外,时间和日期都以BCD码的形式显示。

RTC本质上就是一个1秒计数器,通过秒来换算出时间。因此需要我们提供一个1HZ频率的时钟。

RTC结构框图

RTC原理图

RTC时钟电源

RTC时钟分为两个电源域。RTC的核心部分位于备份域中。系统复位或从待机模式唤醒时,RTC的设置和时间都保持不变。另一部分包括APB接口及一组控制寄存器位于VDD电源域中。

RTC的配置流程

RTC时钟

开发流程
  1. 加载依赖。gd32f4xx_rtc.c,gd32f4xx_pmu.c
  2. 初始化RTC。
  3. 时钟配置。
  4. 获取时钟。
RTC初始化
// 电池管理加载
rcu_periph_clock_enable(RCU_PMU);
pmu_backup_write_enable();

// 重置备份域(不重置可能导致无法设置晶振,出现不走字情况)
/* reset backup domain */
rcu_bkp_reset_enable();
rcu_bkp_reset_disable();

// 2. 设置时钟的晶振 LXTAL (低速外部时钟, 需焊接)
// rcu_osci_on(RCU_LXTAL);
// rcu_osci_stab_wait(RCU_LXTAL);
// rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);

// 2. 设置时钟的晶振 IRC32K
// rcu_osci_on(RCU_IRC32K);
// // 等待晶振稳定
// rcu_osci_stab_wait(RCU_IRC32K);
// /* 给rtc配置晶振 configure the RTC clock source selection */
// rcu_rtc_clock_config(RCU_RTCSRC_IRC32K);

// 2. 设置时钟的晶振 HXTAL -> 8M
 rcu_osci_on(RCU_HXTAL);
 // 等待晶振稳定
 rcu_osci_stab_wait(RCU_HXTAL);
 /* 给rtc配置晶振 configure the RTC clock source selection */
 rcu_rtc_clock_config(RCU_RTCSRC_HXTAL_DIV_RTCDIV);
 // 分频系数(HXTAL时,需要配置) // DIV25 -> 320K
 rcu_rtc_div_config(RCU_RTC_HXTAL_DIV25); 

// RTC功能加载
rcu_periph_clock_enable(RCU_RTC);
rtc_register_sync_wait();
  • RTC电源供应为外部独立电路,需要加载电源管理,打开rtc电源供应。
  • 重置备份域,不重置可能导致无法设置晶振,出现时钟不走字情况。
  • RTC的时钟晶振为外部,需要加载外部晶振。
  • 加载完成过程,需要等待同步。

时钟配置
rtc_parameter_struct rps;
rps.year = 0x23;
rps.month = 0x04;
rps.date = 0x20;
rps.day_of_week = 0x04;
rps.hour = 0x23;
rps.minute = 0x59;
rps.second = 0x55;
rps.display_format = RTC_24HOUR;
rps.am_pm = RTC_AM;
// 配置异步和同步分频器数值 LXTAL
// rps.factor_asyn = 0x7F;
// rps.factor_syn = 0xFF;

  // 配置异步和同步分频器数值IRC32K
//  rps.factor_asyn = 0x7F;   // 7位异步预分频器, 0x0 - 0x7F
//  rps.factor_syn  = 0xF9;   // 15位同步预分频器。0x0 - 0x7FFF

// IRC32K ck_spre = 1 -> 1秒 -> 1个时钟 (1Hz)
// ck_spre = rtc_clk / ((FACTOR_A + 1)*( FACTOR_S + 1))
// 1 = 32K / ((0x7F + 1)*( FACTOR_S + 1))
// FACTOR_S = 32K / 0x80 - 1 = 32K / 128 - 1 = 249

// 配置异步和同步分频器数值HXTAL_DIV25
rps.factor_asyn = 127;   // 7位异步预分频器, 0x0 - 0x7F
rps.factor_syn  = 2499;   // 15位同步预分频器。0x0 - 0x7FFF

// HXTAL_DIV25 -> 8M/25 -> 320K
// ck_spre = 1 -> 1秒 -> 1个时钟 (1Hz)
// ck_spre = rtc_clk / ((FACTOR_A + 1)*( FACTOR_S + 1))
// 1 = 320K / ((0x7F + 1)*( FACTOR_S + 1))
// FACTOR_S = 320K / 0x80 - 1 = 32K / 128 - 1 = 2499

rtc_init(&rps);

1 = rtc_clk/(asyn + 1)/(syn + 1)

  • asyn取值范围为0到0x7F
  • syn取值范围为0到0x07FF
时钟获取
rtc_parameter_struct rps;
rtc_current_time_get(&rps);

uint16_t year = READ_BCD(rps.year) + 2000;
uint8_t month = READ_BCD(rps.month);
uint8_t date = READ_BCD(rps.date);
uint8_t week = READ_BCD(rps.day_of_week);
uint8_t hour = READ_BCD(rps.hour);
uint8_t minute = READ_BCD(rps.minute);
uint8_t second = READ_BCD(rps.second);

printf("%d-%d-%d %d %d:%d:%d\r\n", year, month, date, week, hour, minute, second);
BCD格式转化

BCD(Binary-Coded Decimal,二进制编码十进制)是一种用于表示十进制数字的二进制编码形式。在RTC(实时时钟)等应用中,BCD格式常用于存储和显示日期和时间信息。它的主要特点是每个十进制数位都被编码成4位二进制数。

在BCD格式中,一个十进制数的每一位被表示为4位二进制数,其中每个二进制数位都对应一个十进制数位。例如:

  • 十进制数 0 用BCD表示为 0000。
  • 十进制数 1 用BCD表示为 0001。
  • 十进制数 9 用BCD表示为 1001。

这样,一个BCD字节(8位)可以表示两个十进制数字。

// 十位取出左移4位 + 个位 (得到BCD数)
#define WRITE_BCD(val) 	((val / 10) << 4) + (val % 10)
// 将高4位乘以10 + 低四位 (得到10进制数)
#define READ_BCD(val) 	(val >> 4) * 10 + (val & 0x0F)
完整代码
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "Usart.h"

// 十位取出左移4位 + 个位 (得到BCD数)
#define WRITE_BCD(val) 	((val / 10) << 4) + (val % 10)
// 将高4位乘以10 + 低四位 (得到10进制数)
#define READ_BCD(val) 	(val >> 4) * 10 + (val & 0x0F)

void Usart0_recv(uint8_t *data, uint32_t len) {
    printf("%s\r\n", data);
}

static void RTC_config() {
    // 电池管理加载
    rcu_periph_clock_enable(RCU_PMU);
    pmu_backup_write_enable();
    
    // 重置备份域(不重置可能导致无法设置晶振,出现不走字情况)
    /* reset backup domain */
    rcu_bkp_reset_enable();
    rcu_bkp_reset_disable();
    
    // 晶振加载
    rcu_osci_on(RCU_LXTAL);
    rcu_osci_stab_wait(RCU_LXTAL);
    rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);
    // RTC功能加载
    rcu_periph_clock_enable(RCU_RTC);
    rtc_register_sync_wait();

    rtc_parameter_struct rps;
    rps.year = WRITE_BCD(23);
    rps.month = WRITE_BCD(4);
    rps.date = WRITE_BCD(20);
    rps.day_of_week = WRITE_BCD(4);
    rps.hour = WRITE_BCD(23);
    rps.minute = WRITE_BCD(59);
    rps.second = WRITE_BCD(55);
    rps.display_format = RTC_24HOUR;
    rps.am_pm = RTC_AM;
    rps.factor_asyn = 0x7F;
    rps.factor_syn = 0xFF;

    rtc_init(&rps);
}

static void RTC_read() {
    rtc_parameter_struct rps;
    rtc_current_time_get(&rps);

    uint16_t year = READ_BCD(rps.year) + 2000;
    uint8_t month = READ_BCD(rps.month);
    uint8_t date = READ_BCD(rps.date);
    uint8_t week = READ_BCD(rps.day_of_week);
    uint8_t hour = READ_BCD(rps.hour);
    uint8_t minute = READ_BCD(rps.minute);
    uint8_t second = READ_BCD(rps.second);

    printf("%d-%d-%d %d %d:%d:%d\r\n", year, month, date, week, hour, minute, second);
}

int main(void)
{
    nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
    systick_config();
    Usart0_init();

    RTC_config();

    while(1) {
        RTC_read();

        delay_1ms(1000);
    }
}

RTC时钟备份寄存器

RTC时钟有20个32位(共80字节)通用备份寄存器,能够在省电模式下保存数据。通过备份寄存器可以实现只配置一次时间即可。

注意:如果在尝试向RTC_BKP0写入数据之前或之后调用了rcu_bkp_reset_enable(),那么这确实会导致写入的数据在系统复位后丢失,因为RTC备份寄存器会被复位重置。因此,要确保在向RTC备份寄存器写入数据并期望这些数据在复位后仍然有效时,不能调用rcu_bkp_reset_enable()。

if( RTC_BKP0 == 0xf234 ){	
	//说明不是第一次初始化,可以不用重新设置时间
}else{//如果后备寄存器0 的值 不为 0XF234
    //设置后备寄存器0的值为 0XF234,标记已经初始化过RTC
    RTC_BKP0 = 0xf234;
    //初始化RTC时间
    RtcTimeConfig(0x23,0x07,0x12,0x03,0x12,0x59,0x50);
}

总结

  1. 理解了RTC的基本原理,包括其在实时时钟设计中的作用和结构。
  2. 掌握了初始化RTC的步骤,包括加载依赖、配置时钟源和初始化RTC等。
  3. 理解了设置时间的方法,包括配置时钟参数和异步同步分频器的数值等。
  4. 掌握了读取时间的操作,包括BCD格式转换和从RTC中获取日期和时间信息。
  • 20
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: STM32F030C8T6是意法半导体推出的一款低功耗、高性能的32位微控制器芯片,它内置RTC实时时钟)模块,可实现钟表、定时、闹钟等功能。 下面以ST官方提供的RTC示例为例,简单介绍一下该芯片的RTC实现方法。 首先,在工程中需要包含以下头文件: #include "stm32f0xx.h" #include "stm32f0xx_rcc.h" #include "stm32f0xx_rtc.h" 然后需要初始化RTC时钟,以及配置RTC的时钟源、时钟分频器等参数: RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); PWR_BackupAccessCmd(ENABLE); RCC_LSEConfig(RCC_LSE_ON); //使能外部低速震荡器 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET); //等待低速震荡器启动 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //将RTC时钟源设置为低速震荡器 RCC_RTCCLKCmd(ENABLE); //使能RTC时钟 RTC_WaitForSynchro(); //等待RTC计数器同步 接下来就可以对RTC模块进行配置,像设定当前时间、闹钟、定时器、周期性间隔中断等等: RTC_InitTypeDef RTC_InitStructure; RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24; RTC_InitStructure.RTC_AsynchPrediv = 0x7F; RTC_InitStructure.RTC_SynchPrediv = 0xFF; RTC_Init(&RTC_InitStructure); RTC_SetTime(RTC_Format_BIN, &RTC_TimeType); RTC_SetAlarm(RTC_Format_BIN,RTC_AlarmTime); RTC_GetTime(RTC_Format_BIN,&RTC_TimeType); RTC_SetWakeUpClock(RTC_WakeUpClock_CK_SPRE_16bits); RTC_WakeUpCmd(ENABLE); 可以看到,使用STM32F030C8T6的RTC模块实现时钟、定时、闹钟等功能非常简单,而且能够在低功耗状态下工作,非常适合用于一些需要长时间运行并需要精确时钟的场合。 ### 回答2: STM32F030C8T6是一款低功耗、高性能的ARM Cortex-M0单片机,它内置实时时钟RTC)模块,可以实现精确的时间计数和日期计算功能。 为了更好地了解STM32F030C8T6的RTC模块,STMicroelectronics为其提供了RTC示例代码。这个示例包括初始化RTC模块、设置时间和日期、读取时间和日期以及设置闹钟等功能,可以帮助开发者快速上手使用RTC模块。 在示例代码中,开发者需要首先初始化RTC模块并设置时间、日期和闹钟。随后,可以通过调用相应的API来获取当前时间和日期,或者设置闹钟触发时间。在RTC的工作过程中,可以通过轮询或者中断方式来检测闹钟的触发,从而完成相应的任务。 除了基本的时间和日期计算功能,示例代码还提供了其他实用的功能,比如可以设置备份寄存器、设置时间戳、以及支持闹钟和唤醒功能等等。这些功能能够充分发挥RTC模块的实用性,使其在物联网、智能家居和嵌入式系统等领域得到广泛应用。 综上所述,STM32F030C8T6 RTC示例代码是一份非常实用的参考资料,可以帮助开发者快速学习和掌握STM32F030C8T6 RTC模块的使用方法,为物联网、智能家居和嵌入式系统等领域的应用开发提供强有力的支持。 ### 回答3: stm32f030c8t6是STM32系列单片机之一,它具有实时时钟RTC)模块,可以用来记录时间,具有较高的准确度和稳定性。下面我们以RTC示例为例,来介绍STM32F030C8T6的RTC模块使用方法。 首先,我们需要在代码中初始化RTC模块。使用STM32CubeMX软件,我们可以配置RTC的时钟源和时钟分频器,可以选择外部晶振或内部RC振荡器作为时钟源。然后,我们需要在代码中启用RTC时钟和备份寄存器,并设置RTC的时间和日期。在开发的过程中,可以根据需要修改时间和日期。 其次,我们可以利用RTC模块实现定时操作,例如定时唤醒系统、定时采集数据等。RTC提供了设置和清除闹钟功能,可以在特定时间点触发外部中断。我们可以在RTC中设置闹钟,然后中断处理函数中实现需要执行的操作。 最后,RTC还可以用于实现唤醒系统的低功耗模式。在设置低功耗模式时,我们需要将系统进入待机模式,RTC时钟作为唤醒源,在一定条件下唤醒系统。实现低功耗模式可以大大降低系统功耗,延长系统电池寿命。 总的来说,STM32F030C8T6的RTC模块是非常实用的功能模块,可以方便地记录时间、实现定时操作和低功耗模式,可以适用于很多实际应用场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛慕昭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值