STM32-定时器与日历时钟

1、什么是RTC

实时时钟的缩写是RTC(Real_Time Clock)。RTC 是集成电路,通常称为时钟芯片。

可编程的预分频系数:分频系数高为220。

32位的可编程计数器,可用于较长时间段的测量。

2个分离的时钟:用于APB1接口的PCLK1和RTC时钟(RTC时钟的频率必须小于PCLK1时钟 频率的四分之一以上)。
可以选择以下三种RTC的时钟源

HSE时钟除以128;
LSE振荡器时钟;
LSI振荡器时钟

2个独立的复位类型

APB1接口由系统复位;
RTC核心(预分频器、闹钟、计数器和分频器)只能由后备域复位

3个专门的可屏蔽中断

1.闹钟中断,用来产生一个软件可编程的闹钟中断。
2.秒中断,用来产生一个可编程的周期性中断信号(长可达1秒)。
3.溢出中断,指示内部可编程计数器溢出并回转为0的状态。

RTC时钟源
三种不同的时钟源可被用来驱动系统时钟(SYSCLK):

HSI振荡器时钟
HSE振荡器时钟
PLL时钟

这些设备有以下2种二级时钟源:

40kHz低速内部RC,可以用于驱动独立看门狗和通过程序选择驱动RTC。 RTC用于从停机/待机模式下自动唤醒系统。
32.768kHz低速外部晶体也可用来通过程序选择驱动RTC(RTCCLK)。

RTC具体流程:

RTCCLK经过RTC_DIV预分频,RTC_PRL设置预分频系数,然后得到TR_CLK时钟信号,我们一般设置其周期为1s,RTC_CNT计数器计数,假如1970设置为时间起点为0s,通过当前时间的秒数计算得到当前的时间。RTC_ALR是设置闹钟时间,RTC_CNT计数到RTC_ALR就会产生计数中断,

RTC_Second为秒中断,用于刷新时间。
RTC_Overflow是溢出中断。
RTC Alarm 控制开关机

RTC时钟选择

使用HSE分频时钟或者LSI的时候,在主电源VDD掉电的情况下,这两个时钟来源都会受到影响,因此没法保证RTC正常工作.所以RTC一般都时钟低速外部时钟LSE,频率为实时时钟模块中常用的32.768KHz,因为32768
= 2^15,分频容易实现,所以被广泛应用到RTC模块.(在主电源VDD有效的情况下(待机),RTC还可以配置闹钟事件使STM32退出待机模式).

RTC复位过程

除了RTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV寄存器外,所有的系统寄存器都由系统复位或电源复位进行异步复位。
RTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV寄存器仅能通过备份域复位信号复位。

系统复位后,禁止访问后备寄存器和RCT,防止对后卫区域(BKP)的意外写操作

RTC中断

秒中断: 这里时钟自带一个秒中断,每当计数加一的时候就会触发一次秒中断,。注意,这里所说的秒中断并非一定是一秒的时间,它是由RTC时钟源和分频值决定的“秒”的时间,当然也是可以做到1秒钟中断一次。我们通过往秒中断里写更新时间的函数来达到时间同步的效果

闹钟中断: 闹钟中断就是设置一个预设定的值,计数每自加多少次触发一次闹钟中断

2、创建项目

①、设置RCC

在这里插入图片描述

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

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

②、配置RTC

在这里插入图片描述
Activate Clock Source 激活时钟源
Activate calendar激活日历

在这里插入图片描述
此处的时间为默认值,便于验证初始时间,之后想要设置为其他时间时可以再继续更改

③、使能串口

在这里插入图片描述
使能一下串口,便于发送日期到上位机

④、时钟源设置

在这里插入图片描述
1、选择外部时钟HSE 8MHz
2、PLL锁相环倍频9倍
3、系统时钟来源选择为PLL
4、设置APB1分频器为 /2
5、使能CSS监视时钟
6、设置RTC时钟为LSE

⑤、项目文件设置

在这里插入图片描述
在这里插入图片描述

3、验证初始时间

①、代码:

在main函数中的while循环中加入如下代码:

	  /* Get the RTC current Time */
	  HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN);
      /* Get the RTC current Date */
      HAL_RTC_GetDate(&hrtc, &GetData, RTC_FORMAT_BIN);

      /* Display date Format : yy/mm/dd */
      printf("%02d/%02d/%02d\r\n",2000 + GetData.Year, GetData.Month, GetData.Date);
      /* Display time Format : hh:mm:ss */
      printf("%02d:%02d:%02d\r\n",GetTime.Hours, GetTime.Minutes, GetTime.Seconds);

      printf("\r\n");

      HAL_Delay(1000);

因为在上述代码中使用了printf函数,所以我们还要重写fputc函数,完成printf函数的重定向
在main.c文件中添加如下函数

#include "stdio.h"

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

注意,当在这里重写了printf函数时,我们要勾选Use MiscroLiB
在这里插入图片描述

②、结果

根据预期,输出的结果应该是从1970/1/1 00:00:00开始,但是输出确实从2000年开始的。但是CubeMX中的初始值又是这个值。所以,我认为应该是用cubeMx生成的原因。
在这里插入图片描述

4、RTC时间调整为当前时间

①、修改rtc.c

这里是将时间设置为2021年1月29日,20点16分0秒,是星期一
大家可以自己调节
在这里插入图片描述
我将时间调成了2022-11-1 23:21:0 星期二

  sTime.Hours = 0x23;
  sTime.Minutes = 0x21;
  sTime.Seconds = 0x0;

  DateToUpdate.WeekDay = RTC_WEEKDAY_TUESDAY;
  DateToUpdate.Month = RTC_MONTH_NOVEMBER;
  DateToUpdate.Date = 0x01;
  DateToUpdate.Year = 0x22;

②、结果

在这里插入图片描述

5、输出星期几

①、修改代码

只需要在while循环中在加上如下代码

			if(GetData.WeekDay==1){
				printf("Monday\r\n");
			}else if(GetData.WeekDay==2){
				printf("Tuesday\r\n");
			}else if(GetData.WeekDay==3){
				printf("Wednesday\r\n");
			}else if(GetData.WeekDay==4){
				printf("Thursday\r\n");
			}else if(GetData.WeekDay==5){
				printf("Friday\r\n");
			}else if(GetData.WeekDay==6){
				printf("Saturday\r\n");
			}else if(GetData.WeekDay==7){
				printf("Sunday\r\n");
			}

则,此时while循环中变成:

  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
			  /* Get the RTC current Time */
	    HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN);
      /* Get the RTC current Date */
      HAL_RTC_GetDate(&hrtc, &GetData, RTC_FORMAT_BIN);
      /* Display date Format : yy/mm/dd */
      printf("%02d/%02d/%02d\r\n",2000 + GetData.Year, GetData.Month, GetData.Date);
      /* Display time Format : hh:mm:ss */
      printf("%02d:%02d:%02d\r\n",GetTime.Hours, GetTime.Minutes, GetTime.Seconds);
			/* Display date Format : weekday */
			if(GetData.WeekDay==1){
				printf("Monday\r\n");
			}else if(GetData.WeekDay==2){
				printf("Tuesday\r\n");
			}else if(GetData.WeekDay==3){
				printf("Wednesday\r\n");
			}else if(GetData.WeekDay==4){
				printf("Thursday\r\n");
			}else if(GetData.WeekDay==5){
				printf("Friday\r\n");
			}else if(GetData.WeekDay==6){
				printf("Saturday\r\n");
			}else if(GetData.WeekDay==7){
				printf("Sunday\r\n");
			}
      printf("\r\n");

      HAL_Delay(1000);

  }

②、结果

在这里插入图片描述

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值