STM32 —— RTC 时间读取

这篇具有很好参考价值的文章主要介绍了STM32 —— RTC 时间读取。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

STM32 —— RTC 时间读取

实验目的

了解实时时钟RTC的原理。STM32 芯片自带 RTC,因此不须像其他 MCU 需外接 RTC 模块。请编程实现 STM32 的日历读取、设置和输出。要求:

  1. 读取 RTC 初始时间,验证是否为 1970年1月1日零分零秒;

  2. 将 RTC 时间调整为当前时间,并以 2021年x月x日x分x秒的格式从串口输出(或输出到OLED屏),每1s改变一次;

  3. 如果输出内容中需加入“星期x”,请修改代码。

实验原理

根据实验要求,我们需要读取 RTC 模块的日历,这里我们就需要知道在 STM32 中是自带 RTC 的,不像其他的 MCU 一样需要外接,这里我们就可以直接设置并通过 HAL 库调用一些 RTC 的函数,完成指定的要求,由于 RTC 掉电后会重置,这里设计了代码来防止 RTC 在掉电后被重置导致时间回到初始设置状态

具体的 RTC 原理可以看我的另一篇博客:STM32 —— RTC 入门

HAL 库方法

CubeMX 项目配置

RCC 配置

设置高速外部时钟 HSE 选择外部时钟源,使能外部晶振 LSE

STM32 —— RTC 时间读取
时钟配置
STM32 —— RTC 时间读取

这里说明一下为什么要使用 LSE 外部晶振:

RTC 设备因为其独特的运行方式(即掉电依旧运行)使用 HSE 分频时钟或者 LSI 的时候,在主电源 VDD 掉电的情况下,这两个时钟来源都会受到影响,资源消耗太大,小小的纽扣电池根本吃不消。没法保证 RTC 正常工作.所以 RTC 一般都时钟低速外部时钟 LSE

USART1 配置
STM32 —— RTC 时间读取
RTC 配置
STM32 —— RTC 时间读取

RTC_OUT: Not RTC_OUT

Tamper: ×

第一个是是否使能 tamper(PC13)引脚上输出校正的秒脉冲时钟,第二个是 RTC 入侵检测校验功能

RTC 校验功能,使能侵入检测功能。RTC 时钟经 64 分频输出到侵入检测引脚 TAMPER 上,当 TAMPER 引脚上的信号从 0 变成 1 或者从 1 变成 0 (取决于备份控制寄存器 BKP_CR 的 TPAL 位),会产生一个侵入检测事件。侵入检测事件将所有数据备份寄存器内容清除

也就是第一个是使能 tamper(PC13)引脚作为时钟脉冲输出,第二个是使能 tamper(PC13)引脚作为入侵检测功能

在第一个任务的时候,我们是要进行读取默认的系统时间,这里不需要进行设置:

STM32 —— RTC 时间读取

第二个任务要求我们进行时间设置,这里直接设置成相对应该的时间即可:

STM32 —— RTC 时间读取
TIM2 配置
STM32 —— RTC 时间读取
引脚配置
STM32 —— RTC 时间读取

代码设计

首先我们需要知道两个 RTC 的中断:

RTC_IRQHandler()	// RTC 全局中断

RTCAlarm_IRQHandler()	// 闹钟中断函数

我们首先可以看 stm32f1xx_hal_rtc.h ,这里在库中已经给我们封装好了一些能够获取目前板载系统时间和日历的一些内容,并且提供了一些设定闹钟的函数,我们直接使用即可

STM32 —— RTC 时间读取

下面我们对函数中的三个变量进行分析:

RTC_HandleTypeDef *hrtc	// 我们要调用的封装了 RTC 的串口

RTC_TimeTypeDef *sTime/sData	// 我们获取的时间的对象,HAL 库中已经给出了对应的结构体,我们只需要声明对应的结构体成员即可

uint32_t Format	// 这是我们所需要的时间或日期的数据编排格式,我们需要填写我们事先在前面设置的格式即可
STM32 —— RTC 时间读取
STM32 —— RTC 时间读取

前面我们已经实现了定时器,这里我们依旧使用定时器方法进行设计,这样可以提高 cpu 使用效率,并且这里也采用我们前面提到过的重写 printf 函数的方式进行输出

重写 fputc 函数:

int fputc(int ch,FILE *f){
		uint8_t temp[] = {ch};
		HAL_UART_Transmit(&huart1,(uint8_t*)temp,sizeof(temp),0xFFFF);
		return ch;
}

启动定时器 TIM2:

HAL_TIM_Base_Start_IT(&htim2);

重写定时器回调函数与 RTC 计时器获取时间:

RTC_DateTypeDef Date;
RTC_TimeTypeDef Time;

uint8_t str[] = "ppqppl\r\n";

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
	static int time = 0;
	if(htim->Instance == TIM2){
		time++;
		if(time%1000 == 0){
			HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
			HAL_RTC_GetDate(&hrtc,&Date,RTC_FORMAT_BIN);
			HAL_RTC_GetTime(&hrtc,&Time,RTC_FORMAT_BIN);
			printf("%02d年-%02d月-%02d日\r\n",Date.Year,Date.Month,Date.Date);	// Date.WeekDay表示日期
			printf("%02d时:%02d分:%02d秒\r\n",Time.Hours,Time.Minutes,Time.Seconds);
			HAL_UART_Transmit(&huart1,(uint8_t*)str,sizeof(str),0xFFFF);
			printf("\r\n");
		}
	}
}

注意:这里由于 RTC 会占用 PC13 引脚,所以这里选择使用 PA5 外接小灯泡进行测试

如果我们需要读取日期,并且需要显示当前时间的话,我们就需要在 CubeMX 中设置好时间,然后在代码中对时间进行简单的判断和计算即可显示正确的时间日期,由于其他代码相同,这里只提供最终输出的代码段,代码如下:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
	static int time = 0;
	if(htim->Instance == TIM2){
		time++;
		if(time%1000 == 0){
			HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
			HAL_RTC_GetDate(&hrtc,&Date,RTC_FORMAT_BIN);
			HAL_RTC_GetTime(&hrtc,&Time,RTC_FORMAT_BIN);
			printf("%02d年-%02d月-%02d日-",2000+Date.Year,Date.Month,Date.Date);	// 由于在 CubeMX 中设置的年份只是后两位,这里需要加上 2000 来表示当前年份
			switch(Date.WeekDay){	// Date.WeekDay 是数字 1-7 ,分别代表星期一到星期日
				case 1:{
					printf("星期一\r\n");
					break;
				}
				case 2:{
					printf("星期二\r\n");
					break;
				}
				case 3:{
					printf("星期三\r\n");
					break;
				}
				case 4:{
					printf("星期四\r\n");
					break;
				}
				case 5:{
					printf("星期五\r\n");
					break;
				}
				case 6:{
					printf("星期六\r\n");
					break;
				}
				case 7:{
					printf("星期日\r\n");
					break;
				}
				default:{
					printf("没有获取到WeekDay数据!\r\n");
					break;
				}
			}
			printf("%02d时:%02d分:%02d秒\r\n",Time.Hours,Time.Minutes,Time.Seconds);
			HAL_UART_Transmit(&huart1,(uint8_t*)str,sizeof(str),0xFFFF);
			printf("\r\n");
			time = 0;
		}
	}
}

当然我们也可以在 rtc.c 中通过代码去设置时间,但是要注意的是,这里对变量赋值应该是 16 进制的,否则可能会导致输出异常,代码如下:

sTime.Hours = 0x12;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;

DateToUpdate.WeekDay = RTC_WEEKDAY_FRIDAY;
DateToUpdate.Month = RTC_MONTH_NOVEMBER;
DateToUpdate.Date = 0x4;
DateToUpdate.Year = 0x22;

标准库方法

若有需要,后续会更新标准库写法

寄存器方法

若有需要,后续会更新寄存器写法

运行测试

虚拟串口测试

虚拟串口测试:

STM32 —— RTC 时间读取

这里由于串口测试没有放着环境,只能看到输出情况

Proteus 仿真模拟

由于 Proteus 无法使用外部晶振,所以 RTC 这里选择的是 LSI 运行

仿真图如下:

STM32 —— RTC 时间读取

图中给出了外部 LSE 的正确接发(虽然无法使用)

运行结果:

STM32 —— RTC 时间读取

由于时间过长,这里将时间缩短为 0.1 秒

接线示例

STM32 —— RTC 时间读取
STM32 —— RTC 时间读取
STM32 —— RTC 时间读取

运行结果

STM32 —— RTC 时间读取
STM32 —— RTC 时间读取

结果分析

这里可以看到,RTC 基于 HAL 库的初始日期并不是 1970 年,而是编译器设置的默认值,在 CubeMX 中默认值是 00 年,也就是说,默认值只是设置了年份的后两位,只要我们在输出时年份进行简单计算后,就可以设置成任意年限

波形检测

做波形检测没有意义,这里直接省略这一步骤

错误解决方法

  1. 串口输出问题

对于重写 printf 串口输出,会存在一个致命的问题,就是当你的函数存在问题时,会出现乱码,重写 fputc 函数和注意事项如下:

int fputc(int ch,FILE *f){
		uint8_t temp[] = {ch};	// 这里注意一定要将 ch 存在字符串数组中,不能直接将 ch 转为 uint8_t 类型
		HAL_UART_Transmit(&huart1,temp,1,0xFFFF);	// 这里特别要注意输出的一定要是上面声明的 temp ,不能直接输出(uint8_t *)ch ,否则就会产生输出乱码
		return ch;
}
  1. 时间输出问题

对于时间的获取,函数调用如下:

HAL_RTC_GetDate(&hrtc,&Date,RTC_FORMAT_BIN);
HAL_RTC_GetTime(&hrtc,&Time,RTC_FORMAT_BIN);

需要注意的是,这里函数的第三个参数是时间的格式,我们一定要选择 RTC_FORMAT_BIN 格式,不然我们就会发现输出的时间与实际设置的时间不符,甚至可能会出现 17 月份或星期 9 这样诡异的时间点

  1. 仿真运行问题

如果我们在使用 MDK 进行仿真的时候出现如下问题:

*** error 65: access violation at 0x40021000 : no 'read' permission

则是因为较新版本默认用的是 CM 内核,如果使用的是 STM 系列就会出现这种错误,只要把参数设置成相应的 STM 系列的就可以使用了

STM32 —— RTC 时间读取

这个报错本质上就是因为我们的 Memory_map 地址不够大,导致我们程序无法正常运行,虽然程序没有问题,但是会产生仿真运行中程序中断报错文章来源地址https://www.toymoban.com/news/detail-506421.html

参考文档

到了这里,关于STM32 —— RTC 时间读取的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【STM32】学习笔记-时间戳&RTC

    Unix 时间戳(Unix Timestamp)定义为从UTC/GMT的1970年1月1日0时0分0秒开始所经过的秒数,不考虑闰秒 时间戳存储在一个秒计数器中,秒计数器为32位/64位的整型变量 世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间. 好处:时间间隔好;硬件电路使用;储存

    2024年02月10日
    浏览(27)
  • STM32CubeMX教程11 RTC 实时时钟 - 入侵检测和时间戳

    目录 1、准备材料 2、实验目标 3、实验流程 3.0、前提知识 3.1、CubeMX相关配置 3.1.0、工程基本配置 3.1.1、时钟树配置 3.1.2、外设参数配置 3.1.3、外设中断配置 3.2、生成代码 3.2.0、配置Project Manager页面 3.2.1、外设初始化调用流程 3.2.2、外设中断调用流程 3.2.3、添加其他必要代码

    2024年02月03日
    浏览(33)
  • STM32 HAL库 RTC实时时钟打印时间日期 掉电不清零 CubeMX

    启用HSE和HSI 启用RTC和Calendar功能,选择内部唤醒 设置参数 Hour Format:小时格式(12小时或24小时制) Asynchronous Predivider value:异步分频系数 Synchronous Predivider value:同步分频系数 异步分频系数和同步分频系数共同决定RTC的频率。当使用32.768KHz的LSE时,RTC分频后的时钟频率为

    2024年04月27日
    浏览(34)
  • 【正点原子STM32连载】 第二十七章 RTC实验摘自【正点原子】APM32E103最小系统板使用指南

    1)实验平台:正点原子APM32E103最小系统板 2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420 3)全套实验源码+手册+视频下载地址: http://www.openedv.com/docs/boards/xiaoxitongban 本章介绍APM32E103实时时钟(RTC)的使用,实时时钟能为系统提供一个准确的时间,即时系统复位或主

    2024年01月19日
    浏览(47)
  • STM32-单通道ADC采集(DMA读取)实验

    关于ADC的一些原理和实验我们已经有了2篇笔记,链接如下: 关于ADC的笔记1_Mr_rustylake的博客-CSDN博客 STM32-ADC单通道采集实验_Mr_rustylake的博客-CSDN博客 实验要求:通过ADC1通道1(PA1)采集电位器的电压,并显示ADC转换的数字量和换算后的电压值。 我们通过下表可以知道DMA1通道

    2024年02月16日
    浏览(36)
  • STM32——电容触摸按键充电时间测量实验

    无手指触摸:上电时,电阻作用下,电容Cs进行充电,直到电容充满,这时候会有一个充电时间Tcs。 有手指触摸:上电时,电阻作用下,电容Cs和Cx进行充电,电容充满时间会变长,得到充电时间Tcx。 注意:充电过程可以看成是一个信号从低电平变为高电平的过程。STM32认为高

    2024年02月01日
    浏览(32)
  • STM32 第19讲 IIC(协议简介/读取驱动AT24C02/实验)

    IIC: Inter Integrated Circuit,集成电路总线,是一种 同步 串行 半双工通信协议 ①总线由数据线 SDA 和时钟线 SCL 构成的串行总线,数据线用来传输数据,时钟线用来同步数据收发。 ②总线上每一个器件都有一个唯一的地址识别,所以我们只需要知道器件的地址,根据时序就可以

    2024年02月03日
    浏览(30)
  • 32单片机RTC时间接续,掉电时间保存

    前提:首先要实现RTC掉电之后时间还能继续走,RTC电池是必要的 说明:设备第一次启动需要初始化配置RTC,但当二次启动再重新配置RTC会导致RTC计数器置零,所以传统的程序流程是不行的,我们需要知道设备是第一次启动还是二次启动,来判断是否需要重新初始化配置RTC。另

    2024年01月17日
    浏览(37)
  • 看野火的视频,用正点原子的板子(STM32F4探索者)做ADC读取电压实验

    使用STM32F4的ADC1通道5(PA5)来采样外部电压值(这里采样两个电压值TPAD(3.3v),GND(0v)),最后通过串口打印电压值。 由上图可以看到, ADC1 的通道 5是对应着引脚PA5的。 板子右边是GND,ADC,TPAD引脚,做实验时,把两者相连即可读电压值。 ADC时钟: 这里是用于模拟电路的时

    2024年02月09日
    浏览(33)
  • IMX6ULL裸机篇之RTC实验-时间错误问题

    我这里用的开发板上芯片是 IMX6ULL,但是,由于恩智浦提供的 IMX6ULL芯片的参考手册关于 RTC章节的不全面。所以,实际在开发时使用了 《IMX6UL参考手册》。 对参考手册的理解如下: LPSRTCMR 寄存器 与 LPSRTCLR 寄存器是存时间的两个寄存器。即用两个寄存器来存时间。 读取SRTC的

    2024年02月06日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包