首页 > 其他分享 >STM32标准库RTC时钟

STM32标准库RTC时钟

时间:2024-03-04 11:11:06浏览次数:35  
标签:NVIC RTC STM32 start tm time EXTI 时钟

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();                  // 等待最后一个任务结束
	}
}

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

标签:NVIC,RTC,STM32,start,tm,time,EXTI,时钟
From: https://www.cnblogs.com/tqht7h/p/18051420

相关文章

  • 十三、BKP备份寄存器&RTC实时时钟
    十一、BKP备份寄存器&RTC实时时钟Unix时间戳Unix时间戳(UnixTimestamp)定义为从UTC/GMT的1970年1月1日0时0分0秒开始所经过的秒数,不考虑闰秒时间戳存储在一个秒计数器中,秒计数器为32位/64位的整型变量世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间UTC/......
  • linux基于VSCODE搭建stm32开发环境
    1.安装VSCODEhttps://code.visualstudio.com/2.安装系统相关编译软件sudoaptinstallbuild-essentialgdbsudoaptinstallgcc-arm-none-eabisudoaptinstallmakecmakesudoaptinstallopenocd3.安装VSCODE插件cortex-debug  4 安装stlink驱动下载地址......
  • STM32的中断刨析
    STM32中断刨析一直以来,学习了stm32和freertos但在思考rtos的任务调度时,涉及到stm32的中断就感觉糊里糊涂。本篇记录刨析stm32的中断系统。中断和异常在STM32微控制器中,中断(Interrupt)和异常(Exception)是两种处理器响应外部事件的机制。它们的区别和联系如下:区别:中......
  • linux基于STM32CUBE IDE搭建stm32开发环境
    1.安装STM32CUBEMX安装地址https://www.st.com/zh/development-tools/stm32cubemx.html2.安装STM32CUBEIDE安装地址https://www.st.com/zh/development-tools/stm32cubeide.html3.安装烧写相关软件3.1安装openocd方法1:命令安装(不推荐,因为默认安装的是0.10.0,不支持......
  • linux基于clion搭建stm32开发环境
    1.安装开发工具1.1安装stm32cubemx下载地址https://www.st.com/zh/development-tools/stm32cubemx.html1.2安装clion方法1:直接下载clion,下载地址https://www.jetbrains.com/clion/download方法2:通过JetBrainsToolBox下载,JetBrainsToolBox下载地址https://www.j......
  • 使用STM32CubeMX创建工程
    1,选择芯片新建工程 2.时钟模块的设置分别设置HSE,LSE,MCO 3.时钟系统配置分别配置PLL,SYSCLK,AHB,APB1,APB2等等,配置修改如下红色标记部分 4.Cortex内核配置分别配置SYS(DEBUG),NVIC(优先级分组) 5.GPIO引脚配置我的板子的原理图的PB5引脚是LED0  6.修改工程配......
  • STM32 | STM32到底是什么?(第一天)
    零基础STM32第一天一、认知STM321、STM32概念STM32:意法半导体基于ARM公司的Cortex-M内核开发的32位的高性能、低功耗单片机。ST:意法半导体M:基于ARM公司的Cortex-M内核的高性能、低功耗单片机32:32位单片机2、STM32开发的产品STM32开发的产品:无人机、扫地机器人、3D打......
  • 关于STM32Fx部分引脚不可以正常输出高低电平的解决办法(不可以正常使用)
    一、概述在一次电路版测试中,发现stm32的部分引脚不可以正常的输出高低电平,刚开始以为是板子没有焊接好所以导致的经过多次的测试,发现电路版没问题。当时就想不清楚了,后面就问学长,还有实验室的学长一起测试。刚开始我们经过测试,认为是SCL的问题,认为在某个地方该引脚被......
  • STM32ADC单通道转换
    STM32ADC单通道转换1.初始化ADC功能初始化主要分三部分,GPIO初始化、ADC模式初始化与NVIC初始化。1.1初始化GPIOvoidADC_GPIO_Config(void)//配置ADC通道引脚{ GPIO_InitTypeDefGPIO_InitStructure;//定义GPIO结......
  • STM32OLED使用
    STM32OLED使用.mdSTM32OLED使用市面上大部分OLED使用SSD1306作为主控芯片,在这里使用STM32F103作为主控芯片,使用IIC总线点亮OLED。1.IIC设置以及初始化共需要引用4个头文件“stm32f10x_rcc.h”,“stm32f10x_gpio.h”,“stm32f10x_i2c.h”,“string.h”voidIIC_init(){RCC_A......