STM32H743-ARM例程15-RTC

目录

实验平台

硬件:银杏科技GT7000双核心开发板-ARM-STM32H743XIH6,银杏科技iToolXE仿真器

软件:最新版本STM32CubeH7固件库STM32CubeMX v6.10.0,开发板环境MDK v5.35,串口工具putty

RTC

RTC介绍

RTC(Real-Time Clock)是电子设备中的‌独立计时模块‌,功能类似于电子手表,用于管理所有低功耗模式的自动唤醒单元。实时时钟 (RTC) 是一个独立的 BCD 定时器/计数器。RTC 提供具有可编程闹钟中断功能的日历时钟/日历。RTC拥有独立电源域‌:通过VBAT引脚连接备份电池(典型3V CR2032),主电源关闭时保持计时。

主要特性如下:

  • 包含亚秒、秒、分钟、小时(12/24 小时制)、星期几、日期、月份和年份的日历。
  • 软件可编程的夏令时补偿,自动将月份的天数补偿为 28、29(闰年)、30 和 31 天。
  • 具有中断功能的可编程闹钟。可通过任意日历字段的组合触发闹钟。
  • 自动唤醒单元,可周期性地生成标志以触发自动唤醒中断。
  • 参考时钟检测:可使用更加精确的第二时钟源(50Hz 或 60Hz)来提高日历的精确度。
  • 利用亚秒级移位特性与外部时钟实现精确同步。
  • 数字校准电路(周期性计数器调整):精度为 0.95ppm,在数秒钟的校准窗口中获得。
  • 用于事件保存的时间戳功能。
  • 带可配置过滤器和内部上拉的入侵检测事件。
  • 可屏蔽中断/事件:
    • --闹钟 A
    • --闹钟 B
    • --唤醒中断
    • --时间戳
    • --入侵检测
  • 32 备份寄存器。

RTC框图

1.时钟源

STM32H743 的 RTC 时钟(RTCCLK)通过时钟控制器,可以从 LSE 时钟、LSI 时钟以及HSE 时钟三者中选择(通过 RCC_BDCR寄存器选择)。一般我们选择 LSE,即外部 32.768Khz 晶振作为时钟源(RTCCLK),而 RTC时钟核心,要求提供 1Hz 的时钟,所以,我们要设置 RTC 的可编程预分配器。

2.预分频器

STM32H743的可编程预分配器(RTC_PRER)分为 2 个部分:

(1) 一个通过 RTC_PRER 寄存器的 PREDIV_A 位配置的 7 位异步预分频器。

(2) 一个通过 RTC_PRER 寄存器的 PREDIV_S 位配置的 15 位同步预分频器。

RTC 框图中,ck_spre 的时钟可由如下计算公式计算:

Fck_spre=Frtcclk/[(PREDIV_S+1)*(PREDIV_A+1)]

其中,Fck_spre 即可用于更新日历时间等信息。PREDIV_A 和 PREDIV_S 为 RTC 的异步和同步分频器。且推荐设置 7 位异步预分频器(PREDIV_A)的值较大,以最大程度降低功耗。

3.日历时间(RTC_TR)和日期(RTC_DR)寄存器

STM32H743 的 RTC 日历时间(RTC_TR)和日期(RTC_DR)寄存器,用于存储时间和日期(也可以用于设置时间和日期),可以通过与 PCLK1(APB1 时钟)同步的影子寄存器来访问,这些时间和日期寄存器也可以直接访问,这样可避免等待同步的持续时间。

每隔 2 个 RTCCLK 周期,当前日历值便会复制到影子寄存器,并置位 RTC_ISR 寄存器的 RSF 位。我们可以读取RTC_TR 和 RTC_DR 来得到当前时间和日期信息,不过需要注意的是:时间和日期都是以BCD 码的格式存储的,读出来要转换一下,才可以得到十进制的数据。

4.可编程闹钟

STM32H743 提供两个可编程闹钟:闹钟 A(ALARM_A)和闹钟 B(ALARM_B)。通过 RTC_CR 寄存器的 ALRAE 和 ALRBE 位置 1 来使能闹钟。当日历的亚秒、秒、分、小时、日期分别与闹钟寄存器RTC_ALRMASSR/RTC_ALRMAR和RTC_ALRMBSSR/RTC_ALRMBR 中的值匹配时,则可以产生闹钟(需要适当配置)。本章我们将利用闹钟A 产生闹铃,即设置RTC_ALRMASSR 和 RTC_ALRMAR 即可。

5.周期性自动唤醒

STM32H743 的 RTC 不带秒钟中断,但是多了一个周期性自动唤醒功能。周期性唤醒功能,由一个 16 位可编程自动重载递减计数器(RTC_WUTR)生成,可用于周期性中断/唤醒。

我们可以通过 RTC_CR 寄存器中的WUTE 位设置使能此唤醒功能。唤醒定时器的时钟输入可以是:2、4、8 或 16 分频的 RTC 时钟(RTCCLK),也可以是 ck_spre 时钟(一般为1 HZ)。

本实验中,通过软件对 RTC 计数器进行相关的配置,可以提供时钟功能,通过修改计时器的值可以调整时钟。最终通过串口在终端显示时间。

STM32CubeMX生成工程

我们参考前面章节STM32H743-结合CubeMX新建HAL库MDK工程,打开CubeMX软件,重复步骤不再展示,我们来看配置RTC部分如下图所示:

实验代码

1. 主函数

c 复制代码
int main(void)
{
    RTC_TimeTypeDef sTime;
    //定义RTC_TimeTypeDef结构体类型下的结构体变量sTime(时间)
    RTC_DateTypeDef sDate;//(日期)
    int second_bak = 0;
    MPU_Config();
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_RTC_Init();
    MX_USART6_UART_Init();
    uart6.initialize(115200);
    //设置RTC日期和时间
    my_rtc.set_date(25,3,11,2);
    my_rtc.set_time(14,32,00);
    while (1)
    {
        if(systick._500ms_flag == 1)
        {
            systick._500ms_flag = 0;
            HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
            //使用HAL库函数获取RTC的时间信息,将结果存储在sTime变量中
            HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
            //使用HAL库函数获取RTC的日期信息,将结果存储在sDate变量中
            if(second_bak != sTime.Seconds)                              
            //上一秒的秒数second_bak是否与当前秒数sTime.Seconds不相等,用于实现每秒钟输出一次RTC时间
            {
                uart6.printf("\x0c");             //用于清屏操作
                uart6.printf("\033[1;32;40m");    //用于设置终端显示颜色
                uart6.printf("Hello,I am GT7000!\r\nThis is RTC TIME interface!\r\n");
                uart6.printf("RTC TIME:");
                uart6.printf(" %02d:%02d:%02d",sTime.Hours,sTime.Minutes,sTime.Seconds);                 //将格式化后的时间信息发送到UART6,格式为"时:分:秒"
                uart6.printf("20%02d-%02d-%02d星期期%01d\r\n\r\n",sDate.Year,sDate.Month,sDate.Date,sDate.WeekDay);
                //将格式化后的日期信息发送到UART6,格式为"年-月-日   星期-"
                second_bak = sTime.Seconds;
            }
        }
    }
}

2. RTC初始化

c 复制代码
void MX_RTC_Init(void)
{
    RTC_TimeTypeDef sTime = {0};
    RTC_DateTypeDef sDate = {0};
    hrtc.Instance = RTC;
    hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
    hrtc.Init.AsynchPrediv = 127;
    hrtc.Init.SynchPrediv = 255;
    hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
    hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
    hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
    hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
    if (HAL_RTC_Init(&hrtc) != HAL_OK)
    {
        Error_Handler();
    }
    sTime.Hours = 0x11;
    sTime.Minutes = 0x40;
    sTime.Seconds = 0x0;
    sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
    sTime.StoreOperation = RTC_STOREOPERATION_RESET;
    if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
    {
        Error_Handler();
    }
    sDate.WeekDay = RTC_WEEKDAY_TUESDAY;
    sDate.Month = RTC_MONTH_MARCH;
    sDate.Date = 0x11;
    sDate.Year = 0x0;
    if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
    {
        Error_Handler();
    }
    if (HAL_RTCEx_SetWakeUpTimer(&hrtc, 0, RTC_WAKEUPCLOCK_RTCCLK_DIV16) != HAL_OK)
    {
        Error_Handler();
    }
}

该函数用来初始化 RTC 配置以及日期和时钟,这里设置时间和日期,分别是通过

HAL_RTC_SetTime 函数和 HAL_RTC_SetDate 函数来实现。

3、设置时间和日期

主函数中调用设置时间和日期的自定义函数rtc_set_time 和rtc_set_date 来设置初始时间日期,这两个函数实际就是调用库函数里面的 HAL_RTC_SetTime 函数和HAL_RTC_SetDate函数来实现的,它们的定义如下:

c 复制代码
static int rtc_set_time(unsigned char hour,unsigned char min,unsigned char sec)
{
    RTC_TimeTypeDef sTime;
    
    sTime.Hours = hour;
    sTime.Minutes = min;
    sTime.Seconds = sec;
    sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
    sTime.StoreOperation = RTC_STOREOPERATION_RESET;
    if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
    {
        while(1);
    }
    return 0;
}
static int rtc_set_date(unsigned char year,unsigned char month,unsigned char date,unsigned char week)
{
    RTC_DateTypeDef sDate;
    sDate.WeekDay = week;
    sDate.Month = month;
    sDate.Date = date;
    sDate.Year = year;
    if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
    {
        while(1);
    }       
    return 0;
}

实验现象

在终端屏幕上可以看到显示的时间和日期。如图所示。

相关推荐
pu_taoc3 小时前
深入剖析:基于epoll与主从Reactor模型的高性能服务器设计与实现
服务器·c语言·c++·vscode
机器视觉知识推荐、就业指导5 小时前
STM32 外设驱动模块【含代码】:SG90 舵机模块
stm32·单片机·嵌入式硬件·学习
韧竹、6 小时前
数据结构之顺序表
c语言·数据结构
szxinmai主板定制专家9 小时前
RK3588+AI算力卡替代英伟达jetson方案,大算力,支持FPGA自定义扩展
arm开发·人工智能·分布式·fpga开发
努力努力再努力wz11 小时前
【C++进阶系列】:万字详解智能指针(附模拟实现的源码)
java·linux·c语言·开发语言·数据结构·c++·python
凤年徐11 小时前
【C++】string的模拟实现
c语言·开发语言·c++
CodingCos11 小时前
【ARM 嵌入式 编译系列 10.4.3 -- 查看 bss 段在bin 文件中存在吗?】
arm开发
hazy1k12 小时前
K230基础-获取触摸坐标
图像处理·stm32·单片机·嵌入式硬件·k230
知南x12 小时前
STM32MP157目标检测环境搭建 (3) NCNN环境安装
stm32·嵌入式硬件·目标检测