一:stm32的RTC功能概述 (基于stm32f10x)
1:绪论
实时时钟是一个独立的计时器,RTC提供一套持续运行的计数器,这些计数器可以配合适合的软件用来提供一个时钟日历功能。计数器的值可以被写入以设置系统当前时间/日期
2:主要特性
可编程的余分频器:分频因子可以高达220
用于长期测量的32位可编程的计数器
2个独立的时钟:PCLK1时钟(用于APB1接口)和RTC时钟(必须比PCLK1时钟慢至少4倍)
两个单独的复位类型:
APB1由系统复位复位
RTC内核(分频器、警告、计数器、除法器)通过备份区域复位来复位
三个专用的可屏蔽中断线:
警告中断线,用来产生一个软件可编程的警告中断
秒中断线,用来产生一个周期性(周期长度可编程,高达1s)的中断信号
溢出中断线,用来检测内部可编程计数器什么时候翻滚到0
3:功能描述
(1)概要:
RTC 由两个主要的单元组成,第一个(APB1 接口)用于提供和 APB1
总线的接口,该单元还包括一套可以从 APB1总线以读或者写方式访问的16位的寄存器。APB1 接口由 APB1总线时钟驱动以和APB1总线连接。
另一个单元(RT内核)由一串可编程的计数器组成,这些计数器由两个模块构成:第
一个模块是RTC 预分频器模块,该模块产生RTC 时间基数 TR_CLK,时基可以被编程为1
个可以高达1秒的周期,它包含一个20位的可编程除法器(RTC预分频器)如果在RTC_CR
寄存器中使能了这个中断的话,每个TR_CLK 周期,RTC产生一个中断(秒中断);第二个
模块是一个32位的可编程的计数器,该计数器可以用当前的系统时间来初始化,系统时间
以 TR_CLK速率速率递增,并且和一个可编程的日期(存储在RTC_ALR 急存器中)进行比较以
产生一个警告中断(如果该中断在RTC_CR 控制寄存器中被使能了的话)
RTC简化结构图
4:读取RTC寄存器
RTC内核完全独立于RTC APB1接口
软件通过 APB1 接口访问RTC 预分频器,计数器和警告值,但是相关的可读寄存器在
每个由 RTC APB1 时钟再同步过的RTC时钟的上升沿期间内部更新。这对于RTC标志来说
也是一样的。
这意味着如果 APB1接口先前被禁用了在APB1接口使能后并且还没有进行第一次内
部更新之前迅速读取RTC APB1寄存器读出的值可能是错误的(一般读到0)。这在以下情
况下可能发生:
(1) 发生了系统复位或电源复位
(2)MCU刚从STANDBY模式唤醒
(3)MCU刚从停止模式唤醒
在以上所有的情况,APB1接口禁用(复位,无时钟驱动或者无电源供应)期间RTC
内核被保持在运行状态。
因此,当禁用 RTC APB1接口后读取RTC寄存器时,软件首先必须等待RTC_CRL寄存
器中的 RSF位(寄存器同步位)被硬件置位。
注意 RTC APB1 接口不受WFI和 WFE 低功耗模式影响。
5:配置RTC寄存器
为了写 RTC_PRL,RTC_CNT,RTC_ALR寄存器,外设必须进入配置模式,这是通过
设置 RTC_CRL 寄存器中的CNF位来完成。
另外,向任何RTC 寄存器的写操作仅当先前的写操作完成后才被进行。为了使软件能
够检测这种情况,RTC_CR 寄存器中的RTOFF 状态位专门用来指示寄存器是否正在进行更
新中,仅当 RTOFF 状态位值为‘1’的时候才能够向RTC 寄存器中写入新值。
配置的过程:
1.轮询 RTOFF 位,在它的值变为‘1’之前等待
2. 置位 CNF 位以进入配置模式
3.写一个或者多个RTC 寄存器
4.清除 CNF 位以退出配置模式
5.轮询 RTOFF,直到它的值变成‘1’以确认写操作结束
写操作仅当 CNF位被清除时才执行,需要至少3个RTCCLK周期才能够完成。
二:stm32cubemx中RTC配置
1:第一步 创建工程
打开stm32cubemx 选择芯片
2:第二步 配置RTC
RTC使能日历 将初始时间设置为 2024年8月1日18时50分39秒 周四
3:第三步 配置调试接口
4:第四步 配置时钟
5:第五步 配置串口
使能串口2 波特率为115200 数据位为8 奇偶校验位无 停止位1
6:生成工程
三:实现RTC读取时钟
1: 第一步 打开工程 编译一下
在main函数中可以找到rtc模块的初始化函数
时分秒设置
年月日 周几设置
2: 第二步 定义声明接收时间数据和日期数据的结构体
找到hal库中存放时间和日期的结构体原型
时间数据结构体原型
日期数据结构体原型
在main函数开头定义时间数据结构体和日期数据结构体用来接收rtc模块的数据
3: 第三步 重定向串口函数
找地方重写printf重定向函数
包含相关的头文件
函数源码
int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xffff); return ch; }
4: 第四步 在HAL库函数中找到获取时间和日期的函数
hal库中获取rtc时间函数
hal库中获取rtc日期函数
5: 第五步 调用函数将RTC时钟的时间数据存放到接收数据的结构体中
调用函数获取时间
调用函数获取日期
6: 第六步 通过串口将时间和日期发送出去
串口发送 日期
串口发送时间
调用延时函数延时1s 在循环内每隔1s读取时间和日期并将时间和日期发送出去
7:通过usb转tll用串口调试助手在电脑端显示数据
第一步:准备usb转tll模块
第二步:接线
单片机的 rx 对应usb转tll的tx tx 对应 usb转tll的rx
第三步:下载代码后打开串口调试助手 选择配置串口是时的波特率 数据位 校验位等
单片机发送出的日期和时间数据 实现1s发送一次 一次发送两行 第一行 为年 月 日 周几
第二行为时 分 秒
串口助手收不到数据时可以查看是否是魔术棒选项未勾选 Use MicroLIB
mian函数源码
int main(void) { /* USER CODE BEGIN 1 */ RTC_TimeTypeDef time_data; //接收时间数据结构体 时分秒 RTC_DateTypeDef date_data; //接收日期数据结构体 周几 几月 第几天 几几年 /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_RTC_Init(); MX_USART2_UART_Init(); /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ //调用获取时间函数 HAL_RTC_GetTime(&hrtc,&time_data,RTC_FORMAT_BIN); //调用获取日期函数 HAL_RTC_GetDate(&hrtc,&date_data,RTC_FORMAT_BIN); //串口输出日期 printf("%02d/%02d/%02d %d",2000+date_data.Year,date_data.Month,date_data.Date,date_data.WeekDay); //串口输出时间 printf("%02d:%02d:%02d",time_data.Hours,time_data.Minutes,time_data.Seconds); HAL_Delay(1000); //单位ms 1000 = 1s } /* USER CODE END 3 */ }