STM32标准库RTC时钟

STM32标准库RTC时钟

1. RTC时钟配置

1.1 头文件引用

需要引用以下头文件或打开以下模块:

#include "stm32f10x_rcc.h"      // 包含RCC时钟配置头文件
#include "stm32f10x_pwr.h"      // 包含PWR时钟配置头文件
#include "stm32f10x_rtc.h"      // 包含RTC时钟配置头文件
#include "time.h"               // 包含时间头文件

其中stm32f10x_rcc.h头文件用于配置RTC相关的时钟频率,stm32f10x_pwr.h头文件用于启用对RTC和备份域寄存器的访问,stm32f10x_rtc.h用于配置RTC模块,time.h用于在STM32上建立较为完善的时间管理机制。

1.2. RTC时钟初始化

void RTC_Init()                                           
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP,ENABLE); // 使能PWR和BKP时钟
	PWR_BackupAccessCmd(ENABLE);                            // 使能RTC和后备寄存器访问
//	RCC_LSEConfig(RCC_LSE_ON);
//	while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
//	
//	RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
	
	RCC_LSICmd(ENABLE);                                     // 使能LSI时钟
	
	while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);     // 等待LSI时钟准备就绪
	
	RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);                 // 选择LSI作为RTC时钟源
	
	RCC_RTCCLKCmd(ENABLE);                                  // 使能RTC时钟
	
	RTC_WaitForSynchro();                                   // 等待RTC时钟同步
	
	RTC_WaitForLastTask();                                  // 等待上一次RTC操作完成
	
	RTC_ITConfig(RTC_IT_SEC,ENABLE);                        // 使能秒中断
	RTC_ITConfig(RTC_IT_ALR,ENABLE);                        // 使能闹钟中断
	
	RTC_WaitForLastTask();                                  // 等待上一次RTC操作完成
	
	//RTC_SetPrescaler(32768-1);
	RTC_SetPrescaler(40000-1);                              //设定RTC频率            
	
	RTC_WaitForLastTask();                                  // 等待上一次RTC操作完成
	
	NVIC_InitTypeDef NVIC_InitStructure;                    // 定义NVIC_InitTypeDef结构体
	NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;          // 选择RTC中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;   // 设置抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;      // 设置子优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         // 使能中断
	
	NVIC_Init(&NVIC_InitStructure);                         // 初始化NVIC_InitTypeDef结构体
	
	NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;     // 选择闹钟中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;   // 设置抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;      // 设置子优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         // 使能中断
	
	NVIC_Init(&NVIC_InitStructure);                         // 初始化NVIC_InitTypeDef结构体
	
	EXTI_InitTypeDef EXTI_Instructure;                      // 定义EXTI_InitTypeDef结构体
	EXTI_Instructure.EXTI_Line = EXTI_Line17;               // 选择EXTI17中断
	EXTI_Instructure.EXTI_Mode = EXTI_Mode_Interrupt;       // 选择中断模式
	EXTI_Instructure.EXTI_Trigger = EXTI_Trigger_Rising;    // 选择上升沿触发
	EXTI_Instructure.EXTI_LineCmd = ENABLE;                 // 使能中断线
	EXTI_Init(&EXTI_Instructure);                           // 初始化EXTI_InitTypeDef结构体
}

在这里我使用了LSI时钟作为RTC时钟源,也可使用LSE时钟作为时钟源,不过打开方式略有不同,只要将上面注释的部分打开,删除代码中的LSI相关代码,并将RTC时钟频率修改为1Hz即可。
需要注意, RTCAlarm_IRQn中断的优先级必须要比RTC_IRQn高,否则会陷入中断嵌套,导致程序卡死。其次RTC的闹钟中断属于外部中断,需要同时打开对应的外部中断。

2. RTC时钟操作

2.1 设置时间


void RTC_SetTime(uint32_t time)    
{
	RTC_SetCounter(time);       // 设置RTC计数器
	RTC_WaitForLastTask();      // 等待上一次RTC操作完成
}

函数非常简单,但是这里要注意,向RTC时钟输入的时间为Unix时间戳,即从1970年1月1日0时0分0秒开始计算的秒数。开头时引用的time.h头文件便是为了更简便实现正常时间与时间戳的转换。具体转换操作如下所示:

struct tm time_start;               // 定义一个时间结构体,该结构体内存储的时间格式为正常时间
time_start.tm_year = year_start;    // 设置年,这个年指的是当前年数减1900的得到数字,范围为0-128
time_start.tm_mon = mon_start;      // 设置月,这个月指的是当前月数减1得到的数字,范围为0-12,因为Unix时间是从1月开始算的
time_start.tm_mday = mday_start;    // 设置日
time_start.tm_wday = wday_start;    // 设置星期
time_start.tm_yday = yday_start;    // 设置一年的天数
time_start.tm_hour = hour_start;    // 设置小时
time_start.tm_min = min_start;      // 设置分钟
time_start.tm_sec = sec_start;      // 设置秒数
RTC_SetTime(mktime(&time_start));   // 设置RTC时间,mktime函数会将时间结构体转换为Unix时间戳

2.2 获取时间

void RTC_GetTime()                  // 获取RTC时间
{
	struct tm *time;                // 定义一个时间结构体
	time_t time_temp = RTC_GetCounter();   // 获取RTC计数器
	time = localtime(&time_temp);   // 将Unix时间戳转换为时间结构体
	printf("unix:%d\n",time_temp);
	printf("%d-%d-%d-%d-%d",time->tm_year+1900,time->tm_mon+1,time->tm_mday,time->tm_wday,time->tm_yday);
	printf("-%d-%d-%d\n",time->tm_hour,time->tm_min,time->tm_sec);
}

在time.h头文件中,time.t = uint32_t.

2.3 设置闹钟

void RTC_SetAlarmTime(uint32_t time)
{
	PWR_BackupAccessCmd(ENABLE);
	RTC_SetAlarm(time);
	RTC_WaitForLastTask();
}

设置闹钟与设置时间差不多,区别在于设置闹钟要先打开备份寄存器,然后才能设置闹钟时间。

3. 中断函数

RTC的中断没什么特别,就是正常的进中断、清标志位。

3.1 秒中断

void RTC_IRQHandler()                           // RTC中断处理函数
{
	if(RTC_GetITStatus(RTC_IT_SEC) != RESET)    // 判断是否是秒中断
	{
		TimeRead_Flag = 1;                      // 设置读秒标志位
		RTC_ClearITPendingBit(RTC_IT_SEC);      // 清除秒中断标志位
		RTC_WaitForLastTask();                  // 等待最后一个任务结束
	}
}

3.2 闹钟中断

void RTCAlarm_IRQHandler()                      // 闹钟中断处理函数
{
	if(RTC_GetITStatus(RTC_IT_ALR) != RESET)    // 判断是否是闹钟中断
	{
		printf("Alarm is OK\n");                // 输出提示信息
		EXTI_ClearITPendingBit(EXTI_Line17);    // 清除闹钟中断的外部标志位
		RTC_ClearITPendingBit(RTC_IT_ALR);      // 清除闹钟中断标志位
		RTC_WaitForLastTask();                  // 等待最后一个任务结束
	}
}

这里需要注意,闹钟中断里需要清除两个中断标志位,否则会一直触发中断。

在使用STM32标准库进行RTC时钟配置时,可以按照以下步骤进行: 1. 首先,需要使能RTC外设时钟。可以通过RCC_APB1PeriphClockCmd函数来使能RTC外设时钟。例如,对于STM32F4系列微控制器,可以使用以下代码: ``` RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_RTC, ENABLE); ``` 2. 然后,需要初始化RTC时钟源。对于STM32F4系列微控制器,可以选择使用LSI(低速内部时钟)或者LSE(低速外部时钟)作为RTC时钟源。初始化RTC时钟源的代码示例如下: ``` RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); // 或 RCC_RTCCLKSource_LSE RCC_RTCCLKCmd(ENABLE); ``` 3. 对于RTC的配置和操作,还需要使用RTC库函数进行设置。以下是一些常见的RTC配置操作示例: - 设置RTC预分频器: ``` RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24; RTC_InitStructure.RTC_AsynchPrediv = 0x7F; RTC_InitStructure.RTC_SynchPrediv = 0xFF; RTC_Init(&RTC_InitStructure); ``` - 设置RTC时间: ``` RTC_TimeStructure.RTC_Hours = 12; RTC_TimeStructure.RTC_Minutes = 30; RTC_TimeStructure.RTC_Seconds = 0; RTC_SetTime(RTC_Format_BIN, &RTC_TimeStructure); ``` - 设置RTC日期: ``` RTC_DateStructure.RTC_Year = 21; RTC_DateStructure.RTC_Month = RTC_Month_July; RTC_DateStructure.RTC_Date = 1; RTC_SetDate(RTC_Format_BIN, &RTC_DateStructure); ``` 4. 最后,根据需要可以配置RTC的中断和事件。例如,可以使用RTC_ITConfig函数使能RTC的中断,并在对应的中断处理函数中进行相应的操作。 请注意,以上代码仅供参考,具体的RTC时钟配置可能会因不同型号的STM32微控制器而有所差异。建议参考官方提供的参考手册和示例代码进行具体的RTC时钟配置。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值