6.4 实例代码
#include "tim4.h" // Device header #include "stdio.h" void TIM4_Init(u16 psc,u16 arr) { TIM_TimeBaseInitTypeDef tim4; NVIC_InitTypeDef NVIC_tim4; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能定时器4时钟 tim4.TIM_ClockDivision=TIM_CKD_DIV1; tim4.TIM_CounterMode=TIM_CounterMode_Down; tim4.TIM_Period=arr; tim4.TIM_Prescaler=psc-1; tim4.TIM_RepetitionCounter=0; TIM_TimeBaseInit(TIM4, &tim4); //初始化定时器4的配置 TIM_ITConfig(TIM4,TIM_IT_Update, ENABLE); //使能更新中断 NVIC_tim4.NVIC_IRQChannel=TIM4_IRQn; //设置的NVIC优先级的中断编号 NVIC_tim4.NVIC_IRQChannelCmd=ENABLE; NVIC_tim4.NVIC_IRQChannelPreemptionPriority=2; //抢占优先级 NVIC_tim4.NVIC_IRQChannelSubPriority=0; //响应优先级 NVIC_Init(&NVIC_tim4); TIM_Cmd(TIM4, ENABLE); } //中断服务函数 void TIM4_IRQHandler(void) { TIM_ClearITPendingBit(TIM4, TIM_IT_Update); //清除更新中断 printf("1S时间到\r\n"); }
7.RTC实时时钟
7.1 简介
什么是实时时钟?实时时钟RTC是一个独立的定时器。RTC模块拥有一组连续计数的计数器,在相应软件配置下,可以供应时钟日历的功能。修改计数器的数值可以重新设置当前的时间和日期。RTC模块和时钟配置系统(RCC_BDCR寄存器)处于后备区域,即在系统复位或待机模式唤醒以后,RTC的设置和事件维持不变。RTC由自带的电源引脚VBat供电,VBat可以和蓄电池相互连接,也可以和外部的3.3V电源引脚相连接或保持断开!
PS:RTC是一个系统定时器中独立出来的设备,用于设置系统时钟,提供报警器或周期性的定时器。
7.2 STM32F4系列RTC特点
- 包含里秒、秒,分钟、小时( 12/24 小时制)、星期儿,日期、月份和年份的日历。
- 软件可编程的夏令时补偿。
- 两个具有中断功能的可编程网钟。可通过任意日历字段的组合驱动闹钟。
- 自动唤醒单元,可周期性地生成标志以触发自动唤醒中断。
- 参考时钟检测:可使用更加精确的第二时钟源(50 Hz或60 Hz)来提高日历的精确度。
- 利用亚秒级移位特性与外部时钟实现精确同步。
- 可屏蔽中断/事件:
- 一闹钟A;
- --闹钟B
- 唤醒中断
- -时间戳
- 一入侵检测
- 数字校准电路(周期性计数器调整)
- 一精度为5ppa
- -精度为0. 95 ppa,在数秒钟的校准窗口中获取
- 用于事件保存的时间戳功能( 1个事件)
- 入侵检测:
- 一2个带可能置过速器和内部上拉的入侵事件
- 20个备份寄存器80字节) .发生入侵检测事件时,将复位备份寄存器
- 复用功能输出 (RTC_OUT),可选择以下两个输出之一:
- — RTC_CALIB : 512 Hz 或 1 Hz 时钟输出( LSE 频率为 32.768 kHz) 。
可通过将 RTC_CR 寄存器中的 COE[23] 位置 1 来使能此输出。该输出可连接到器
件 RTC_AF1 功能。
— RTC_ALARM (闹钟 A 、闹钟 B 或唤醒)。
可通过配置 RTC_CR 寄存器的 OSEL[1:0] 位选择此输出。该输出可连接到器件
RTC_AF1 功能。
- RTC 复用功能输入:
— RTC_TS:时间戳事件检测。该输入可连接到器件RTC_AF1 和RTC_AF2 功能。
— RTC_TAMP1 : TAMPER1 事件检测。该输入可连接到器件 RTC_AF1 和 RTC_AF2
功能。
— RTC_TAMP2 : TAMPER2 事件检测。
— RTC_REFIN :参考时钟输入(通常为市电, 50 Hz 或 60 Hz )。
RTC框架图
7.3 RTC 初始化和配置
7.3.1 寄存器访问
RTC 寄存器为32 位寄存器。除了当BYPSHAD=0 时对日历影子寄存器执行的读访问之外,APB 接口会在访问RTC 寄存器时引入2 个等待周期。
7.3.2 寄存器写保护
系统复位后,可通过 PWR 电源控制寄存器 (PWR_CR) 的 DBP 位保护 RTC 寄存器以防止非正常的写访问。必须将 DBP 位置 1 才能使能 RTC 寄存器的写访问。
上电复位后,所有 RTC 寄存器均受到写保护。通过向写保护寄存器 (RTC_WPR) 写入一个密钥来使能对 RTC 寄存器的写操作。
要解锁所有 RTC 寄存器( RTC_ISR[13:8] 、 RTC_TAFCR 和 RTC_BKPxR 除外)的写保护,需要执行以下步骤:
1. 将“0xCA ”写入 RTC_WPR 寄存器。
2. 将“0x53 ”写入 RTC_WPR 寄存器。
写入一个错误的关键字会再次激活写保护。
保护机制不受系统复位影响
7.3.3 日历初始化和配置
要编程包括时间格式和预分频器配置在内的初始时间和日期日历值,需按照以下顺序操作:
- 将 RTC_ISR 寄存器中的 INIT 位置 1 以进入初始化模式。在此模式下,日历计数器将停 止工作并且其值可更新。
- 轮询 RTC_ISR 寄存器中的 INITF 位。当 INITF 置 1 时进入初始化阶段模式。大约需要
2 个RTCCLK 时钟周期(由于时钟同步)。
- 要为日历计数器生成 1 Hz 时钟,应首先编程 RTC_PRER 寄存器中的同步预分频系数,
然后编程异步预分频系数。即使只需要更改这两个字段中之一,也必须对RTC_PRER
寄存器执行两次单独的写访问。
- 在影子寄存器(RTC_TR 和 RTC_DR)中加载初始时间和日期值,然后通过 RTC_CR
寄存器中的FMT 位配置时间格式(12 或24 小时制)。
- 通过清零 INIT 位退出初始化模式。随后,自动加载实际日历计数器值,在 4 个 RTCCLK
时钟周期后重新开始计数。
当初始化序列完成之后,日历开始计数。
7.3.4 夏令时
可通过RTC_CR 寄存器的SUB1H、ADD1H 和BKP 位管理夏令时。 利用 SUB1H 或ADD1H,软件只需单次操作便可在日历中减去或增加一个小时,无需执行整个初始化步骤。 此外,软件还可以使用 BKP 位来记录是否曾经执行过此操作。
7.4 RTC 相关寄存器
7.4.1 RTC 时间寄存器(RTC_TR)
位 31-24 保留
位 23 保留,必须保持复位值。
位 22 PM:AM/PM 符号 (AM/PM notation)
0:AM 或24 小时制
1:PM
位 21:20 HT[1:0]:小时的十位(BCD 格式)(Hour tens in BCD format)
位 16:16 HU[3:0]:小时的个位(BCD 格式)(Hour units in BCD format)
位 15 保留,必须保持复位值。
位 14:12 MNT[2:0]:分钟的十位(BCD 格式)(Minute tens in BCD format)
位 11:8 MNU[3:0]:分钟的个位(BCD 格式)(Minute units in BCD format)
位 7 保留,必须保持复位值。
位 6:4 ST[2:0]:秒的十位(BCD 格式)(Second tens in BCD format)
位 3:0 SU[3:0]:秒的个位(BCD 格式)(Second units in BCD format)
7.4.2 RTC日期寄存器(RTC_DR)
位 31-24 保留
位 23:20 YT[3:0]:年份的十位(BCD 格式)(Year tens in BCD format)
位 19:16 YU[3:0]:年份的个位(BCD 格式)(Year units in BCD format)
位 15:13 WDU[2:0]:星期几的个位 (Week day units)
000:禁止
001:星期一
...
111:星期日
位 12 MT:月份的十位(BCD 格式)(Month tens in BCD format)
位 11:8 MU:月份的个位(BCD 格式)(Month units in BCD format)
位 7:6 保留,必须保持复位值。
位 5:4 DT[1:0]:日期的十位(BCD 格式)(Date tens in BCD format)
位 3:0 DU[3:0]:日期的个位(BCD 格式)(Date units in BCD format)
7.4.3 RTC控制寄存器
位 31:24 保留,必须保持复位值
位 23 COE:校准输出使能 (Calibration output enable)
该位使能RTC_CALIB 输出
0:禁止校准输出
1:使能校准输出
位 22:21 OSEL[1:0]:输出选择 (Output selection)
这些位用于选择要连接到RTC_ALARM 输出的标志
00:禁止输出
01:使能闹钟A 输出
10:使能闹钟B 输出
11:使能唤醒输出
位 20 POL:输出极性 (Output polarity)
该位用于配置 RTC_ALARM 输出的极性
0 :当 ALRAF/ALRBF/WUTF 置 1 时(取决于 OSEL[1:0] ),该引脚为高电平
1 :当 ALRAF/ALRBF/WUTF 置 1 时(取决于 OSEL[1:0] ),该引脚为低电平
位 19 COSEL:校准输出选择 (Calibration output selection)
当 COE=1 时,该位可选择 RTC_CALIB 上输出的信号。
0 :校准输出为 512 Hz
1 :校准输出为 1 Hz
在 RTCCLK 为 32.768 kHz 且预分频器为其默认值( PREDIV_A=127 且 PREDIV_S=255)的条件下,这些频率有效。
位 18 BKP:备份 (Backup)
用户可对此位执行写操作以记录是否已对夏令时进行更改。
位 17 SUB1H:减少 1 小时(冬季时间更改)(Subtract 1 hour (winter time change))
当该位在初始化模式以外的模式下置 1 时,如果当前小时不是 0 ,则日历时间将减少 1 小时。此位始终读为 0 。
当前小时为 0 时,将此位置 1 没有任何作用。
0 :无作用。
1 :将当前时间减少 1 小时。这可用于冬季时间更改。
位 16 ADD1H:增加 1 小时(夏季时间更改)(Add 1 hour (summer time change))
当该位在初始化模式以外的模式下置 1 时,日历时间将增加 1 小时。此位始终读为 0 。
0 :无作用。
1:将当前时间增加1 小时。这可用于夏季时间更改
位 15 TSIE:时间戳中断使能 (Timestamp interrupt enable)
0:禁止时间戳中断
1:使能时间戳中断
位 14 WUTIE:使能唤醒定时器使能 (Wakeup timer interrupt enable)
0:禁止唤醒定时器中断
1:使能唤醒定时器中断
位 13 ALRBIE:闹钟 B 中断使能 (Alarm B interrupt enable)
0:闹钟B 中断禁止
1:闹钟B 中断使能
位 12 ALRAIE:闹钟 A 中断使能 (Alarm A interrupt enable)
0:禁止闹钟A 中断
1:使能闹钟A 中断
位 11 TSE:时间戳使能 (Time stamp enable)
0:禁止时间戳
1:使能时间戳
位 10 WUTE:唤醒定时器使能 (Wakeup timer enable)
0:禁止唤醒定时器
1:使能唤醒定时器
位 9 ALRBE:闹钟 B 使能 (Alarm B enable)
0:禁止闹钟B
1:使能闹钟B
位 8 ALRAE:闹钟 A 使能 (Alarm A enable)
0:禁止闹钟A
1:使能闹钟A
位 7 DCE:粗略数字校准使能 (Coarse digital calibration enable)
0:禁止数字校准
1:使能数字校准
PREDIV_A 必须大于或等于6
位 6 FMT:小时格式 (Hour format)
0:24 小时/天格式
1:AM/PM 小时格式
位 5 BYPSHAD:旁路影子寄存器 (Bypass the shadow registers)
0 :日历值(从 RTC_SSR 、 RTC_TR 和 RTC_DR 读取时)取自影子寄存器,该影子寄存器
每两个 RTCCLK 周期更新一次。
1 :日历值(从 RTC_SSR 、 RTC_TR 和 RTC_DR 读取时)直接取自日历计数器。
注意:如果 APB1 时钟的频率低于 7 倍的 RTCCLK 频率,则必须将 BYPSHAD 置“ 1 ”
位 4 REFCKON:参考时钟检测使能(50 Hz 或 60 Hz)(Reference clock detection enable (50 or60 Hz))
0 :禁止参考时钟检测
1 :使能参考时钟检测
注意:PREDIV_S 必须为0x00FF。
位 3 TSEDGE:时间戳事件有效边沿 (Timestamp event active edge)
0 : TIMESTAMP 上升沿生成时间戳事件
1 : TIMESTAMP 下降沿生成时间戳事件
TSEDGE 发生更改时,必须复位 TSE 以避免将 TSF 意外置 1
位 2:0 WUCKSEL[2:0]:唤醒时钟选择 (Wakeup clock selection)
000:选择RTC/16 时钟
001 :选择 RTC/8 时钟
010 :选择 RTC/4 时钟
011 :选择 RTC/2 时钟
10x :选择 ck_spre 时钟(通常为 1 Hz )
11x :选择 ck_spre 时钟(通常为 1 Hz )并将 WUT 计数器值增加 2 16 (见下面的注释)
7.4.4 RTC初始化和状态寄存器(RTC_ISR)
位 31:17 保留
位 16 RECALPF:重新校准挂起标志 (Recalibration pending Flag)
当软件对 RTC_CALR 寄存器执行写操作时, RECALPF 状态标志将自动置“ 1 ”,指示
RTC_CALR 寄存器已屏蔽。当采用新的校准设置时,该位恢复为“ 0 ”。请参见 动态重校准一节。
位 15 保留,必须保持复位值。
位 14 TAMP2F:TAMPER2 检测标志 (TAMPER2 detection flag)
在入侵输入2 上检测到入侵检测事件时,由硬件将此标志置1。
该标志由软件写零清除。
位 13 TAMP1F:入侵检测标志 (Tamper detection flag)
当检测到入侵检测事件时,由硬件将此标志置1。
该标志由软件写零清除。
位 12 TSOVF:时间戳溢出标志 (Timestamp overflow flag)
当在TSF 已置1 的情况下发生时间戳事件时,由硬件将此标志置1。
该标志由软件写零清除。建议仅在TSF 位清零之后再检查并清零TSOVF 位。否则,如果时间戳事件恰好在清零TSF 位之前刚刚发生,则溢出事件可能会被漏掉。
位 11 TSF:时间戳标志 (Timestamp flag)
发生时间戳事件时,由硬件将此标志置1。
该标志由软件写零清除。
位 10 WUTF:唤醒定时器标志 (Wakeup timer flag)
当唤醒自动重载计数器计数到0 时,由硬件将此标志置1。
该标志由软件写零清除。
软件必须在 WUTF 再次置 1 的 1.5 个 RTCCLK 周期之前将该标志清零。
位 9 ALRBF:闹钟 B 标志 (Alarm B flag)
当时间 / 日期寄存器( RTC_TR 和 RTC_DR )与闹钟 B 寄存器 (RTC_ALRMBR) 匹配时,由硬件将该标志置 1 。
该标志由软件写零清除。
位 8 ALRAF:闹钟 A 标志 (Alarm A flag)
当时间 / 日期寄存器( RTC_TR 和 RTC_DR )与闹钟 A 寄存器 (RTC_ALRMAR) 匹配时,由硬件将该标志置 1 。
该标志由软件写零清除。
位 7 INIT:初始化模式 (Initialization mode)
0:自由运行模式。
1 :初始化模式,用于编程时间和日期寄存器( RTC_TR 和 RTC_DR )以及预分频器寄存器(RTC_PRER) 。计数器停止计数,当 INIT 被复位后,计数器从新值开始计数。
位 6 INITF:初始化标志 (Initialization flag)
当此位置1 时,RTC 处于初始化状态,此时可更新事件、日期和预分频器寄存器。
0:不允许更新日历寄存器。
1:允许更新日历寄存器。
位 5 RSF:寄存器同步标志 (Registers synchronization flag)
每次将日历寄存器的值复制到影子寄存器( RTC_SSRx 、 RTC_TRx 和 RTC_DRx )时,都会由硬件将此位置 1 。在初始化模式下、平移操作挂起时 (SHPF=1) 或在旁路影子寄存器模式 (BYPSHAD=1) 下,该位由硬件清零。该位还可由软件清零。
0 :日历影子寄存器尚未同步
1 :日历影子寄存器已同步
位 4 INITS:初始化状态标志 (Initialization status flag)
当日历年份字段不为0 时(上电复位状态),由硬件将该位置1。
0:日历尚未初始化
1:日历已经初始化
位 3 SHPF:平移操作挂起 (Shift operation pending)
0:没有平移操作挂起
1:某个平移操作挂起
只要通过对 RTC_SHIFTR 寄存器执行写操作来启动平移操作,此标志便由硬件置 1 。执行完相应的平移操作后,此标志由硬件清零。对 SHPF 执行写入操作不起作用。
位 2 WUTWF:唤醒定时器写标志 (Wakeup timer write flag)
在 RTC_CR 寄存器中的 WUTE 位置 0 后,当唤醒定时器值可更改时,由硬件将该位置 1 。
0 :不允许更新唤醒定时器配置
1 :允许更新唤醒定时器配置
位 1 ALRBWF:闹钟 B 写标志 (Alarm B write flag)
在 RTC_CR 寄存器中的 ALRBIE 位置 0 之后,当闹钟 B 的值可更改时,由硬件将该位置 1 。
该位在初始化模式下由硬件清零。
0 :不允许更新闹钟 B
1 :允许更新闹钟 B
位 0 ALRAWF:闹钟 A 写标志 (Alarm A write flag)
在 RTC_CR 寄存器中的 ALRAE 位置 0 后,当闹钟 A 的值可更改时,由硬件将该位置 1 。
该位在初始化模式下由硬件清零。
0 :不允许更新闹钟 A
1 :允许更新闹钟 A
7.4.5 RTC预分频寄存器(TRC_PRER)
位 31:24 保留
位 23 保留,必须保持复位值。
位 22:16 PREDIV_A[6:0]:异步预分频系数 (Asynchronous prescaler factor)
下面是异步分频系数的公式:
ck_apre 频率 = RTCCLK 频率 /(PREDIV_A+1)
注意: PREDIV_A [6:0]= 000000 为禁用值。
位 15 保留,必须保持复位值。
位 14:0 PREDIV_S[14:0]:同步预分频系数 (Synchronous prescaler factor)
下面是同步分频系数的公式:
ck_spre 频率= ck_apre 频率/(PREDIV_S+1)
7.4.6 RTC唤醒定时器寄存器(RTC_WUTR)
位 31:16 保留
位 15:0 WUT[15:0]:唤醒自动重载值位 (Wakeup auto-reload value bit)
当使能唤醒定时器时( WUTE 置 1 ),每 (WUT[15:0] + 1) 个 ck_wut 周期将 WUTF 标志置 1
一次。 ck_wut 周期通过 RTC_CR 寄存器的 WUCKSEL[2:0] 位进行选择。
当 WUCKSEL[2] = 1 时,唤醒定时器变为 17 位, WUCKSEL[1] 等效为 WUT[16] ,即要重载到定时器的最高有效位。
注意: WUTF 第一次置 1 发生在 WUTE 置 1 之后 (WUT+1) 个 ck_wut 周期。禁止在
WUCKSEL[2:0]=011(RTCCLK/2) 时将 WUT[15:0] 设置为 0x0000 。
7.4.7 RTC校准寄存器(RTC_CALIBR)
位 31:8 保留
位 7 DCS:数字校准符号 (Digital calibration sign)
0:正校准:增加日历更新频率
1:负校准:降低日历更新频率
位 6:5 保留,必须保持复位值。
位 4:0 DC[4:0]:数字校准 (Digital calibration)
DCS = 0 (正校准)
00000 : + 0 ppm
00001 : + 4 ppm (舍入值)
00010 : + 8 ppm (舍入值)
..
11111 : + 126 ppm (舍入值)
DCS = 1 (负校准)
00000 : 0 ppm
00001 : 2 ppm (舍入值)
00010 : 4 ppm (舍入值)
..
11111 : 63 ppm (舍入值)
7.4.8 RTC闹钟A寄存器(RTC_ALRMAR)
位 31 MSK4:闹钟 A 日期掩码 (Alarm A date mask)
0 :如果日期 / 日匹配,则闹钟 A 置 1
1 :在闹钟 A 比较中,日期 / 日无关
位 30 WDSEL:星期几选择 (Week day selection)
0:DU[3:0] 代表日期的个位
1 : DU[3:0] 代表星期几。 DT[1:0] 为无关位。
位 29:28 DT[1:0]:日期的十位(BCD 格式)(Date tens in BCD format)。
位 27:24 DU[3:0]:日期的个位或日(BCD 格式)(Date units or day in BCD format)。
位 23 MSK3:闹钟 A 小时掩码 (Alarm A hours mask)
0:如果小时匹配,则闹钟A 置1
1:在闹钟A 比较中,小时无关
位 22 PM:AM/PM 符号 (AM/PM notation)
0 : AM 或 24 小时制
1 : PM
位 21:20 HT[1:0]:小时的十位(BCD 格式)(Hour tens in BCD format)。
位 19:16 HU[3:0]:小时的个位(BCD 格式)(Hour units in BCD format)。
位 15 MSK2:闹钟 A 分钟掩码 (Alarm A minutes mask)
0:如果分钟匹配,则闹钟A 置1
1:在闹钟A 比较中,分钟无关
位 14:12 MNT[2:0]:分钟的十位(BCD 格式)(Minute tens in BCD format)。
位 11:8 MNU[3:0]:分钟的个位(BCD 格式)(Minute units in BCD format)。
位 7 MSK1:闹钟 A 秒掩码 (Alarm A seconds mask)
0:如果秒匹配,则闹钟A 置1
1:在闹钟A 比较中,秒无关
位 6:4 ST[2:0]:秒的十位(BCD 格式)(Second tens in BCD format)。
位 3:0 SU[3:0]:秒的个位(BCD 格式)(Second units in BCD format)
7.4.9 RTC闹钟B寄存器(RTC_ALRMBR)
位 31 MSK4:闹钟 B 日期掩码 (Alarm B date mask)
0:如果日期和日匹配,则闹钟B 置1
1:在闹钟B 比较中,日期和日无关
位 30 WDSEL:星期几选择 (Week day selection)
0:DU[3:0] 代表日期的个位。
1:DU[3:0] 代表星期几。DT[1:0] 为无关位。
位 29:28 DT[1:0]:日期的十位(BCD 格式)(Date tens in BCD format)
位 27:24 DU[3:0]:日期个位或日(BCD 格式)(Date units or day in BCD format)
位 23 MSK3:闹钟 B 小时掩码 (Alarm B hours mask)
0:如果小时匹配,则闹钟B 置1
1:在闹钟B 比较中,小时无关
位 22 PM:AM/PM 符号 (AM/PM notation)
0:AM 或24 小时制
1:PM
位 21:20 HT[1:0]:小时的十位(BCD 格式)(Hour tens in BCD format)
位 19:16 HU[3:0]:小时的个位(BCD 格式)(Hour units in BCD format)
位 15 MSK2:闹钟 B 分钟掩码 (Alarm B minutes mask)
0:如果分钟匹配,则闹钟B 置1
1:在闹钟B 比较中,分钟无关
位 14:12 MNT[2:0]:分钟的十位(BCD 格式)(Minute tens in BCD format)
位 11:8 MNU[3:0]:分钟的个位(BCD 格式)(Minute units in BCD format)
位 7 MSK1:闹钟 B 秒掩码 (Alarm B seconds mask)
0:如果秒匹配,则闹钟B 置1
1:在闹钟B 比较中,秒无关
位 6:4 ST[2:0]:秒的十位(BCD 格式)(Second tens in BCD format)
位 3:0 SU[3:0]:秒的个位(BCD 格式)(Second units in BCD format)
7.4.10 RTC写保护寄存器(RTC_WPR)
上电后,所有 RTC 寄存器都受到写保护( RTC_ISR[13:8]、 RTC_TAFCR 和 RTC_BKPxR 除外),必须依次写入: 0XCA、 0X53 两关键字到 RTC_WPR 寄存 器,才可以解锁。
位 31:8 保留,必须保持复位值。
位 7:0 KEY:写保护关键字 (Write protection key)
可通过软件对该字节执行写操作。
读取该字节时,始终返回0x00。
7.5 实例代码(初始化时间和日期)
#include "rtc.h" // Device header #include "stdio.h" void RTC_Time_Init(u16 Year, u16 month, u16 day,u16 hour,u16 minute,u16 second,u16 WeekDay) { RTC_InitTypeDef rtc; RTC_TimeTypeDef rtcTime; RTC_DateTypeDef rtcDate; RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE); //PWR控制写保护的电源/备份区电源 PWR_BackupAccessCmd(ENABLE); //使能PWR备份域电源 PWR_BackupRegulatorCmd(ENABLE); //使能RTC备份寄存器 //1、选择RTC时钟源 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //RTC选择LSE外部低速时钟 RCC_RTCCLKCmd(ENABLE); //使能RTC时钟 RCC_LSEConfig(RCC_LSE_ON); //打开LSE时钟 while(!(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==SET)); //等待LSE时钟精密校准完成 while(!(RTC_WaitForSynchro() == SUCCESS)); //等待LSE时钟和RTC同步完成 RTC_WriteProtectionCmd(DISABLE); //写DISABLE,是失能写保护功能 while(!(RTC_EnterInitMode() == SUCCESS) ); //等待进入初始化模式完成 //初始化RTC rtc.RTC_AsynchPrediv= 127; //异步,寄存器已经+1 rtc.RTC_HourFormat=RTC_HourFormat_24; //24小时制 rtc.RTC_SynchPrediv=255; //同步,寄存器已经+1 RTC_Init(&rtc); //初始化RTC //设置时间 rtcTime.RTC_Hours=hour; //时 rtcTime.RTC_Minutes=minute; //分 rtcTime.RTC_Seconds=second; //秒 RTC_SetTime(RTC_Format_BIN, &rtcTime); //设置日期 rtcDate.RTC_Year=Year; //年 rtcDate.RTC_Month=month; //月 rtcDate.RTC_Date=day; //日 rtcDate.RTC_WeekDay=WeekDay; //星期 RTC_SetDate(RTC_Format_BIN, &rtcDate); RTC_WriteProtectionCmd(ENABLE); //开启写保护功能 }
7.6 代码实现(RTC备份区--复位不修改时间)
#include "rtc.h" // Device header #include "stdio.h" void RTC_Time_Init(u16 Year, u16 month, u16 day,u16 hour,u16 minute,u16 second,u16 WeekDay) { RTC_InitTypeDef rtc; RTC_TimeTypeDef rtcTime; RTC_DateTypeDef rtcDate; RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE); //PWR控制写保护的电源/备份区电源 PWR_BackupAccessCmd(ENABLE); //使能PWR备份域电源 PWR_BackupRegulatorCmd(ENABLE); //使能RTC备份寄存器 //1、选择RTC时钟源为LSE RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //RTC选择LSE外部低速时钟 RCC_RTCCLKCmd(ENABLE); //使能RTC时钟 //2、打开LSE时钟 RCC_LSEConfig(RCC_LSE_ON); while(!(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==SET)); //等待LSE时钟校准完成 while(!(RTC_WaitForSynchro() == SUCCESS)); //等待LSE时钟和RTC进行同步完成 RTC_WriteProtectionCmd(DISABLE); //写DISABLE,是失能写保护功能 if(RTC_ReadBackupRegister(RTC_BKP_DR0)!=0xaa) //读备份区,判断是否初始化过 { while(!(RTC_EnterInitMode() == SUCCESS) ); //使能初始化之前,必须先关闭写保护,等待进入初始化模式完成 //初始化RTC rtc.RTC_AsynchPrediv= 127; //异步,寄存器已经+1 rtc.RTC_HourFormat=RTC_HourFormat_24; //24小时制 rtc.RTC_SynchPrediv=255; //同步,寄存器已经+1 RTC_Init(&rtc); //初始化RTC //设置时间 rtcTime.RTC_Hours=hour; //时 rtcTime.RTC_Minutes=minute; //分 rtcTime.RTC_Seconds=second; //秒 RTC_SetTime(RTC_Format_BIN, &rtcTime); //设置日期 rtcDate.RTC_Year=Year; //年 rtcDate.RTC_Month=month; //月 rtcDate.RTC_Date=day; //日 rtcDate.RTC_WeekDay=WeekDay; //星期 RTC_SetDate(RTC_Format_BIN, &rtcDate); RTC_WriteBackupRegister(RTC_BKP_DR0, 0xaa); //写入备份区0xaa,记录已经初始化化过一次了 } RTC_WriteProtectionCmd(ENABLE); //开启写保护功能 }
复位后时间没有改变的;
7.7 代码实现(LCD显示+动态修改RTC时间日期)
#include "rtc.h" // Device header #include "stdio.h" void RTC_Time_Init(u16 Year, u16 month, u16 day,u16 hour,u16 minute,u16 second,u16 WeekDay) { RTC_InitTypeDef rtc; RTC_TimeTypeDef rtcTime; RTC_DateTypeDef rtcDate; RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE); //PWR控制写保护的电源/备份区电源 PWR_BackupAccessCmd(ENABLE); //使能PWR备份域电源 PWR_BackupRegulatorCmd(ENABLE); //使能RTC备份寄存器 //1、选择RTC时钟源为LSE RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //RTC选择LSE外部低速时钟 RCC_RTCCLKCmd(ENABLE); //使能RTC时钟 //2、打开LSE时钟 RCC_LSEConfig(RCC_LSE_ON); while(!(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==SET)); //等待LSE时钟校准完成 while(!(RTC_WaitForSynchro() == SUCCESS)); //等待LSE时钟和RTC进行同步完成 RTC_WriteProtectionCmd(DISABLE); //写DISABLE,是失能写保护功能 if(RTC_ReadBackupRegister(RTC_BKP_DR0)!=0xaa) //读备份区,判断是否初始化过 { while(!(RTC_EnterInitMode() == SUCCESS) ); //使能初始化之前,必须先关闭写保护,等待进入初始化模式完成 //初始化RTC rtc.RTC_AsynchPrediv= 127; //异步,寄存器已经+1 rtc.RTC_HourFormat=RTC_HourFormat_24; //24小时制 rtc.RTC_SynchPrediv=255; //同步,寄存器已经+1 RTC_Init(&rtc); //初始化RTC //设置时间 rtcTime.RTC_Hours=hour; //时 rtcTime.RTC_Minutes=minute; //分 rtcTime.RTC_Seconds=second; //秒 RTC_SetTime(RTC_Format_BIN, &rtcTime); //设置日期 rtcDate.RTC_Year=Year; //年 rtcDate.RTC_Month=month; //月 rtcDate.RTC_Date=day; //日 rtcDate.RTC_WeekDay=WeekDay; //星期 RTC_SetDate(RTC_Format_BIN, &rtcDate); RTC_WriteBackupRegister(RTC_BKP_DR0, 0xaa); //写入备份区0xaa,记录已经初始化化过一次了 } RTC_WriteProtectionCmd(ENABLE); //开启写保护功能 } void RTC_Set_time(u16 hour,u16 minute,u16 second) { RTC_TimeTypeDef rtcTime; RTC_WriteProtectionCmd(DISABLE); //写DISABLE,是失能写保护功能 while(!(RTC_EnterInitMode() == SUCCESS) ); //使能初始化之前,必须先关闭写保护,等待进入初始化模式完成 //设置时间 rtcTime.RTC_Hours=hour; //时 rtcTime.RTC_Minutes=minute; //分 rtcTime.RTC_Seconds=second; //秒 RTC_SetTime(RTC_Format_BIN, &rtcTime); RTC_WriteProtectionCmd(ENABLE); //开启写保护功能 } void RTC_Set_date(u16 Year, u16 month, u16 day,u16 WeekDay) { RTC_DateTypeDef rtcDate; RTC_WriteProtectionCmd(DISABLE); //写DISABLE,是失能写保护功能 while(!(RTC_EnterInitMode() == SUCCESS) ); //使能初始化之前,必须先关闭写保护,等待进入初始化模式完成 rtcDate.RTC_Year=Year; //年 rtcDate.RTC_Month=month; //月 rtcDate.RTC_Date=day; //日 rtcDate.RTC_WeekDay=WeekDay; //星期 RTC_SetDate(RTC_Format_BIN, &rtcDate); RTC_WriteProtectionCmd(ENABLE); //开启写保护功能 }