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

相关文章

苹果macOS 26 Tahoe主题功能大升级:可定制图标/高亮文本/文件夹颜色

《苹果macOS26Tahoe主题功能大升级:可定制图标/高亮文本/文件夹颜色》在整体系统设计方面,macOS26采用了全新的玻璃质感视觉风格,应用于Dock栏、应用图标以及桌面小部件等多个界面... 科技媒体 MACRumors 昨日(6 月 13 日)发布博文,报道称在 macOS 26 Tahoe 中

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

LiteFlow轻量级工作流引擎使用示例详解

《LiteFlow轻量级工作流引擎使用示例详解》:本文主要介绍LiteFlow是一个灵活、简洁且轻量的工作流引擎,适合用于中小型项目和微服务架构中的流程编排,本文给大家介绍LiteFlow轻量级工... 目录1. LiteFlow 主要特点2. 工作流定义方式3. LiteFlow 流程示例4. LiteF

MyBatis ResultMap 的基本用法示例详解

《MyBatisResultMap的基本用法示例详解》在MyBatis中,resultMap用于定义数据库查询结果到Java对象属性的映射关系,本文给大家介绍MyBatisResultMap的基本... 目录MyBATis 中的 resultMap1. resultMap 的基本语法2. 简单的 resul

MybatisPlus service接口功能介绍

《MybatisPlusservice接口功能介绍》:本文主要介绍MybatisPlusservice接口功能介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录Service接口基本用法进阶用法总结:Lambda方法Service接口基本用法MyBATisP

Mybatis Plus Join使用方法示例详解

《MybatisPlusJoin使用方法示例详解》:本文主要介绍MybatisPlusJoin使用方法示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录1、pom文件2、yaml配置文件3、分页插件4、示例代码:5、测试代码6、和PageHelper结合6

MySQL JSON 查询中的对象与数组技巧及查询示例

《MySQLJSON查询中的对象与数组技巧及查询示例》MySQL中JSON对象和JSON数组查询的详细介绍及带有WHERE条件的查询示例,本文给大家介绍的非常详细,mysqljson查询示例相关知... 目录jsON 对象查询1. JSON_CONTAINS2. JSON_EXTRACT3. JSON_TA

使用SpringBoot整合Sharding Sphere实现数据脱敏的示例

《使用SpringBoot整合ShardingSphere实现数据脱敏的示例》ApacheShardingSphere数据脱敏模块,通过SQL拦截与改写实现敏感信息加密存储,解决手动处理繁琐及系统改... 目录痛点一:痛点二:脱敏配置Quick Start——Spring 显示配置:1.引入依赖2.创建脱敏

SpringBoot 中 CommandLineRunner的作用示例详解

《SpringBoot中CommandLineRunner的作用示例详解》SpringBoot提供的一种简单的实现方案就是添加一个model并实现CommandLineRunner接口,实现功能的... 目录1、CommandLineRunnerSpringBoot中CommandLineRunner的作用