STM32F1基于标准库工程RTC秒钟断+定时闹钟功能示例

2023-10-10 21:10

本文主要是介绍STM32F1基于标准库工程RTC秒钟断+定时闹钟功能示例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

STM32F1基于标准库工程RTC秒钟断+定时闹钟功能示例


  • 🔖使用正点原子标准库工程模板创建。

  • 📍参考:https://mp.weixin.qq.com/s/0oLpg9Kjlfo4Z9q0s6lZuQ

  • 📋串口调试打印信息:
    在这里插入图片描述

  • 🚩本文仅针对STM32F1系列标准库函数使用。不适用于其他型号!!!

📗工程功能介绍

📜基于STM32F103,使用的是标准库,套用正点原子工程模板,使用STM32的RTC时钟系统中的秒中断和RTC 闹钟报警中断来执行相对应的代码。这里仅演示各中断功能响应执行的代码。可以参考此功能模块自行移植。

📓RTC秒中断和闹钟驱动

  • 📝RTC.C
#include "rtc.h"_calendar_obj calendar;    //时钟结构体
const u8 mon_table[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};static void RTC_Alarm_EXIT(void)
{EXTI_InitTypeDef EXTI_InitStructure;EXTI_ClearITPendingBit(EXTI_Line17);EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Line = EXTI_Line17;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);}
/*** @brief  Configure the RTC peripheral by selecting the clock source.* @param  None* @retval None*/
void RTC_Config(void)
{NVIC_InitTypeDef NVIC_InitStructure;/* 使能PWR和BKP时钟 *//* Enable PWR and BKP clocks */RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);/* 使能对后备寄存器的访问 *//* Allow access to BKP Domain */PWR_BackupAccessCmd(ENABLE);/* 复位BKP寄存器 *//* Reset Backup Domain */BKP_DeInit();/* 将 RTC时钟设置为LSE这个32.768KHZ的晶振*//* Enable LSE */RCC_LSEConfig(RCC_LSE_ON);/* Wait till LSE is ready */while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET){}/* Select LSE as RTC Clock Source */RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);/* 使能RTC Clock *//* Enable RTC Clock */RCC_RTCCLKCmd(ENABLE);/* 等待同步 *//* Wait for RTC registers synchronization */RTC_WaitForSynchro();/* 等待对RTC寄存器最后的写操作完成*//* Wait until last write operation on RTC registers has finished */RTC_WaitForLastTask();/* 使能RTC秒中断 *//* Enable the RTC Second */RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能秒钟断和闹钟中断RTC_ITConfig(RTC_IT_ALR, ENABLE);//使能秒钟断和闹钟中断/* 等待对RTC寄存器最后的写操作完成*//* Wait until last write operation on RTC registers has finished */RTC_WaitForLastTask();/* 配置了预分频值: 设置RTC时钟周期为1s *//* Set RTC prescaler: set RTC period to 1sec */RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) *//* 等待对RTC寄存器最后的写操作完成*//* Wait until last write operation on RTC registers has finished */RTC_WaitForLastTask();/* Enable the RTC Alarm Interrupt */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_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn; //闹钟中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =  1; //比RTC全局中断的优先级高NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);RTC_Alarm_EXIT();}u8 Is_Leap_Year(u16 pyear)
{if(pyear % 4 == 0) //首先需能被4整除{if(pyear % 100 == 0){if(pyear % 400 == 0)    return 1; //如果以00结尾,还要能被400整除else    return 0;}elsereturn 1;}elsereturn 0;
}
/*
得到当前的时间
成功返回0,错误返回其它
*/
u8 RTC_Get(void)
{static u16 dayCount = 0;u32 secCount = 0;volatile u32 tmp = 0;u16 tmp1 = 0;secCount = RTC_GetCounter();tmp = secCount / 86400; //得到天数if(dayCount != tmp) //超过一天{dayCount = tmp;tmp1 = 1970; //从1970年开始while(tmp >= 365){if(Is_Leap_Year(tmp1))//是闰年{if(tmp >= 366)tmp -= 366; //减掉闰年的天数else{//    tmp1++;break;}}elsetmp -= 365; //平年tmp1++;}calendar.w_year = tmp1; //得到年份tmp1 = 0;while(tmp >= 28) //超过一个月{if(Is_Leap_Year(calendar.w_year) && tmp1 == 1) //当年是闰年且轮循到2月{if(tmp >= 29)tmp -= 29;elsebreak;}else{if(tmp >= mon_table[tmp1]) //平年tmp -= mon_table[tmp1];elsebreak;}tmp1++;}calendar.w_month = tmp1 + 1; //得到月份,tmp1=0表示1月,所以要加1calendar.w_date = tmp + 1; //得到日期,因为这一天还没过完,所以tmp只到其前一天,但是显示的时候要显示正常日期}tmp = secCount % 86400; //得到秒钟数calendar.hour = tmp / 3600; //小时calendar.min = (tmp % 3600) / 60; //分钟calendar.sec = (tmp % 3600) % 60; //秒return 0;
}
/*
*设置时钟
*把输入的时钟转换为秒钟
*以1970年1月1日为基准
*1970~2099年为合法年份
返回值:0,成功;其它:错误
*/
u8 RTC_Set(u16 year, u8 mon, u8 day, u8 hour, u8 min, u8 sec)
{u16 t;u32 secCount = 0;if(year < 1970 || year > 2099)return 1;//for(t = 1970; t < year; t++) //把所有年份的秒钟相加{if(Is_Leap_Year(t))//闰年secCount += 31622400; //闰年的秒钟数elsesecCount += 31536000;}mon -= 1; //先减掉一个月再算秒数(如现在是5月10日,则只需要算前4个月的天数,再加上10天,然后计算秒数)for(t = 0; t < mon; t++){secCount += (u32)mon_table[t] * 86400; //月份秒钟数相加if(Is_Leap_Year(year) && t == 1)secCount += 86400; //闰年,2月份增加一天的秒钟数}secCount += (u32)(day - 1) * 86400; //把前面日期的秒钟数相加(这一天还没过完,所以-1)secCount += (u32)hour * 3600; //小时秒钟数secCount += (u32)min * 60; //分钟秒钟数secCount += sec;
//    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR    | RCC_APB1Periph_BKP,ENABLE);
//    PWR_BackupAccessCmd(ENABLE);RTC_SetCounter(secCount);//设置RTC计数器的值RTC_WaitForLastTask();    //等待最近一次对RTC寄存器的写操作完成RTC_Get();//更新时间return 0;
}
  • 📝RTC.H
#ifndef __RTC_H
#define __RTC_H
#include "stm32f10x.h"//时间结构体
typedef struct 
{vu8 hour;vu8 min;vu8 sec;            //公历年月日周vu16 w_year;vu8  w_month;vu8  w_date;vu8  week;     
}_calendar_obj;  extern _calendar_obj calendar;void RTC_Config(void);
void RTC_Init(void);
u8 RTC_Set(u16 year,u8 mon,u8 day,u8 hour,u8 min,u8 sec);
u8 RTC_Get(void);
#endif

📑main主程序

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "rtc.h"
#include <stdio.h>volatile unsigned char RTC_IT_SEC_flag = 0;
/* Private function prototypes -----------------------------------------------*/
void LEDInit(void);/* Private functions ---------------------------------------------------------*/
/*** @brief  Configures LED GPIO.* @retval None*/
void LEDInit(void)
{GPIO_InitTypeDef  GPIO_InitStructure;/* Enable the GPIO Clock */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);/* Configure the GPIO pin */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOE, &GPIO_InitStructure);
}int main(void)
{volatile u8 t = 0;delay_init();	    	 //延时函数初始化/* Configure RTC */RTC_Config();RTC_Set(2023, 6, 14, 12, 27, 5); //RTC_EnterConfigMode();RTC_SetAlarm(6 + RTC_GetCounter());//配置下次闹钟RTC_WaitForLastTask();RTC_ExitConfigMode();NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级uart_init(115200);	 //串口初始化为115200LEDInit();while(1){/* Show Time */if(t != calendar.sec)
//        if(RTC_IT_SEC_flag){t = calendar.sec;printf("NowTime:%d 年 %d 月 %d 日 %d 时 %d 分 %d 秒 \r\n ", \calendar.w_year, calendar.w_month, calendar.w_date, calendar.hour, calendar.min, calendar.sec);
//            RTC_IT_SEC_flag = 0;}}
}
/*** @brief  This function handles RTC global interrupt request.* @param  None* @retval None*/
void RTC_IRQHandler(void)
{if(RTC_GetITStatus(RTC_IT_SEC) != RESET) //秒钟中断{/* Clear the RTC Second interrupt */RTC_ClearITPendingBit(RTC_IT_SEC);RTC_Get();//更新时间
//        RTC_IT_SEC_flag = 1;/* Toggle LED */GPIOE->ODR ^= GPIO_Pin_5;printf("RTC_IT_SEC!\r\n");/* Wait until last write operation on RTC registers has finished */RTC_WaitForLastTask();}
}void RTCAlarm_IRQHandler(void)
{if(RTC_GetITStatus(RTC_IT_ALR) != RESET) //ALR中断{EXTI_ClearITPendingBit(EXTI_Line17);RTC_WaitForLastTask();printf("Alarm clock!\r\n");/* Clear the RTC ALR interrupt */RTC_ClearITPendingBit(RTC_IT_ALR);PWR_BackupAccessCmd(ENABLE);RTC_EnterConfigMode();RTC_SetAlarm(6 + RTC_GetCounter());//配置下次闹钟/* Wait until last write operation on RTC registers has finished */RTC_WaitForLastTask();RTC_ExitConfigMode();PWR_BackupAccessCmd(DISABLE);}RTC_ClearITPendingBit(RTC_IT_OW);/* Wait until last write operation on RTC registers has finished */RTC_WaitForLastTask();}

📚工程源码

链接:https://pan.baidu.com/s/1Zl6vd0h_uHkYnrfIYxtmMQ 
提取码:2xk3

这篇关于STM32F1基于标准库工程RTC秒钟断+定时闹钟功能示例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/183119

相关文章

C语言小项目实战之通讯录功能

《C语言小项目实战之通讯录功能》:本文主要介绍如何设计和实现一个简单的通讯录管理系统,包括联系人信息的存储、增加、删除、查找、修改和排序等功能,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录功能介绍:添加联系人模块显示联系人模块删除联系人模块查找联系人模块修改联系人模块排序联系人模块源代码如下

Java中注解与元数据示例详解

《Java中注解与元数据示例详解》Java注解和元数据是编程中重要的概念,用于描述程序元素的属性和用途,:本文主要介绍Java中注解与元数据的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参... 目录一、引言二、元数据的概念2.1 定义2.2 作用三、Java 注解的基础3.1 注解的定义3.2 内

Java中使用Java Mail实现邮件服务功能示例

《Java中使用JavaMail实现邮件服务功能示例》:本文主要介绍Java中使用JavaMail实现邮件服务功能的相关资料,文章还提供了一个发送邮件的示例代码,包括创建参数类、邮件类和执行结... 目录前言一、历史背景二编程、pom依赖三、API说明(一)Session (会话)(二)Message编程客

SQL Server使用SELECT INTO实现表备份的代码示例

《SQLServer使用SELECTINTO实现表备份的代码示例》在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误,在SQLServer中,可以使用SELECTINT... 在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误。在 SQL Server 中,可以使用 SE

Java CompletableFuture如何实现超时功能

《JavaCompletableFuture如何实现超时功能》:本文主要介绍实现超时功能的基本思路以及CompletableFuture(之后简称CF)是如何通过代码实现超时功能的,需要的... 目录基本思路CompletableFuture 的实现1. 基本实现流程2. 静态条件分析3. 内存泄露 bug

C#实现系统信息监控与获取功能

《C#实现系统信息监控与获取功能》在C#开发的众多应用场景中,获取系统信息以及监控用户操作有着广泛的用途,比如在系统性能优化工具中,需要实时读取CPU、GPU资源信息,本文将详细介绍如何使用C#来实现... 目录前言一、C# 监控键盘1. 原理与实现思路2. 代码实现二、读取 CPU、GPU 资源信息1.

Java中Springboot集成Kafka实现消息发送和接收功能

《Java中Springboot集成Kafka实现消息发送和接收功能》Kafka是一个高吞吐量的分布式发布-订阅消息系统,主要用于处理大规模数据流,它由生产者、消费者、主题、分区和代理等组件构成,Ka... 目录一、Kafka 简介二、Kafka 功能三、POM依赖四、配置文件五、生产者六、消费者一、Kaf

基于Python开发电脑定时关机工具

《基于Python开发电脑定时关机工具》这篇文章主要为大家详细介绍了如何基于Python开发一个电脑定时关机工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 简介2. 运行效果3. 相关源码1. 简介这个程序就像一个“忠实的管家”,帮你按时关掉电脑,而且全程不需要你多做

python实现pdf转word和excel的示例代码

《python实现pdf转word和excel的示例代码》本文主要介绍了python实现pdf转word和excel的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、引言二、python编程1,PDF转Word2,PDF转Excel三、前端页面效果展示总结一

在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码

《在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码》在MyBatis的XML映射文件中,trim元素用于动态添加SQL语句的一部分,处理前缀、后缀及多余的逗号或连接符,示... 在MyBATis的XML映射文件中,<trim>元素用于动态地添加SQL语句的一部分,例如SET或W