实时时钟(RTC)
小容量产品是指闪存存储器容量在16K至32K字节之间的STM32F101xx、STM32F102xx和STM32F103xx微控制器。
中容量产品是指闪存存储器容量在64K至128K字节之间的STM32F101xx、STM32F102xx和STM32F103xx微控制器。
大容量产品是指闪存存储器容量在256K至512K字节之间的STM32F101xx和STM32F103xx微控制器。
互联型产品是指STM32F105xx和STM32F107xx微控制器。
主要特性
● 可编程的预分频系数:分频系数最高为20 。
● 32位的可编程计数器,可用于较长时间段的测量。
● 2个分离的时钟:用于APB1接口的PCLK1和RTC时钟(RTC时钟的频率必须小于PCLK1时钟频率的四分之一以上)。
● 可以选择以下三种RTC的时钟源:
─ HSE时钟除以128;
─ LSE振荡器时钟;
─ LSI振荡器时钟
● 2个独立的复位类型:
─ APB1接口由系统复位;
─ RTC核心(预分频器、闹钟、计数器和分频器)只能由后备域复位。
● 3个专门的可屏蔽中断:
─ 闹钟中断,用来产生一个软件可编程的闹钟中断。
─ 秒中断,用来产生一个可编程的周期性中断信号(最长可达1秒)。
─ 溢出中断,指示内部可编程计数器溢出并回转为0的状态。
STM32 RTC 时钟简介
STM32 的实时时钟(RTC)是一个独立的定时器。STM32 的 RTC 模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。
RTC 模块和时钟配置系统(RCC_BDCR 寄存器)是在后备区域,即在系统复位或从待机模式唤醒后 RTC 的设置和时间维持不变。但是在系统复位后,会自动禁止访问后备寄存器和 RTC,以防止对后备区域(BKP)的意外写操作。所以在要设置时间之前, 先要取消备份区域(BKP)写保护。
RTC 由两个主要部分组成(参见上图 ),第一部分(APB1 接口)用来和 APB1 总线相连。此单元还包含一组 16 位寄存器,可通过 APB1 总线对其进行读写操作。APB1 接口由 APB1 总线时钟驱动,用来与 APB1 总线连接。
另一部分(RTC 核心)由一组可编程计数器组成,分成两个主要模块。第一个模块是 RTC 的预分频模块,它可编程产生 1 秒的 RTC 时间基准 TR_CLK。RTC 的预分频模块包含了一个 20位的可编程分频器(RTC 预分频器)。如果在 RTC_CR 寄存器中设置了相应的允许位,则在每个TR_CLK 周期中 RTC 产生一个中断(秒中断)。第二个模块是一个 32 位的可编程计数器,可被初始化为当前的系统时间,一个 32 位的时钟计数器,按秒钟计算,可以记录 4294967296 秒,约合 136 年左右,作为一般应用,这已经是足够了的。
复位过程
除了RTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV寄存器外,所有的系统寄存器都由系统复位或电源复位进行异步复位。RTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV寄存器仅能通过备份域复位信号复位。
读RTC寄存器
RTC核完全独立于RTC APB1接口。
软件通过APB1接口访问RTC的预分频值 、 计数器值和闹钟值。但是,相关的可读寄存器只在与RTC APB1时钟进行重新同步的RTC时钟的上升沿被更新。RTC标志也是如此的。
这意味着,如果APB1接口曾经被关闭,而读操作又是在刚刚重新开启APB1之后,则在第一次的内部寄存器更新之前,从APB1上读出的RTC寄存器数值可能被破坏了(通常读到0)。下述几种
情况下能够发生这种情形:
● 发生系统复位或电源复位。
● 系统刚从待机模式唤醒。
4.3 ● 系统刚从停机模式唤醒。
所有以上情况中,APB1接口被禁止时(复位、无时钟或断电)RTC核仍保持运行状态。
因此,若在读取RTC寄存器时,RTC的APB1接口曾经处于禁止状态,则软件首先必须等待RTC_CRL寄存器中的RSF位(寄存器同步标志)被硬件置’1’。
注: RTC 的 APB1 接口不受 WFI 和 WFE 等低功耗模式的影响。
配置RTC寄存器
必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入RTC_PRL、RTC_CNT、RTC_ALR寄存器。
另外,对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行。可以通过查询RTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新中。仅当RTOFF状态位是’1’时,才可以写入RTC寄存器。
配置过程: 配置过程:
查询RTOFF位,直到RTOFF的值变为’1’
置CNF值为1,进入配置模式
对一个或多个RTC寄存器进行写操作
清除CNF标志位,退出配置模式
查询RTOFF,直至RTOFF位变为’1’以确认写操作已经完成。
仅当CNF标志位被清除时,写操作才能进行,这个过程至少需要3个RTCCLK周期。
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计数器。
RTC 正常工作的一般配置步骤
1. 使能BPK PWR时钟、中断初始化
//必须先使能电源时钟和备份区域时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
//中断初始化
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel =RTC_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
2. 取消备份区写保护
PWR_BackupAccessCmd(ENABLE); //使能 RTC 和后备寄存器访问
3. 复位备份区域,开启外部低速振荡器
BKP_DeInit();//复位备份区域
RCC_LSEConfig(RCC_LSE_ON);//开启外部低速振荡器
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);//检查指定的 RCC 标志位设置与否,等待低速晶振就绪
4. 配置RCT时钟源
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //选择 LSE 作为 RTC 时钟
RCC_RTCCLKCmd(ENABLE); //使能 RTC 时钟
RTC_WaitForLastTask(); //等待最近一次对 RTC 寄存器的写操作完成
RTC_WaitForSynchro(); //等待 RTC 寄存器同步
RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能 RTC 秒中断
RTC_WaitForLastTask(); //等待最近一次对 RTC 寄存器的写操作完成
5. 设置 RTC 的分频,以及配置 RTC 时钟
RTC_EnterConfigMode();/// 允许配置
RTC_SetPrescaler(32767);//设置 RTC 时钟分频数 晶振32.768KHz
RTC_ITConfig(RTC_IT_SEC,ENABLE); //使能 RTC 秒中断
RTC_SetCounter(0);//最后在配置完成之后
6. 更新配置,设置RTC中断分组
RTC_ExitConfigMode();//退出配置模式,更新配置
//往备份区域写用户数据
void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data);
//读取备份区域指定寄存器的用户数据
BKP_ReadBackupRegister(uint16_t BKP_DR);
7. 编写中断服务函数
注:中断标志
RTC_FLAG_RTOFF RTC 操作 OFF 标志位
RTC_FLAG_RSF 寄存器已同步标志位
RTC_FLAG_OW 溢出中断标志位
RTC_FLAG_ALR 闹钟中断标志位
RTC_FLAG_SEC 秒中断标志位
void RTC_IRQHandler(void)
{
if (RTC_GetITStatus(RTC_IT_SEC) != RESET) //秒钟中断
{
data++;
printf(“time:%dt”,data);
}
RTC_ClearITPendingBit(RTC_IT_SEC); //清中断
RTC_WaitForLastTask();
}
完整程序
#include “stm32f10x.h”
#include “stdio.h”
int fputc(int ch, FILE *f)
{
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
USART_SendData(USART1,(uint8_t)ch);
return ch;
}
void delay_ms(u16 time)
{
u16 i = 0;
while(time--)
{
i = 12000;
while(i--);
}
}
u16 data = 0;
void Usart_Init()
{
GPIO_InitTypeDef GPIO_ITDef1;
GPIO_InitTypeDef GPIO_ITDef;
USART_InitTypeDef USART_ITDef;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
//挂载时钟(复用PA) 串口时钟使能,GPIO 时钟使能,复用时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
//PA9 TXD初始化
GPIO_ITDef.GPIO_Pin = GPIO_Pin_9;//PA9 TXD
GPIO_ITDef.GPIO_Mode = GPIO_Mode_AF_PP;复用推挽输出
GPIO_ITDef.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_ITDef);
//PA10 TXD初始化
GPIO_ITDef1.GPIO_Pin = GPIO_Pin_10;//PA10 RXD
GPIO_ITDef1.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA,&GPIO_ITDef1);
//USART初始化
USART_ITDef.USART_BaudRate = 115200;//波特率
USART_ITDef.USART_WordLength = USART_WordLength_8b;//发送数据长度
USART_ITDef.USART_StopBits = USART_StopBits_1; //一个停止位
USART_ITDef.USART_Parity = USART_Parity_No; //无奇偶校验位
USART_ITDef.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_ITDef.USART_Mode = USART_Mode_Tx| USART_Mode_Rx ;//发送模式
USART_Init(USART1,&USART_ITDef);
USART_Cmd(USART1, ENABLE);//使能串口
}
void RTC_Init(void)
{
//1.使能BPK PWR时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel =RTC_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
//2.取消备份区写保护
PWR_BackupAccessCmd(ENABLE); //使能 RTC 和后备寄存器访问
//3.复位备份区域,开启外部低速振荡器
BKP_DeInit();//复位备份区域
RCC_LSEConfig(RCC_LSE_ON);//开启外部低速振荡器
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);//检查指定的 RCC 标志位设置与否,等待低速晶振就绪
//4.配置RCT时钟源
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //选择 LSE 作为 RTC 时钟
RCC_RTCCLKCmd(ENABLE); //使能 RTC 时钟
RCC_RTCCLKCmd(ENABLE); //使能 RTC 时钟
RTC_WaitForLastTask(); //等待最近一次对 RTC 寄存器的写操作完成
RTC_WaitForSynchro(); //等待 RTC 寄存器同步
RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能 RTC 秒中断
RTC_WaitForLastTask(); //等待最近一次对 RTC 寄存器的写操作完成
//5.设置 RTC 的分频,以及配置 RTC 时钟
RTC_EnterConfigMode();/// 允许配置
RTC_SetPrescaler(32767);//设置 RTC 时钟分频数 晶振32.768KHz
RTC_ITConfig(RTC_IT_SEC,ENABLE); //使能 RTC 秒中断
RTC_SetCounter(0);//最后在配置完成之后
//6.更新配置,设置RTC中断分组。
RTC_ExitConfigMode();//退出配置模式,更新配置
}
int main(void)
{
Usart_Init();
RTC_Init();
while(1)
{
;
}
}
//每秒触发一次
void RTC_IRQHandler(void)
{
if (RTC_GetITStatus(RTC_IT_SEC) != RESET) //秒钟中断
{
data++;//每一秒+1
printf(“time:%dt”,data);//串口打印当前时间值
}
RTC_ClearITPendingBit(RTC_IT_SEC); //清中断
RTC_WaitForLastTask();
}
实时时钟(RTC)
小容量产品是指闪存存储器容量在16K至32K字节之间的STM32F101xx、STM32F102xx和STM32F103xx微控制器。
中容量产品是指闪存存储器容量在64K至128K字节之间的STM32F101xx、STM32F102xx和STM32F103xx微控制器。
大容量产品是指闪存存储器容量在256K至512K字节之间的STM32F101xx和STM32F103xx微控制器。
互联型产品是指STM32F105xx和STM32F107xx微控制器。
主要特性
● 可编程的预分频系数:分频系数最高为20 。
● 32位的可编程计数器,可用于较长时间段的测量。
● 2个分离的时钟:用于APB1接口的PCLK1和RTC时钟(RTC时钟的频率必须小于PCLK1时钟频率的四分之一以上)。
● 可以选择以下三种RTC的时钟源:
─ HSE时钟除以128;
─ LSE振荡器时钟;
─ LSI振荡器时钟
● 2个独立的复位类型:
─ APB1接口由系统复位;
─ RTC核心(预分频器、闹钟、计数器和分频器)只能由后备域复位。
● 3个专门的可屏蔽中断:
─ 闹钟中断,用来产生一个软件可编程的闹钟中断。
─ 秒中断,用来产生一个可编程的周期性中断信号(最长可达1秒)。
─ 溢出中断,指示内部可编程计数器溢出并回转为0的状态。
STM32 RTC 时钟简介
STM32 的实时时钟(RTC)是一个独立的定时器。STM32 的 RTC 模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。
RTC 模块和时钟配置系统(RCC_BDCR 寄存器)是在后备区域,即在系统复位或从待机模式唤醒后 RTC 的设置和时间维持不变。但是在系统复位后,会自动禁止访问后备寄存器和 RTC,以防止对后备区域(BKP)的意外写操作。所以在要设置时间之前, 先要取消备份区域(BKP)写保护。
RTC 由两个主要部分组成(参见上图 ),第一部分(APB1 接口)用来和 APB1 总线相连。此单元还包含一组 16 位寄存器,可通过 APB1 总线对其进行读写操作。APB1 接口由 APB1 总线时钟驱动,用来与 APB1 总线连接。
另一部分(RTC 核心)由一组可编程计数器组成,分成两个主要模块。第一个模块是 RTC 的预分频模块,它可编程产生 1 秒的 RTC 时间基准 TR_CLK。RTC 的预分频模块包含了一个 20位的可编程分频器(RTC 预分频器)。如果在 RTC_CR 寄存器中设置了相应的允许位,则在每个TR_CLK 周期中 RTC 产生一个中断(秒中断)。第二个模块是一个 32 位的可编程计数器,可被初始化为当前的系统时间,一个 32 位的时钟计数器,按秒钟计算,可以记录 4294967296 秒,约合 136 年左右,作为一般应用,这已经是足够了的。
复位过程
除了RTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV寄存器外,所有的系统寄存器都由系统复位或电源复位进行异步复位。RTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV寄存器仅能通过备份域复位信号复位。
读RTC寄存器
RTC核完全独立于RTC APB1接口。
软件通过APB1接口访问RTC的预分频值 、 计数器值和闹钟值。但是,相关的可读寄存器只在与RTC APB1时钟进行重新同步的RTC时钟的上升沿被更新。RTC标志也是如此的。
这意味着,如果APB1接口曾经被关闭,而读操作又是在刚刚重新开启APB1之后,则在第一次的内部寄存器更新之前,从APB1上读出的RTC寄存器数值可能被破坏了(通常读到0)。下述几种
情况下能够发生这种情形:
● 发生系统复位或电源复位。
● 系统刚从待机模式唤醒。
4.3 ● 系统刚从停机模式唤醒。
所有以上情况中,APB1接口被禁止时(复位、无时钟或断电)RTC核仍保持运行状态。
因此,若在读取RTC寄存器时,RTC的APB1接口曾经处于禁止状态,则软件首先必须等待RTC_CRL寄存器中的RSF位(寄存器同步标志)被硬件置’1’。
注: RTC 的 APB1 接口不受 WFI 和 WFE 等低功耗模式的影响。
配置RTC寄存器
必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入RTC_PRL、RTC_CNT、RTC_ALR寄存器。
另外,对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行。可以通过查询RTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新中。仅当RTOFF状态位是’1’时,才可以写入RTC寄存器。
配置过程: 配置过程:
查询RTOFF位,直到RTOFF的值变为’1’
置CNF值为1,进入配置模式
对一个或多个RTC寄存器进行写操作
清除CNF标志位,退出配置模式
查询RTOFF,直至RTOFF位变为’1’以确认写操作已经完成。
仅当CNF标志位被清除时,写操作才能进行,这个过程至少需要3个RTCCLK周期。
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计数器。
RTC 正常工作的一般配置步骤
1. 使能BPK PWR时钟、中断初始化
//必须先使能电源时钟和备份区域时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
//中断初始化
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel =RTC_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
2. 取消备份区写保护
PWR_BackupAccessCmd(ENABLE); //使能 RTC 和后备寄存器访问
3. 复位备份区域,开启外部低速振荡器
BKP_DeInit();//复位备份区域
RCC_LSEConfig(RCC_LSE_ON);//开启外部低速振荡器
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);//检查指定的 RCC 标志位设置与否,等待低速晶振就绪
4. 配置RCT时钟源
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //选择 LSE 作为 RTC 时钟
RCC_RTCCLKCmd(ENABLE); //使能 RTC 时钟
RTC_WaitForLastTask(); //等待最近一次对 RTC 寄存器的写操作完成
RTC_WaitForSynchro(); //等待 RTC 寄存器同步
RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能 RTC 秒中断
RTC_WaitForLastTask(); //等待最近一次对 RTC 寄存器的写操作完成
5. 设置 RTC 的分频,以及配置 RTC 时钟
RTC_EnterConfigMode();/// 允许配置
RTC_SetPrescaler(32767);//设置 RTC 时钟分频数 晶振32.768KHz
RTC_ITConfig(RTC_IT_SEC,ENABLE); //使能 RTC 秒中断
RTC_SetCounter(0);//最后在配置完成之后
6. 更新配置,设置RTC中断分组
RTC_ExitConfigMode();//退出配置模式,更新配置
//往备份区域写用户数据
void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data);
//读取备份区域指定寄存器的用户数据
BKP_ReadBackupRegister(uint16_t BKP_DR);
7. 编写中断服务函数
注:中断标志
RTC_FLAG_RTOFF RTC 操作 OFF 标志位
RTC_FLAG_RSF 寄存器已同步标志位
RTC_FLAG_OW 溢出中断标志位
RTC_FLAG_ALR 闹钟中断标志位
RTC_FLAG_SEC 秒中断标志位
void RTC_IRQHandler(void)
{
if (RTC_GetITStatus(RTC_IT_SEC) != RESET) //秒钟中断
{
data++;
printf(“time:%dt”,data);
}
RTC_ClearITPendingBit(RTC_IT_SEC); //清中断
RTC_WaitForLastTask();
}
完整程序
#include “stm32f10x.h”
#include “stdio.h”
int fputc(int ch, FILE *f)
{
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
USART_SendData(USART1,(uint8_t)ch);
return ch;
}
void delay_ms(u16 time)
{
u16 i = 0;
while(time--)
{
i = 12000;
while(i--);
}
}
u16 data = 0;
void Usart_Init()
{
GPIO_InitTypeDef GPIO_ITDef1;
GPIO_InitTypeDef GPIO_ITDef;
USART_InitTypeDef USART_ITDef;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
//挂载时钟(复用PA) 串口时钟使能,GPIO 时钟使能,复用时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
//PA9 TXD初始化
GPIO_ITDef.GPIO_Pin = GPIO_Pin_9;//PA9 TXD
GPIO_ITDef.GPIO_Mode = GPIO_Mode_AF_PP;复用推挽输出
GPIO_ITDef.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_ITDef);
//PA10 TXD初始化
GPIO_ITDef1.GPIO_Pin = GPIO_Pin_10;//PA10 RXD
GPIO_ITDef1.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA,&GPIO_ITDef1);
//USART初始化
USART_ITDef.USART_BaudRate = 115200;//波特率
USART_ITDef.USART_WordLength = USART_WordLength_8b;//发送数据长度
USART_ITDef.USART_StopBits = USART_StopBits_1; //一个停止位
USART_ITDef.USART_Parity = USART_Parity_No; //无奇偶校验位
USART_ITDef.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_ITDef.USART_Mode = USART_Mode_Tx| USART_Mode_Rx ;//发送模式
USART_Init(USART1,&USART_ITDef);
USART_Cmd(USART1, ENABLE);//使能串口
}
void RTC_Init(void)
{
//1.使能BPK PWR时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel =RTC_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
//2.取消备份区写保护
PWR_BackupAccessCmd(ENABLE); //使能 RTC 和后备寄存器访问
//3.复位备份区域,开启外部低速振荡器
BKP_DeInit();//复位备份区域
RCC_LSEConfig(RCC_LSE_ON);//开启外部低速振荡器
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);//检查指定的 RCC 标志位设置与否,等待低速晶振就绪
//4.配置RCT时钟源
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //选择 LSE 作为 RTC 时钟
RCC_RTCCLKCmd(ENABLE); //使能 RTC 时钟
RCC_RTCCLKCmd(ENABLE); //使能 RTC 时钟
RTC_WaitForLastTask(); //等待最近一次对 RTC 寄存器的写操作完成
RTC_WaitForSynchro(); //等待 RTC 寄存器同步
RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能 RTC 秒中断
RTC_WaitForLastTask(); //等待最近一次对 RTC 寄存器的写操作完成
//5.设置 RTC 的分频,以及配置 RTC 时钟
RTC_EnterConfigMode();/// 允许配置
RTC_SetPrescaler(32767);//设置 RTC 时钟分频数 晶振32.768KHz
RTC_ITConfig(RTC_IT_SEC,ENABLE); //使能 RTC 秒中断
RTC_SetCounter(0);//最后在配置完成之后
//6.更新配置,设置RTC中断分组。
RTC_ExitConfigMode();//退出配置模式,更新配置
}
int main(void)
{
Usart_Init();
RTC_Init();
while(1)
{
;
}
}
//每秒触发一次
void RTC_IRQHandler(void)
{
if (RTC_GetITStatus(RTC_IT_SEC) != RESET) //秒钟中断
{
data++;//每一秒+1
printf(“time:%dt”,data);//串口打印当前时间值
}
RTC_ClearITPendingBit(RTC_IT_SEC); //清中断
RTC_WaitForLastTask();
}
举报