那么为什么我们需要一个单独的RTC?
原因是CPU的定时器时钟功能只在“通电时”运行,断电时停止。当然,如果时钟不能连续跟踪时间,则必须手动设置时间。如今,通过接收标准电波(传输各国标准时间的电波)来自动调整时间的手表越来越多,但它是一种不应该在室内携带的电子设备。RTC有一个与CPU单独分离的电源,如纽扣电池(备用电池),即使主机电源关闭,它也保持滴答作响,随时可以实时显示时间。然后,当计算机再次打开时,计算机内置的定时器时钟从RTC读取当前时间,并在此基础上供电的同时,时间在其自身机制下显示。同时RTC单元外接32.768 kHZ晶振,具有定时报警功能。实时时钟的缩写是RTC(Real_Time Clock)。RTC 是集成电路,通常称为时钟芯片。
一、工作原理:
RTC模块的核心是时钟源,它通常是一个高精度的晶体振荡器(晶振)。晶振通过产生稳定的振荡频率(如32.768kHz)为RTC模块提供时间基准。这个频率通过分频器被降低到一个较低的频率(如1Hz),以便为计数器提供时钟信号。RTC模块中的计数器用于跟踪时间。它通常是一个32位的计数器,以固定的时间间隔(如1秒)递增。当计数器溢出时,会产生一个中断或触发其他事件(如闹钟功能)。计数器的值可以通过软件进行读取和修改,以实现时间的设置和校准
二、工作过程:
1、SNVS_HP (high power domain)
SNVS_HP is partitioned into the following functional units(SNVS_HP分为以下功能单元):
- IP bus interface(IP总线接口)
- SNVS_LP interface(SNVS_LP接口)
- Real time counter with alarm (带报警功能的实时计数器)
- Control and status registers(控制和状态寄存器)
2、SNVS_LP (low power domain)
- SNVS_LP has the following functional units(SNVS_LP有以下功能能单位):
- Non-rollover monotonic counter (非翻转单调计数器)
- General purpose register(通用寄存器)
- Control and status registers(控制和状态寄存器)
The SNVS_HP section implements all features that enable system communication and provisioning
of the SNVS_LP section.
SNVS_HP部分实现了启用系统通信和SNVS_LP部分配置的所有功能
The SNVS_LP section provides hardware that enables secure storage and protection of sensitive
data.
SNVS_LP部分提供安全存储和保护敏感数据的硬件。
三、相关寄存器:
1、SNVS_HP Command register (SNVS_HPCOMR)
当设置时,它允许非特权软件访问所有SNVS寄存器
2、SNVS_HP/SNVS_LP Control Register(SNVS_HPCR/SNVS_LPCR)
rtc使能和rtc中断使能
3、SNVS_HP/SNVS_LP Status register(SNVS_HPSR/SNVS_LPSR)
中断状态清理位(设1清零)
4、SNVS_HP/SNVS_LP Real Time Counter MSB Register(HPRTCMR/LPSRTCMR)
整个计数器32bit, 这个寄存器[14:0]位存放的是计数器的高15位值
5、SNVS_HP/SNVS Real-Time Counter LSB Register(SNVS_HPRTCLR/SNVS_LPSRTCLR)
整个计数器32bit, 这个寄存器[31:15]位存放的是计数器的低17位值
4、5、两个寄存器主要是将获取到的数据进行储存(自己设定的时间)
6、SNVS_HP Time Alarm MSB Register (SNVS_HPTAMR)
整个计数器32bit, 这个寄存器[14:0]位存放的是计数器的高15位值
7、SNVS_HP Time Alarm LSB Register (SNVS_HPTALR)
整个计数器32bit, 这个寄存器[31:15]位存放的是计数器的低17位值
6、7、主要是中断时间数据储存寄存器
四、代码说明
1、使用时钟显示时间
具体思路:
2、使用时钟和中断进行
具体思路:
rtc_alarm.h
#ifndef __RTC__HEAD__
#define __RTC__HEAD__
#include <stdio.h>
#include <stdint.h>
#include "rtc_datetime.h"
#include "../uart/uart.h"
#include "../gpt/gpt.h"
#include "../interrupt/interrupt.h"
#include "../buzzer/buzzer.h"
extern void rtc_alarm_test();
#endif // !__RTC__HEAD__
rtc_alarm.c
#include "rtc_alarm.h"
// 控制
int rtc_alarm_handle(int irq_num)
{
uart_printf("alarm irq number:%d\r\n", irq_num);
if (SNVS->HPCR & (0x1 << 0))
{
// 让蜂鸣器响一秒
buzzer_text_one_second();
// 清理中断
SNVS->HPCR | (0x1 << 0); // 放1然后清理
while (SNVS->HPCR & (0x1 << 0))
{
}
}
}
// 使能
void rtc_alarm_enable()
{
SNVS->HPCR &= ~(0x1 << 1);
SNVS->HPCR |= (0x1 << 1);
// 循环判断是否成功
while (!(SNVS->HPCR & (0x1 << 1)))
{
}
}
// 不使能
void rtc_alarm_disable()
{
SNVS->HPCR &= ~(0x1 << 1);
while (SNVS->HPCR & (0x1 << 1))
{
}
}
// 设置alarm日期
void set_rtc_alarm_datetime(const rtc_datetime_t *datetime)
{
rtc_alarm_disable();
// 设置时间
// rtc_datetime_t datetime = {year : 2014, month : 12, day : 4, hour : 20, minute : 30, second : 22}; // 结构体放置具体时间
uint_fast32_t seconds = convert_datetime_to_seconds(datetime); // 转换为晶振时间到时候会显示出来
// 设置高15位和低17位f放置于两个不同的寄存器中
SNVS->HPTAMR = seconds >> 17;
SNVS->HPTALR = seconds << 15;
rtc_alarm_enable();
}
// 进行测试
void rtc_alarm_test()
{
// 初始化
rtc_init();
// 设置时间
rtc_datetime_t datetime = {year : 2024, month : 12, day : 5, hour : 16, minute : 15, second : 0};
set_rtc_datetime(&datetime);
// 设置alarm的时间
rtc_datetime_t alarmdatetime = {year : 2024, month : 12, day : 5, hour : 16, minute : 15, second : 22};
set_rtc_alarm_datetime(&alarmdatetime);
// 注册中断
request_irq(SNVS_Consolidated_IRQn, rtc_alarm_handle);
// 使能
enable_irq();
while (1)
{
get_rtc_datetime(&datetime);
uart_printf("%d-%d-%d-%d : %d : %d\r\n ", datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second);
sgpt_deplay(1); // 延迟1秒
}
}
- 这是本人的学习笔记不是获利的工具,小作者会一直写下去,希望大家能多多监督我
- 文章会每攒够两篇进行更新发布(受平台原因,也是希望能让更多的人看见)
- 感谢各位的阅读希望我的文章会对诸君有所帮助