五.STM32F030C8T6 MCU开发之RTC模块基础例程

news2024/12/26 9:19:08

五.STM32F030C8T6 MCU开发之RTC模块基础例程

文章目录

  • 五.STM32F030C8T6 MCU开发之RTC模块基础例程
    • 0.总体功能概述
    • 1.RTC硬件介绍
      • 1.1日历的功能
      • 1.2 闹钟输出
      • 1.3 入侵检测
      • 1.4 时间戳事件检测
    • 2.RTC软件配置
      • 2.1.RTC 模块初始化配置
      • 2.2 RTC 开始时间配置
        • 2.2.1RTC 年月日 时分秒配置
      • 2.3 RTC时间获取
    • 3.RTC 验证例程
    • 4.总结
      • 4.1RTC模块只是用于时间计算可以不需要开中断。
      • 4.2 rtc只初始化一次即可?

0.总体功能概述

使用STD库–en.stm32f0_stdperiph_lib_v1.6.0。

如果需要年月日时分秒的时间记录,之前开发51单片机上面外挂一个类似DS1302的时钟芯片,再加上时间芯片的外围电路。但现在MCU不再需要这么干了。因为在STM32的内部就已经集成了年月日时分秒的时钟电路–也就是实时时钟(RTC)。

本例程将RTC时间调整为当前时间,并特定格式从串口输出,每1s输出一次;

1.RTC硬件介绍

RTC (Real Time Clock):实时时钟
实时时钟是一个独立的定时器。RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。
RTC模块和时钟配置系统(RCC_BDCR寄存器)处于后备区域,即在系统复位或从待机模式唤醒后, RTC的设置和时间维持不变。
在这里插入图片描述

系统复位后,对后备寄存器和RTC的访问被禁止,这是为了防止对后备区域(BKP)的意外写操作。执行以下操作将使能对后备寄存器和RTC的访问:
● 设置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备接口时钟
● 设置寄存器PWR_CR的DBP位,使能对后备寄存器和RTC的访问。

在这里插入图片描述

实时时钟(RTC)是一个独立的定时器。

1.1日历的功能

STM32 的 RTC 模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。

1.2 闹钟输出

当 RTC 运行的时间跟预设的闹钟时间相同的时候,相应的标志位 ALRAF(在 RTC_ISR 寄存器中)和 ALRBF 会置 1。可以作为备忘提醒功能。
如果使能了闹钟输出(由 RTC_CR 的 OSEL[0:1]位控制),则 ALRAF 和 ALRBF 会连接到闹钟输出引RTC_ALARM.

RTC_ALARM 最终连接到 RTC 的外部引脚 RTC_AF1(即 PC13),输出的极性由 RTC_CR 寄存器的 POL 位配置,可以是高电平或者低电平。

1.3 入侵检测

RTC 自带两个入侵检测引脚RTC_TAMP1 的RTC_AF1(PC13)和 RTC__TAMP2的RTC_AF2(PA0)。这两个输入既可配置为边沿检测,也可配置为带过滤的电平检测。当检测到外部事件时,可复位备份寄存器,共80个字节,可用于记录用户数据。备份寄存器不会在系统复位或电源复位时复位,也不会在器件从待机模式唤醒时复位。

1.4 时间戳事件检测

为了记录外部紧急事件触发的时间。时间戳复用功能 (RTC_TS) 可映射到 RTC_AF1 或 RTC_AF2,当发生外部的入侵事件时,即发生时间戳事件时, RTC_ISR 寄存器中的时间戳标志位 (TSF) 将置 1,日历会保存到时间戳寄存器( RTC_TSSSR、RTC_TSTR 和RTC_TSDR)中。

2.RTC软件配置

配置当前时间:时间可以采取24小时格式,也可以采用12小时格式,默认采用24小时格式。

配置时间时,还会设置日期格式,是采用BCD或者二进制。

建议采用二进制即可,可以直接填入时间数值。

第一,定义一个时间的起点,比如2000年1月1日,0点0分0秒。这里要多说一句,其实这个起点可以随便定义,0也没关系。但网络上通常的做法是1970年的1月1日,至于为什么,可以了解时间戳的概念。

第二,STM32并没有专门的记录分钟、小时、日、月、年的寄存器,换句话说,他只是记录了从时间起点(计数器的初值)到当前时间的总秒数,并且能在掉电情况下持续计数运行。要想得到年、月、日信息,是需要我们自己写函数实现的。这里总感觉STM32干得有猛,很粗鲁的样子,上电的时候直接给年、月、日的变量赋值,想要哪年哪月哪日,就直接赋值,然后在这个基础上累加时间,并不断更新,这样就确定了年、月、日的信息。

但别忘了,这是在CPU上电程序运行的情况下进行的,一旦CPU掉电,程序也不再运行,年、月、日信息就不再更新。此时在工作的,只有那个32位的秒计数器。

第三,要想再次上电后正确显示年、月、日等信息,就需要上电后重新调用自己写的这个函数,根据初始化时的年、月、日初值和计数器的当前值,输出当前时间信息。

RTC一般有单独的外部电池供电。

2.1.RTC 模块初始化配置

可以选择以下三种RTC的时钟源:
— HSE时钟除以128;
— LSE振荡器时钟;
— LSI振荡器时钟(详见6.2.8节RTC时钟)。

RTC_CLOCK_SOURCE_LSE 使用外部 32.768 时钟源

RTC_CLOCK_SOURCE_LSI 使用内部RC 32.768 时钟源

	/**
  * @brief  Configure the RTC peripheral by selecting the clock source.
  * @param  None
  * @retval None
  */
static void RTC_Config(void)
{
  /* Enable the PWR clock */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

  /* Allow access to RTC */
  PWR_BackupAccessCmd(ENABLE);
    
#if defined (RTC_CLOCK_SOURCE_LSI)  /* LSI used as RTC source clock*/
/* The RTC Clock may varies due to LSI frequency dispersion. */   
  /* Enable the LSI OSC */ 
  RCC_LSICmd(ENABLE);

  /* Wait till LSI is ready */  
  while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
  {
  }

  /* Select the RTC Clock Source */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
  
  SynchPrediv = 0x18F;
  AsynchPrediv = 0x63;

#elif defined (RTC_CLOCK_SOURCE_LSE) /* LSE used as RTC source clock */
  /* Enable the LSE OSC */
  RCC_LSEConfig(RCC_LSE_ON);

  /* Wait till LSE is ready */  
  while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
  {
  }

  /* Select the RTC Clock Source */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
  
  SynchPrediv = 0xFF;
  AsynchPrediv = 0x7F;

#else
  #error Please select the RTC Clock source inside the main.c file
#endif /* RTC_CLOCK_SOURCE_LSI */
  
  /* Enable the RTC Clock */
  RCC_RTCCLKCmd(ENABLE);

  /* Wait for RTC APB registers synchronisation */
  RTC_WaitForSynchro();
}

2.2 RTC 开始时间配置

    /* Configure the RTC data register and RTC prescaler */
    RTC_InitStructure.RTC_AsynchPrediv = AsynchPrediv;
    RTC_InitStructure.RTC_SynchPrediv = SynchPrediv;
    RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
   printf("rtc init\r\n");
    /* Check on RTC init */
    if (RTC_Init(&RTC_InitStructure) == ERROR)
    {
    }
	printf("rtc RTC_TimeRegulate\r\n");
    RTC_TimeRegulate(); 

2.2.1RTC 年月日 时分秒配置

static void RTC_TimeRegulate(void)
{
  RTC_TimeTypeDef RTC_TimeStructure;
  RTC_DateTypeDef RTC_DateStructure;
  
  /* Set Time hh:mm:ss */
  RTC_TimeStructure.RTC_H12     = RTC_H12_AM;
  RTC_TimeStructure.RTC_Hours   = 0x08;  
  RTC_TimeStructure.RTC_Minutes = 0x10;
  RTC_TimeStructure.RTC_Seconds = 0x00;
  RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure);

  /* Set Date Week/Date/Month/Year */
  RTC_DateStructure.RTC_WeekDay = 01;
  RTC_DateStructure.RTC_Date = 0x31;
  RTC_DateStructure.RTC_Month = 0x12;
  RTC_DateStructure.RTC_Year = 0x12;
  RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure);
  
  /* Write BkUp DR0 */
  RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2);
}

2.3 RTC时间获取

void RTC_TimeShow(void)
{

  /* Get the current Time */
	RTC_GetTime(RTC_Format_BIN, &aShowTime);
	RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure);

}

3.RTC 验证例程

每隔1秒获取RTC时间,查看RTC时间实际变化

int rtc_main(void)
{

    unsigned int s_time = 0;
    unsigned int e_time = 0;
    RTC_Config();

    /* Configure the RTC data register and RTC prescaler */
    RTC_InitStructure.RTC_AsynchPrediv = AsynchPrediv;
    RTC_InitStructure.RTC_SynchPrediv = SynchPrediv;
    RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
   printf("rtc init\r\n");
    /* Check on RTC init */
    if (RTC_Init(&RTC_InitStructure) == ERROR)
    {
    }
	printf("rtc RTC_TimeRegulate\r\n");
    RTC_TimeRegulate(); 

	printf("rtc start\r\n");
  while(1)
  {	   
   
		s_time = get_curtime();
		while(1)
		{
			e_time = get_curtime();	
			if(e_time>s_time )
			{
				if((e_time - s_time) >=1000)
				{
					break;
				}
			}
		}
	printf("RTC_TimeShow\r\n");
    RTC_TimeShow();
		printf("RTC_Hours=%d:%d:%d\r\n",aShowTime.RTC_Hours,aShowTime.RTC_Minutes,aShowTime.RTC_Seconds);
		printf("y m d=%d %d %d\r\n",RTC_DateStructure.RTC_Year,RTC_DateStructure.RTC_Month,RTC_DateStructure.RTC_Date);
  }		
}

4.总结

4.1RTC模块只是用于时间计算可以不需要开中断。

如果需要用alarm功能 才需要开.

4.2 rtc只初始化一次即可?

每次上电后会读取BKP_DR1的值,判断是否为第一次启动,如果是,则配置RTC。换句话说,出现问题时,这个判断肯定出现问题,也就是备份寄存器的值丢失,导致重复配置RTC!

备份寄存器的值丢失原因:

1》 VDD和VBAT同时掉电

2》 客户代码意外修改

3》 检测到入侵事件

;
}
}


## 4.总结

### 4.1RTC模块只是用于时间计算可以不需要开中断。

如果需要用alarm功能 才需要开.

### 4.2 rtc只初始化一次即可?

每次上电后会读取BKP_DR1的值,判断是否为第一次启动,如果是,则配置RTC。换句话说,出现问题时,这个判断肯定出现问题,也就是备份寄存器的值丢失,导致重复配置RTC!

备份寄存器的值丢失原因:

1》 VDD和VBAT同时掉电

2》 客户代码意外修改

3》 检测到入侵事件

首先怀疑是VBAT引脚。要是VBAT再现异常,RTC重新配置就很正常。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/20992.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

_linux 进程间通信(管道)

文章目录1. 进程间通信目的2. 进程间通信发展3. 进程间通信分类4. 管道1. 进程间通信目的 数据传输:一个进程需要将它的数据发送给另一个进程资源共享:多个进程之间共享同样的资源。通知事件:一个进程需要向另一个或一组进程发送消息&#x…

【English】十大词性之介词

介词 文章目录介词前言一、方位介词1.1 某地1.2 里里外外1.3 上上下下1.4 前前后后1.5 ....中间1.6 ...穿越1.7 ...树上1.8 在...墙上1.9 旁边(距离远近区分)二、时间介词三、方式介词四、易混淆介词4.1 制成4.2 交通工具4.3 除了总结前言 介词是表示名词、代词与句子中其它词…

02Java线程模型

1. 操作系统线程 无论使用何种编程语言编写多线程程序,最终都是通过调用操作系统的线程来执行任务。线程是CPU调度的最小执行单元。 线程有多种实现方式,常见的有:内核线程、用户线程、混合线程。 不同线程模型的主要区别在于线程的调度方不…

【Ubuntu】配置ubuntu网络

配置ubuntu网络 一、三种虚拟网络介绍二、 配置ubuntu系统使用桥接模式连接外网三、通过NAT模式让ubuntu系统连接外网四、常见问题1.解决ubuntu系统没有网络图标一、三种虚拟网络介绍 VMnet0 : 桥接模式,选中桥接模式之后,可以将VMnet0桥接到对应的物理网卡之上, 默认选中自…

uniapp公共新闻模块components案例

uniapp公共新闻模块components案例 简介&#xff1a;本文使用uniapp的公共新闻模块讲解components案例。 效果展示&#xff1a; 第一步 创建公共模块 第二步 编写组件 <template><view class"newsbox"><view class"pic"><ima…

动态路由协议 OSPF 工作过程 之 状态机维度

状态机 &#xff1a; # 什么是状态机呢 &#xff1f; 状态机 &#xff1a; 就是 OSPF 路由间的邻居关系所在的不同阶段 不同的关系 就是 不同的状态机 OSPF 的状态机 &#xff1a; # 我们用 思科 的PPT 来介绍 OSPF 的状态机 # 里面所有黄颜色方框里 标定的就是 状态机…

Json格式API调试,taobao1688pinduoduo商品详情测试接口

Json常用类型 任何支持的类型都可以通过 JSON 来表示&#xff0c;例如字符串、数字、对象、数组等。但是对象和数组是比较特殊且常用的两种类型。 对象&#xff1a;对象在 JS 中是使用花括号包裹 {} 起来的内容&#xff0c;数据结构为 {key1&#xff1a;value1, key2&#xf…

JavaScript:生成器函数

在介绍生成器函数之前先了解一下ES6的一个关键字&#xff0c;名为yield yield关键字&#xff0c;可以让代码在其出现的地方暂停执行&#xff0c;它只能在生成器函数内部使用。 生成器函数 生成器函数的语法比较简单在普通函数声明的时候在函数名前面添加一个*即可&#xff0…

openxr runtime Monado 源码解析 源码分析:Prober设备发现和管理 system device HMD target instance

monado系列文章索引汇总&#xff1a;openxr runtime Monado 源码解析 源码分析&#xff1a;源码编译 准备工作说明 hello_xr解读openxr runtime Monado 源码解析 源码分析&#xff1a;整体介绍 模块架构 模块作用 进程 线程模型 整体流程openxr runtime Monado 源码解析 源码分…

计算机网络4小时速成:物理层,功能特性,通信系统模型,分类,调制,曼彻斯特编码,信噪比,香农定理,复用技术,同轴电缆,中继器

计算机网络4小时速成&#xff1a;物理层&#xff0c;功能特性&#xff0c;通信系统模型&#xff0c;分类&#xff0c;调制&#xff0c;曼彻斯特编码&#xff0c;信噪比&#xff0c;香农定理&#xff0c;复用技术&#xff0c;同轴电缆&#xff0c;中继器 2022找工作是学历、能力…

[附源码]计算机毕业设计JAVA基于jsp的网上点餐系统

[附源码]计算机毕业设计JAVA基于jsp的网上点餐系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM m…

Proxy 代理对象使用详解即原理总结

Proxy 代理对象使用详解即原理总结 Proxy简单介绍 ECMAscript 6新增的代理可以给目标对象定义一个关联的代理对象&#xff0c;而这个代理对象可以作为抽象的目标对象来使用&#xff0c;在对目标对象的各种操作影响目标对象之前&#xff0c;可以在代理对象中对这些操作加以控制…

【python与数据分析】Matplotlib数据可视化

目录 前言 一、数据可视化库matplotlib 1.综述 2.pyplot基础语法 &#xff08;1&#xff09;创建画布与创建子图 &#xff08;2&#xff09;添加画布内容 &#xff08;3&#xff09;保存与展示图形 &#xff08;4&#xff09;设置pyplot的动态rc参数 二、绘制折线图 …

Python面向对象总结一

还记得第一次接触Python是在刚刚进入大学的第一个学期&#xff0c;之后就没有再使用过python。虽然基本语法&#xff0c;内置函数等没有忘记&#xff0c;但最近的学习中&#xff0c;一直在用python、matlab混合编程&#xff0c;零零散散的知识点、模模糊糊的记忆&#xff0c;有…

5G无线技术基础自学系列 | 传统无线网络架构

素材来源&#xff1a;《5G无线网络规划与优化》 一边学习一边整理内容&#xff0c;并与大家分享&#xff0c;侵权即删&#xff0c;谢谢支持&#xff01; 附上汇总贴&#xff1a;5G无线技术基础自学系列 | 汇总_COCOgsta的博客-CSDN博客 在4G网络中&#xff0c; 无线侧基本完成…

Anaconda配置镜像源

目录 一、首先生成 Anaconda的 .condarc配置文件&#xff1a; 二、命令行方式配置镜像源 三、可视化界面的方式配置镜像源 一、首先生成 Anaconda的 .condarc配置文件&#xff1a; 打开 Anaconda prompt&#xff0c;敲命令&#xff1a; conda config 查看 .condarc 中的源…

MySQL 增删改查进阶 — 数据库约束

文章目录数据库约束1.约束类型1.1 not null1.2 unique 唯一约束1.3 主键约束 primary key1.4 default 默认值1.5 外键约束 foreign key数据库约束 约束就是让数据库帮助程序猿更好的检查数据是否正确。 1.约束类型 not null - 提示某列不能存储 NULL 值。 允许为空&#xff…

wav to image concat 版

🍿*★,*:.☆欢迎您/$:*.★* 🍿 目录 背景 正文 总结 背景描述

STM32矩阵按键

矩阵按键原理 本实验使用STM32F103单片机&#xff0c;主题代码通用的。 如果每个按键占用一个GPIO引脚&#xff0c;对于使用多个按键来说就是一种资源的浪费&#xff0c;因此当我们在设计时&#xff0c;可以考虑矩阵这种方式。本实验使用4*4也就是16个按键。 矩阵按键相对于独立…

Go 语言搭建个人博客(qiucode.cn 重构篇 三)

1、读取配置文件 项目中如数据库连接、邮箱配置等这些信息一般会被写入一个文件,而通过编码在程序中读取想要的配置信息。 本项目使用yaml文件作为配置文件,配合第三方库viper来读取yaml配置文件。 go get -u github.com/spf13/viper在项目根目录新建一个yaml文件,内容如…