0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

第十三章 RTC 实时时钟

W55MH32 ? 来源:W55MH32 ? 作者:W55MH32 ? 2025-05-28 11:32 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

单芯片解决方案,开启全新体验——W55MH32 高性能以太网单片机

W55MH32是WIZnet重磅推出的高性能以太网单片机,它为用户带来前所未有的集成化体验。这颗芯片将强大的组件集于一身,具体来说,一颗W55MH32内置高性能Arm? Cortex-M3核心,其主频最高可达216MHz;配备1024KB FLASH与96KB SRAM,满足存储与数据处理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP协议栈、内置MAC以及PHY,拥有独立的32KB以太网收发缓存,可供8个独立硬件socket使用。如此配置,真正实现了All-in-One解决方案,为开发者提供极大便利。

在封装规格上,W55MH32 提供了两种选择:QFN68和QFN100。

W55MH32Q采用QFN68封装版本,尺寸为8x8mm,它拥有36个GPIO、3个ADC、12通道DMA、17个定时器、2个I2C、3个串口、2个SPI接口(其中1个带I2S接口复用)、1个CAN以及1个USB2.0。在保持与同系列其他版本一致的核心性能基础上,仅减少了部分GPIO以及SDIO接口,其他参数保持一致,性价比优势显著,尤其适合网关模组等对空间布局要求较高的场景。紧凑的尺寸和精简化外设配置,使其能够在有限空间内实现高效的网络连接与数据交互,成为物联网网关、边缘计算节点等紧凑型设备的理想选择。 同系列还有QFN100封装的W55MH32L版本,该版本拥有更丰富的外设资源,适用于需要多接口扩展的复杂工控场景,软件使用方法一致。更多信息和资料请进入http://www.w5500.com/网站或者私信获取。

此外,本W55MH32支持硬件加密算法单元,WIZnet还推出TOE+SSL应用,涵盖TCP SSL、HTTP SSL以及MQTT SSL等,为网络通信安全再添保障。

为助力开发者快速上手与深入开发,基于W55MH32Q这颗芯片,WIZnet精心打造了配套开发板。开发板集成WIZ-Link芯片,借助一根USB C口数据线,就能轻松实现调试、下载以及串口打印日志等功能。开发板将所有外设全部引出,拓展功能也大幅提升,便于开发者全面评估芯片性能。

若您想获取芯片和开发板的更多详细信息,包括产品特性、技术参数以及价格等,欢迎访问官方网页:http://www.w5500.com/,我们期待与您共同探索W55MH32的无限可能。

wKgZO2gbOfaAVPzkACJSygzv-rI600.png

第十三章 RTC 实时时钟

本章分为如下几个小节:

1 RTC简介

2 功能描述

3 RTC寄存器描述

4 程序设计

5 下载验证

1 RTC简介

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

RTC 模块和时钟配置系统(RCC_BDCR 寄存器)处于后备区域,即在系统复位或从待机模式唤醒后,RTC 的设置和时间维持不变。系统复位后,对后备寄存器和 RTC 的访问被禁止,这是为了防止对后备区域(BKP)的意外写操作。

执行以下操作将使能对后备寄存器和 RTC 的访问:

?设置寄存器 RCC_APB1ENR 的 PWREN 和 BKPEN 位,使能电源和后备接口时钟

?设置寄存器 PWR_CR 的 DBP 位,使能对后备寄存器和 RTC 的访问。

1.1 主要特性

W55MH32的RTC的主要特性如下:

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

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

?2 个分离的时钟:用于 APB1 接口的 PCLK1 和 RTC 时钟(RTC 时钟的频率必须小于 PCLK1 时钟频率的四分之一以上)。

?可以选择以下三种 RTC 的时钟源:

······ HSE 时钟除以 128;

······LSE 振荡器时钟;

······LSI 振荡器时钟(详见 6.2.8 节 RTC 时钟)。

?2 个独立的复位类型:

······APB1 接口由系统复位;

······RTC 核心(预分频器、闹钟、计数器和分频器)只能由后备域复位(详见 6.1.3 节)。

?3 个专门的可屏蔽中断:

·······闹钟中断,用来产生一个软件可编程的闹钟中断。

······秒中断,用来产生一个可编程的周期性中断信号(最长可达 1 秒)。

······溢出中断,指示内部可编程计数器溢出并回转为 0 的状态。

2 功能描述

2.1 概述

RTC 由两个主要部分组成(参见下图)。第一部分(APB1 接口)用来和 APB1 总线相连。此单元还包含一组 16 位寄存器,可通过 APB1 总线对其进行读写操作。APB1 接口由 APB1 总线时钟驱动,用来与 APB1 总线接口。

另一部分(RTC 核心)由一组可编程计数器组成,分成两个主要模块。第一个模块是 RTC 的预分频模块,它可编程产生最长为 1 秒的 RTC 时间基准 TR_CLK。RTC 的预分频模块包含了一个 20 位的可编程分频器(RTC 预分频器)。如果在 RTC_CR 寄存器中设置了相应的允许位,则在每个TR_CLK 周期中 RTC 产生一个中断(秒中断)。第二个模块是一个 32 位的可编程计数器,可被初始化为当前的系统时间。系统时间按 TR_CLK 周期累加并与存储在 RTC_ALR 寄存器中的可编程时间相比较,如果 RTC_CR 控制寄存器中设置了相应允许位,比较匹配时将产生一个闹钟中断。

wKgZPGg2gtyAO92YAAL2EvNSggM130.png

简化的 RTC 框图

2.2 复位过程

除了 RTC_PRL、RTC_ALR、RTC_CNT 和 RTC_DIV 寄存器外,所有的系统寄存器都由系统复位或电源复位进行异步复位。

2.3 读RTC寄存器

RTC 核完全独立于 RTCAPB1 接口。

软件通过 APB1 接口访问 RTC 的预分频值、计数器值和闹钟值。但是,相关的可读寄存器只在与RTCAPB1 时钟进行重新同步的 RTC 时钟的上升沿被更新。RTC 标志也是如此的。这意味着,如果 APB1 接口曾经被关闭,而读操作又是在刚刚重新开启 APB1 之后,则在第一次的内部寄存器更新之前,从 APB1 上读出的 RTC 寄存器数值可能被破坏了(通常读到 0)。下述几种情况下能够发生这种情形:

发生系统复位或电源复位

系统刚从待机模式唤醒(参见第 18.3节:低功耗模式)。

系统刚从停机模式唤醒(参见第 18.3节:低功耗模式)。

所有以上情况中,APB1 接口被禁止时(复位、无时钟或断电)RTC 核仍保持运行状态。

因此,若在读取 RTC 寄存器时,RTC 的 APB1 接口曾经处于禁止状态,则软件首先必须等待RTC_CRL 寄存器中的 RSF 位(寄存器同步标志)被硬件置'1')。

注: RTC 的 APB1 接口不受 WFI 和 WFE 等低功耗模式的影响。

2.4 配置RTC寄存器

必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入 RTC_PRL、RTC_CNT、RTC_ALR 寄存器。

另外,对 RTC 任何寄存器的写操作,都必须在前一次写操作结束后进行。可以通过查询 RTC_CR寄存器中的 RTOFF 状态位,判断 RTC 寄存器是否处于更新中。仅当 RTOFF 状态位是'1'时,才可以写入 RTC 寄存器。

配置过程:

1. 查询 RTOFF 位,直到 RTOFF 的值变为'1'

2. 置 CNF 值为 1,进入配置模式

3. 对一个或多个 RTC 寄存器进行写操作

4. 清除 CNF 标志位,退出配置模式

5. 查询 RTOFF,直至 RTOFF 位变为'1'以确认写操作已经完成。仅当 CNF 标志位被清除时,写操作才能进行,这个过程至少需要 3 个 RTCCLK 周期。

2.5 RTC标志的设置

在每一个 RTC 核心的时钟周期中,更改 RTC 计数器之前设置 RTC 秒标志(SECF)。在计数器到达0x0000 之前的最后一个 RTC 时钟周期中,设置 RTC 溢出标志(OWF)。

在计数器的值到达闹钟寄存器的值加 1(RTC_ALR+1)之前的 RTC 时钟周期中,设置 RTC_Alarm 和RTC 闹钟标志(ALRF)。对 RTC 闹钟的写操作必须使用下述过程之一与 RTC 秒标志同步:

使用 RTC 闹钟中断,并在中断处理程序中修改 RTC 闹钟和/或 RTC 计数器。

等待 RTC 控制寄存器中的 SECF 位被设置,再更改 RTC 闹钟和/或 RTC 计数器。

wKgZO2g2gtuAWKpuAABQOZmGcbk772.png

RTC 秒和闹钟波形图示例,PR=0003,ALARM=00004

wKgZPGg2gtuAETx0AABTF3gS0Ig259.png

RTC 溢出波形图示例,PR=0003

3 RTC寄存器描述

3.1 RTC控制寄存器高位(RTC_CRH)

偏移地址:0x00

复位值:0x0000

wKgZO2g2gtuAVCpNAAE-dfGDb5w570.png

这些位用来屏蔽中断请求。注意:系统复位后所有的中断被屏蔽,因此可通过写 RTC 寄存器来确保在初始化后没有挂起的中断请求。当外设正在完成前一次写操作时(标志位 RTOFF=0),不能对RTC_CRH 寄存器进行写操作。RTC 功能由这个控制寄存器控制。

3.2 RTC控制寄存器低位(RTC_CRL)

偏移地址:0x00

复位值:0x0000

wKgZO2g2gt2AMIwcAAbAsZRFPQA209.png

注:1.任何标志位都将保持挂起状态,直到适当的 RTC_CR 请求位被软件复位,表示所请求的中断已经被接受。

2.在复位时禁止所有中断,无挂起的中断请求,可以对 RTC 寄存器进行写操作。

3.当 APB1 时钟不运行时,OWF、ALRF、SECF 和 RSF 位不被更新。

4.OWF、ALRF、SECF 和 RSF 位只能由硬件置位,由软件来清零。

5.若 ALRF=1 且 ALRIE=1,则允许产生 RTC 全局中断。如果在 EXTI 控制器中允许产生 EXTI 线 17 中断,则允许产生 RTC 全局中断和 RTC 闹钟中断。

6.若 ALRF=1,如果在 EXTI 控制器中设置了 EXTI 线 17 的中断模式,则允许产生 RTC 闹钟中断;如果在 EXTI 控制器中设置了 EXTI 线 17 的事件模式,则这条线上会产生一个脉冲(不会产生 RTC闹钟中断)。

3.3 RTC预分频装载寄存器(RTC_PRLH/RTC_PRLL)

预分频装载寄存器用来保存 RTC 预分频器的周期计数值。它们受 RTC_CR 寄存器的 RTOFF 位保护,仅当 RTOFF 值为'1'时允许进行写操作。

RTC 预分频装载寄存器高位(RTC_PRLH)

偏移地址:0x08

复位值:0x0000

wKgZPGg2gtyATt7XAAHOGa_KgWg536.png

RTC 预分频装载寄存器低位(RTC_PRLL)

偏移地址:0x0C

复位值:0x8000

wKgZPGg2gtuAJr6aAADTVrBNncE349.png

注: 如果输入时钟频率(fRTCCLK)为 32.768 千赫,则在此寄存器中写入 7FFFh 以获得 1 秒的信号周期

3.4 RTC预分频器余数寄存器(RTC_DIVH/RTC_DIVL)

在 TR_CLK 的每个周期里,RTC 预分频器中计数器的值都会被重新设置为 RTC_PRL 寄存器的值。用户可通过读取 RTC_DIV 寄存器,以获得预分频计数器的当前值,而不停止分频计数器的工作,从而获得精确的时间测量。此寄存器是只读寄存器,其值在 RTC_PRL 或 RTC_CNT 寄存器中的值发生改变后,由硬件重新装载。

RTC 预分频器余数寄存器高位(RTC_DIVH)

偏移地址:0x10

复位值:0x0000

wKgZO2g2gtuAcr6BAACUkDXJI2c091.png

RTC 预分频器余数寄存器低位(RTC_DIVL)

偏移地址:0x14

复位值:0x8000

wKgZPGg2gtuAJr6aAADTVrBNncE349.png

3.5 RTC计数器寄存器(RTC_CNTH/RTC_CNTL)

RTC 核有一个 32 位可编程的计数器,可通过两个 16 位的寄存器访问。计数器以预分频器产生的TR_CLK时间基准为参考进行计数。RTC_CNT寄存器用来存放计数器的计数值。他们受 RTC_CR的位RTOFF写保护,仅当RTOFF值为'1'时,允许写操作。在高或低寄存器(RTC_CNTH或RTC_CNTL)上的写操作,能够直接装载到相应的可编程计数器,并且重新装载 RTC 预分频器。当进行读操作时,直接返回计数器内的计数值(系统时间)。

RTC 计数器寄存器高位(RTC_CNTH)

偏移地址:0x18

复位值:0x0000

wKgZO2g2gtuAZBeOAADEt3w5CV4574.png

RTC 计数器寄存器低位(RTC_CNTL)

偏移地址:0x1C

复位值:0x0000

wKgZPGg2gtuAatcOAADGAT390g4207.png

3.6 RTC闹钟寄存器(RTC_ALRH/RTC_ALRL)

当可编程计数器的值与 RTC_ALR 中的 32 位值相等时,即触发一个闹钟事件,并且产生 RTC 闹钟中断。此寄存器受 RTC_CR 寄存器里的 RTOFF 位写保护,仅当 RTOFF 值为'1'时,允许写操作。

RTC 闹钟寄存器高位(RTC_ALRH)

偏移地址:0x20

复位值:0xFFFF

wKgZPGg2gtuAGaZZAAC6xOcL1pI689.png

RTC 闹钟寄存器低位(RTC_ALRL)

偏移地址:0x24

复位值:0xFFFF

wKgZO2g2gtuAB8HLAAC6HFoBHCs550.png

3.7 RTC寄存器映像

RTC-寄存器映像和复位值

wKgZO2g2gtyAeJvKAAHN1MrlvTg654.png

4 程序设计

4.1 RTC_Calendar例程

1.初始化部分:延时初始化:调用delay_init()函数,虽未展示其具体实现,但为程序提供时间相关基础功能。

?时钟配置:RCC_ClkConfiguration()函数对系统时钟进行配置。先复位 RCC,开启 HSE 并等待其就绪,配置 PLL 为 HSE 经 1 分频后输入,9 倍频输出,使能 PLL 并等待其就绪,选择 PLLCLK 作为系统时钟源,同时设置 HCLK、PCLK1 和 PCLK2 的分频因子,还开启 LSI 和 HSI。

?串口初始化:UART_Configuration()函数配置 USART1 串口。使能 USART1 和 GPIOA 时钟,将 PA9 配置为复用推挽输出(TX),PA10 配置为浮空输入(RX),设置波特率为 115200,数据位 8 位,停止位 1 位,无校验,无硬件流控制,工作模式为收发模式,最后使能串口。

?NVIC 配置:NVIC_Configuration()函数设置 NVIC 优先级分组为 1,使能 RTC 中断,设置其抢占优先级为 1,子优先级为 0。

?RTC 配置:RTC_Configuration()函数配置 RTC。使能 PWR 和 BKP 时钟,允许访问备份区域,对 BKP 进行初始化,开启 LSI 并等待其就绪,选择 LSI 作为 RTC 时钟源,使能 RTC 时钟并等待同步,设置 RTC 秒中断,设置预分频器为 32767,使 RTC 周期为 1 秒。

2.主循环部分:在main()函数中,先进行延时、时钟配置,接着配置串口,输出 “RTC Calendar Test.” 及系统时钟频率信息。检查 BKP 寄存器值判断 RTC 是否已配置,若未配置则进行 RTC 配置并设置时间,若已配置则判断复位类型并根据情况处理。最后调用Time_Show()函数进入一个循环,当TimeDisplay为 1 时显示当前时间。

3.时间调整与显示部分:时间调整:Time_Adjust()函数调用Time_Regulate()函数获取用户通过串口输入的时分秒,然后设置 RTC 计数器。

// 时间调整函数(通过串口输入设置时间)
void Time_Adjust(void)
{
    RTC_WaitForLastTask();
    RTC_SetCounter(Time_Regulate()); // 调用输入函数获取时间并设置RTC计数器
    RTC_WaitForLastTask();
}
// 时间输入函数(串口交互获取时分秒)
uint32_t Time_Regulate(void)
{
    uint32_t Tmp_HH, Tmp_MM, Tmp_SS;
    
    // 输入小时(0-23)
    printf("rn  Please Set Hours");
    while ((Tmp_HH = USART_Scanf(23)) == 0xFF);
    
    // 输入分钟(0-59)
    printf("rn  Please Set Minutes");
    while ((Tmp_MM = USART_Scanf(59)) == 0xFF);
    
    // 输入秒(0-59)
    printf("rn  Please Set Seconds");
    while ((Tmp_SS = USART_Scanf(59)) == 0xFF);
    
    return (Tmp_HH * 3600 + Tmp_MM * 60 + Tmp_SS); // 返回总秒数
}
// 时间显示函数(实时打印时间)
void Time_Show(void)
{
    printf("nr");
    while (1)
    {
        if (TimeDisplay == 1) // TimeDisplay由RTC中断触发置1
        {
            Time_Display(RTC_GetCounter()); // 转换并显示时间
            TimeDisplay = 0;
        }
    }
}
// 时间格式化显示
void Time_Display(uint32_t TimeVar)
{
    uint32_t THH = TimeVar / 3600;
    uint32_t TMM = (TimeVar % 3600) / 60;
    uint32_t TSS = TimeVar % 60;
    
    // 计数器溢出处理(约24小时归零)
    if (RTC_GetCounter() == 0x0001517F) 
    {
        RTC_SetCounter(0);
        RTC_WaitForLastTask();
    }
    
    printf("Time: %02d:%02d:%02dn", THH, TMM, TSS);
}

时间显示:Time_Show()函数进入一个循环,当TimeDisplay为 1 时,调用Time_Display()函数获取 RTC 计数器的值并转换为时、分、秒格式进行显示。同时,Time_Display()函数还会在 RTC 计数器达到特定值(0x0001517F)时将其重置为 0。

4.串口输入处理部分:USART_Scanf()函数用于从串口接收用户输入的数字,检查输入是否为有效数字,若无效则提示用户重新输入,直到输入有效数字。

4.2 RTC_LSICalib例程

1.初始化部分:延时初始化:调用delay_init()函数,虽未给出其具体实现,但为程序提供时间相关的基础功能。

// 1. 延时初始化(依赖delay.h实现)
delay_init();

// 1.a 串口初始化
void UART_Configuration(uint32_t bound)
{
    // 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
    
    // 配置TX/RX引脚
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;  // PA9-TX
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_10;  // PA10-RX
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 配置串口参数
    USART_InitStructure.USART_BaudRate = bound;  // 115200bps
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    
    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE);
}

// 1.b RTC配置
void RTC_Configuration(void)
{
    // 使能电源和备份域时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
    PWR_BackupAccessCmd(ENABLE);
    
    BKP_DeInit();  // 复位备份域
    
    // 配置RTC时钟源(LSI)
    RCC_LSICmd(ENABLE);
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
    RCC_RTCCLKCmd(ENABLE);
    
    RTC_WaitForSynchro();  // 等待RTC寄存器同步
    RTC_ITConfig(RTC_IT_SEC, ENABLE);  // 使能秒中断
    RTC_SetPrescaler(40000);  // 预设预分频值(假设LSI=40kHz)
    
    // 配置RTC输出
    BKP_TamperPinCmd(DISABLE);
    BKP_RTCOutputConfig(BKP_RTCOutputSource_Second);
}

// 1.c 定时器配置(TIM5用于测量LSI频率)
void TIM_Configuration(void)
{
    // 使能时钟和引脚重映射
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_TIM5CH4_LSI, ENABLE);
    
    // 配置TIM5时基
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
    
    // 配置TIM5通道4为输入捕获模式
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICFilter = 0;
    TIM_ICInit(TIM5, &TIM_ICInitStructure);
    
    // 使能TIM5和捕获中断
    TIM_Cmd(TIM5, ENABLE);
    TIM5->SR = 0;  // 清除中断标志
    TIM_ITConfig(TIM5, TIM_IT_CC4, ENABLE);
}

// 1.d NVIC中断配置
void NVIC_Configuration(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);  // 优先级分组1
    
    // 配置RTC中断(最高优先级)
    NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    // 配置TIM5中断(次高优先级)
    NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

串口初始化:UART_Configuration()函数配置 USART1 串口。使能 USART1 和 GPIOA 时钟,将 PA9 配置为复用推挽输出(用于 TX 发送),PA10 配置为浮空输入(用于 RX 接收)。设置串口波特率为 115200,数据位 8 位,停止位 1 位,无校验位,无硬件流控制,工作模式为同时接收和发送,并最终使能串口。

RTC 配置:RTC_Configuration()函数对 RTC 进行配置。使能 PWR 和 BKP 时钟,允许访问备份区域,对 BKP 进行初始化。开启 LSI,选择 LSI 作为 RTC 时钟源,使能 RTC 时钟并等待同步,设置 RTC 秒中断,设置预分频器为 40000,禁用 BKP 篡改引脚,配置 RTC 输出为秒信号。

定时器配置:TIM_Configuration()函数对 TIM5 进行配置。使能 AFIO 和 TIM5 时钟,重映射 TIM5 通道 4 到 LSI。设置 TIM5 的预分频器为 0,计数模式为向上计数,周期为 0xFFFF,时钟分频为 1。配置 TIM5 通道 4 为输入捕获模式,上升沿触发,直接映射到 TI,不分频,无滤波。使能 TIM5,清除状态寄存器,使能 TIM5 通道 4 捕获中断。

NVIC 配置:NVIC_Configuration()函数设置 NVIC 优先级分组为 1。使能 RTC 中断,设置其抢占优先级为 0,子优先级为 0;使能 TIM5 中断,设置子优先级为 2。

2.主循环部分:在main()函数中,先进行延时初始化,接着配置串口,输出 “RTC LSI Calib Test.” 及系统时钟频率信息。然后进行 RTC、TIM5 配置和 NVIC 配置。等待OperationComplete变为 2,这意味着 TIM5 测量操作完成。当OperationComplete为 2 时,计算 LSI 的实际频率,并根据该频率设置 RTC 的预分频器,最后进入无限循环while(1)。

int main(void)
{
    // 系统初始化
    delay_init();
    UART_Configuration(115200);
    printf("RTC LSI Calib Test.n");
    RCC_GetClocksFreq(&clocks);
    printf("SYSCLK: %3.1fMhz, HCLK: %3.1fMhz, PCLK1: %3.1fMhz, PCLK2: %3.1fMhz, ADCCLK: %3.1fMhzn",
           (float)clocks.SYSCLK_Frequency / 1000000, 
           (float)clocks.HCLK_Frequency / 1000000,
           (float)clocks.PCLK1_Frequency / 1000000, 
           (float)clocks.PCLK2_Frequency / 1000000, 
           (float)clocks.ADCCLK_Frequency / 1000000);
    
    // 外设初始化
    RTC_Configuration();
    TIM_Configuration();
    NVIC_Configuration();
    
    // 2. 等待TIM5测量完成(OperationComplete=2)
    while (OperationComplete != 2);
    
    // 计算LSI实际频率并校准RTC
    if (PeriodValue != 0)
    {
        // LSI频率 = (2*PCLK1)/PeriodValue
        LsiFreq = (uint32_t)((uint32_t)(clocks.PCLK1_Frequency * 2) / (uint32_t)PeriodValue);
    }
    printf("LsiFreq: %d Hzn", LsiFreq);
    
    // 根据测量结果校准RTC预分频器
    RTC_SetPrescaler(LsiFreq - 1);
    RTC_WaitForLastTask();
    
    // 无限循环
    while (1);
}

3.辅助函数部分:IncrementVar_OperationComplete()函数使OperationComplete变量自增,并返回自增前的值。

// 3.a 递增OperationComplete并返回旧值
uint32_t IncrementVar_OperationComplete(void)
{
    OperationComplete++;
    return (uint32_t)(OperationComplete - 1);
}

// 3.b 获取OperationComplete值
uint32_t GetVar_OperationComplete(void)
{
    return (uint32_t)OperationComplete;
}

// 3.c 设置PeriodValue值
void SetVar_PeriodValue(uint32_t Value)
{
    PeriodValue = (uint32_t)(Value);
}

GetVar_OperationComplete()函数返回OperationComplete变量的值。

SetVar_PeriodValue()函数设置PeriodValue变量的值。

5 下载验证

5.1 RTC_Calendar例程

wKgZPGg2gtyAdsnsAAHXEQVL4mw508.png

5.2 RTC_LSICalib例程

wKgZO2g2gtyAVIQ_AAJgDSTOzRQ146.png

WIZnet 是一家无晶圆厂半导体公司,成立于 1998 年。产品包括互联网处理器 iMCU?,它采用 TOE(TCP/IP 卸载引擎)技术,基于独特的专利全硬连线 TCP/IP。iMCU? 面向各种应用中的嵌入式互联网设备。

WIZnet 在全球拥有 70 多家分销商,在香港、韩国、美国设有办事处,提供技术支持和产品营销。

香港办事处管理的区域包括:澳大利亚、印度、土耳其、亚洲(韩国和日本除外)。

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 实时时钟
    +关注

    关注

    4

    文章

    315

    浏览量

    67140
  • RTC
    RTC
    +关注

    关注

    2

    文章

    623

    浏览量

    69081
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    STM32 RTC实时时钟(一)

    STM32处理器内部集成了实时时钟控制器(RTC),因此在实现实时时钟功能时,无须外扩时钟芯片即可构建实时时钟系统。
    的头像 发表于 07-22 15:41 ?5641次阅读
    STM32 <b class='flag-5'>RTC</b><b class='flag-5'>实时时钟</b>(一)

    《我和 LabVIEW》示例程序(2010.04.02)光盘第八至第十三章

    《我和 LabVIEW》示例程序(2010.04.02)光盘第八至第十三章
    发表于 06-27 17:12

    明德扬点拨FPGA课程---第十三章 ?计数器的使用

    第十三章计数器的使用1. 计数器使用原则2. 计数器练习13. 计数器练习1答案4. 计数器练习25. 计数器练习2答案6. 计数器练习37. 计数器练习3答案8. 计数器练习49. 计数器练习4
    发表于 10-30 10:15

    布尔值转换(逐点)vi怎么用啊?还有8.2第十三章中火车轮的检测中怎样画出的柱状图 ?

    布尔值转换(逐点)vi怎么用啊?还有8.2第十三章中火车轮的检测中怎样画出的柱状图 ?求大神解答第十三章火车轮实时监测的实例VI!!!!!!!!!!!!
    发表于 11-14 14:22

    什么是实时时钟RTC)?如何更改RTC的时间?

    什么是实时时钟RTC)?实时时钟RTC)的基本功能是什么?实时时钟RTC)晶体误差的主要来
    发表于 07-19 08:44

    RTC实时时钟简介

    RTC实时时钟1. RTC实时时钟简介2. 硬件设计3. 软件设计3.1 STM32CubeMX设置3.2 MDK-ARM编程4. 下载验证
    发表于 08-18 06:55

    RTC是什么?RTC实时时钟实验

    文章目录前言一、RTC是什么?二、RTC实时时钟实验1.引入库2.读入数据总结前言前面我们说了OLED实验,是一个比较好的显示测试代码的方法。现在我们学习关于RTC
    发表于 01-13 07:19

    RTC实时时钟怎么使用?

    RTC实时时钟怎么使用?cubemx中如何配置RTC?如何在keil中编写程序?
    发表于 01-18 07:33

    浅谈RTC实时时钟特征与原理

    一、RTC实时时钟特征与原理 查看STM32中文手册 16 实时时钟RTC)(308页) RTC (Real Time Clock):
    的头像 发表于 06-30 15:54 ?1.2w次阅读

    STM32CubeMX | 40 - 实时时钟RTC的使用(日历和闹钟)

    STM32CubeMX | 40 - 实时时钟RTC的使用(日历和闹钟)
    发表于 11-23 18:06 ?19次下载
    STM32CubeMX | 40 - <b class='flag-5'>实时时钟</b><b class='flag-5'>RTC</b>的使用(日历和闹钟)

    STM32CubeMX系列|RTC实时时钟

    RTC实时时钟1. RTC实时时钟简介2. 硬件设计3. 软件设计3.1 STM32CubeMX设置3.2 MDK-ARM编程4. 下载验证
    发表于 12-24 19:15 ?16次下载
    STM32CubeMX系列|<b class='flag-5'>RTC</b><b class='flag-5'>实时时钟</b>

    DA1468x SoC 的实时时钟(RTC) 概念

    DA1468x SoC 的实时时钟 (RTC) 概念
    发表于 03-15 20:16 ?0次下载
    DA1468x SoC 的<b class='flag-5'>实时时钟</b>(<b class='flag-5'>RTC</b>) 概念

    实时时钟RTC:32.768kHz晶振

    实时时钟(RTC: Real-Time Clock)是集成电路,通常称为时钟芯片。目前实时时钟芯片大多采用精度较高的晶体振荡器作为时钟源。
    的头像 发表于 05-08 10:45 ?3335次阅读
    <b class='flag-5'>实时时钟</b><b class='flag-5'>RTC</b>:32.768kHz晶振

    DA1468x SoC 的实时时钟(RTC) 概念

    DA1468x SoC 的实时时钟 (RTC) 概念
    发表于 07-06 19:27 ?0次下载
    DA1468x SoC 的<b class='flag-5'>实时时钟</b>(<b class='flag-5'>RTC</b>) 概念

    CW32实时时钟RTC)介绍

    CW32实时时钟RTC)介绍
    的头像 发表于 10-24 15:36 ?1685次阅读
    CW32<b class='flag-5'>实时时钟</b>(<b class='flag-5'>RTC</b>)介绍