STM32F407_05

news2024/12/30 2:35:20

RTC实时时钟

主要特性:

由于RTC实时时钟提供了三种时钟源可供选择(LSI,LSE,HSE) ,一般我们选择低速外部时钟源(32.768KHZ)来作为RTC的时钟源

另外,RTC实时时钟可以由系统主电源供电,但是也可以由备份电源供电(系统主电源不工作时),所以想要使用,就必须打开电源控制器的外设时钟,PWR外设挂载在APB1总线下。

RTC具有闹钟中断以及唤醒中断功能 可以利用RTC的唤醒中断功能用来周期性的产生中断并且获取时间和日期 ,优点是获取的时间精准 精度高

RTC中断

#include "rtc.h"  
#include "usart.h"

static RTC_TimeTypeDef  RTC_TimeStructure;
static RTC_InitTypeDef  RTC_InitStructure;
static RTC_AlarmTypeDef RTC_AlarmStructure;
static NVIC_InitTypeDef  NVIC_InitStructure;
static EXTI_InitTypeDef  EXTI_InitStructure;
static RTC_DateTypeDef RTC_DateStructure;

/*
	RTC APB1
	
	初始化配置
*/

void rtc_Config(void)
{
	/* Enable the PWR clock */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
  /* Allow access to RTC */
	PWR_BackupAccessCmd(ENABLE);
	/* Enable the LSE OSC */
	RCC_LSEConfig(RCC_LSE_ON);
	//等待外部低速振荡器稳定
	while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
	
	 /* Select the RTC Clock Source */
	RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
	/* Enable the RTC Clock */
	RCC_RTCCLKCmd(ENABLE);
	/* Wait for RTC APB registers synchronisation */
	RTC_WaitForSynchro();


	 /* Configure the RTC data register and RTC prescaler */
	RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
	RTC_InitStructure.RTC_SynchPrediv = 0xFF;
	RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
	RTC_Init(&RTC_InitStructure);
	
	/* Set Time hh:mm:ss */
	RTC_TimeStructure.RTC_H12     = RTC_H12_AM;
	RTC_TimeStructure.RTC_Hours   = 0x14;  
	RTC_TimeStructure.RTC_Minutes = 0x38;
	RTC_TimeStructure.RTC_Seconds = 0x00;
	RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure);
	
	/* Set Date Week/Date/Month/Year */
	RTC_DateStructure.RTC_WeekDay = RTC_Weekday_Thursday;
	RTC_DateStructure.RTC_Date = 0x26;
	RTC_DateStructure.RTC_Month = RTC_Month_September;
	RTC_DateStructure.RTC_Year = 0x12;
	RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure);
 
	/* Write BkUp DR0 */
	RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2);
}

/*
函数名:Set_Alarm
功能:RTC 闹钟设置
参数:hou 时 min分 sec秒 date/week日期/星期
描述:包括中断配置闹钟使能

*/

void Set_Alarm(uint32_t hou,uint32_t min,uint32_t sec,uint32_t date_week)
{
 /* Enable RTC Alarm A Interrupt */
	//设置闹钟必须先关闭闹钟
	RTC_ITConfig(RTC_IT_ALRA, DISABLE);
	/* Enable the alarm */
	RTC_AlarmCmd(RTC_Alarm_A, DISABLE);
	
	/* Set the alarm 05h:20min:30s */
	if(hou<0x12)
		RTC_AlarmStructure.RTC_AlarmTime.RTC_H12     = RTC_H12_AM;
	else
		RTC_AlarmStructure.RTC_AlarmTime.RTC_H12     = RTC_H12_PM;
	RTC_AlarmStructure.RTC_AlarmTime.RTC_Hours   = hou;
	RTC_AlarmStructure.RTC_AlarmTime.RTC_Minutes = min;
	RTC_AlarmStructure.RTC_AlarmTime.RTC_Seconds = sec;
	RTC_AlarmStructure.RTC_AlarmDateWeekDay = date_week;//日期或者星期几闹
	RTC_AlarmStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;//按天开始闹钟
	RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay;//屏蔽日期和星期
	
	/* Configure the RTC Alarm A register */
	RTC_SetAlarm(RTC_Format_BCD, RTC_Alarm_A, &RTC_AlarmStructure);
	
	/* Enable RTC Alarm A Interrupt */
	RTC_ITConfig(RTC_IT_ALRA, ENABLE);
	
	/* Enable the alarm */
	RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
}

/*
	闹钟初始化
	闹钟中断使能

*/
void rtc_AlarmConfig(void)
{
 /* Enable RTC Alarm A Interrupt */
	RTC_ITConfig(RTC_IT_ALRA, ENABLE);
	
	/* Enable the alarm */
	RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
	
	/* Clear the RTC Alarm Flag */
	RTC_ClearFlag(RTC_FLAG_ALRAF);
	
	/* Clear the EXTI Line 17 Pending bit (Connected internally to RTC Alarm) */
	EXTI_ClearITPendingBit(EXTI_Line17);
	
 /* RTC Alarm A Interrupt Configuration */
	/* EXTI configuration *******************************************************/
	EXTI_ClearITPendingBit(EXTI_Line17);
	EXTI_InitStructure.EXTI_Line = EXTI_Line17;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);
	
	/* Enable the RTC Alarm Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

/*
	函数:rtc_init(void)
	功能:RTC初始化
*/
void rtc_Init(void)
{
	//检测有没有配置时间
	if(RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x32F2)
	{
		rtc_Config();
		Set_Alarm(0x18,0x00,0x00,0x04);
	}
	else
	{
		/* Enable the PWR clock */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
	
	/* Allow access to RTC */
	PWR_BackupAccessCmd(ENABLE);
	
	/* Enable the LSE OSC */
	RCC_LSEConfig(RCC_LSE_ON);
	
	/* Wait till LSE is ready */  
	while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
	/* Select the RTC Clock Source */
	RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

 /* Enable the RTC Clock 使能*/
	RCC_RTCCLKCmd(ENABLE);
	
	/* Wait for RTC APB registers synchronisation 等待寄存器就绪*/
	RTC_WaitForSynchro();
	}
	
	//关闭WAKE UP
	RTC_WakeUpCmd(DISABLE);		

	//唤醒时钟选择RTC配置好的时钟
	RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits);

	//设置WAKE UP自动重装载寄存器,写入零值默认是0+1=1
	RTC_SetWakeUpCounter(0);								
	
	
	//注意:必须添加清空RTC唤醒中断标志位,否则RTC不会触发
	RTC_ClearITPendingBit(RTC_IT_WUT);
	
	/* Enable RTC Wakeup Interrupt ,使能RTC唤醒中断*/
	RTC_ITConfig(RTC_IT_WUT, ENABLE);
	 
	/* Enable the Wakeup ,开启RTCWakeup定时器*/
	RTC_WakeUpCmd(ENABLE);
	
	/* EXTI configuration *******************************************************/
	EXTI_ClearITPendingBit(EXTI_Line22);
	EXTI_InitStructure.EXTI_Line = EXTI_Line22;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);
	 
	/* Enable the RTC Wakup Interrupt,使能RTC唤醒中断 */
	NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	rtc_AlarmConfig();//初始化闹钟


}

void RTC_Date_TimeShow(void)
{
	char buf[128]={0};
	/* Get the current Time,获取时间 */
	RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);
	
	/* Display time Format : 时:分:秒,格式化字符串 */
	sprintf((char*)buf,"time:%02d:%02d:%02d\r\n",RTC_TimeStructure.RTC_Hours, RTC_TimeStructure.RTC_Minutes, RTC_TimeStructure.RTC_Seconds);
	//串口发送
	//printf("%s",buf);
	//蓝牙发送
	//USARTx_SendString(USART_BLE, (uint8_t *)buf);  
	
	RTC_GetDate(RTC_Format_BIN,&RTC_DateStructure);
	
	/* Display date Format 年/月/日 星期几,格式化字符串 */
	sprintf((char*)buf,"date:20%02d/%02d/%02d Week:%d\r\n",RTC_DateStructure.RTC_Year, RTC_DateStructure.RTC_Month, RTC_DateStructure.RTC_Date,RTC_DateStructure.RTC_WeekDay);
	//串口发送
	printf("%s",buf);
	//蓝牙发送
	//USARTx_SendString(USART_BLE, (uint8_t *)buf);	
	
	
}


//RTC WAKE UP中断服务函数
void RTC_WKUP_IRQHandler(void)
{    
	if(RTC_GetFlagStatus(RTC_FLAG_WUTF)==SET)					//WK_UP中断?
	{ 
		RTC_ClearFlag(RTC_FLAG_WUTF);							//清除中断标志
		
		
		
	}   
	RTC_ClearITPendingBit(RTC_IT_WUT);
	EXTI_ClearITPendingBit(EXTI_Line22);						//清除中断线22的中断标志 								
}

//闹钟中断服务函数
void RTC_Alarm_IRQHandler(void)
{
   if(RTC_GetITStatus(RTC_IT_ALRA) != RESET)
   {
	
		RTC_ClearITPendingBit(RTC_IT_ALRA);
		EXTI_ClearITPendingBit(EXTI_Line17);
   } 
}


/*****************实时时钟任务控制块*************************/
OS_TCB RTC_Task_TCB;

CPU_STK RTC_Task_stk[128];			//实时时钟任务的任务堆栈,大小为128字,也就是512字节
void RTC_Task(void *parg);
void RTC_Task(void *parg)
{
	//CPU_SR_ALLOC();							//申请保护CPU的状态
	
	OS_ERR err;
	OSTimeDlyHMSM(0,0,2,0,OS_OPT_TIME_HMSM_STRICT,&err);


	
	while(1)
	{
		//进入临界区,保护以下的代码
		//OS_CRITICAL_ENTER();
		OSSemPend(&SYNC_SEM,0,OS_OPT_PEND_BLOCKING,0,&err); 		//请求信号量
		
		
		//退出临界区
		//OS_CRITICAL_EXIT();
		RTC_Date_TimeShow();
		OSSemPost(&SYNC_SEM,OS_OPT_POST_1,&err);					//发送信号量
		OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //让出CPU,延时100ms
	}

}


#ifndef __RTC_H
#define __RTC_H	 
#include "stm32f4xx.h" 
#include "includes.h"
extern OS_SEM	SYNC_SEM;

/*****************实时时钟任务控制块*************************/
extern OS_TCB RTC_Task_TCB;

extern void RTC_Task(void *parg);

extern CPU_STK RTC_Task_stk[128];			//实时时钟任务的任务堆栈,大小为128字,也就是512字节

 extern void rtc_Init(void);

extern void Set_Alarm(uint32_t hou,uint32_t min,uint32_t sec,uint32_t date_week);
void rtc_Config(void);
void rTC_Date_TimeShow(void);
void rtc_AlarmConfig(void);

#endif











 

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "includes.h"
#include "rtc.h"

任务1控制块
//OS_TCB Task1_TCB;

//void task1(void *parg);

//CPU_STK task1_stk[128];			//任务1的任务堆栈,大小为128字,也就是512字节

OS_SEM	SYNC_SEM;				//定义一个信号量,用于任务同步
//主函数
int main(void)
{
    //定义一个错误处理对象
	OS_ERR err;

	//RTC实时时钟初始化
	rtc_Init();
	delay_init(168);  								//时钟初始化   利用嘀嗒定时器来为操作系统产生周期性的节拍
	//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//中断分组配置 
	uart_init(115200);  				 			//串口初始化
    

	//OS初始化,它是第一个运行的函数,初始化各种的全局变量,例如中断嵌套计数器、优先级、存储器
	OSInit(&err);		   	 						//初始化UCOSIII
			 
	//创建开始任务
	//创建任务1,着重填写前8个参数
	//创建实时时钟任务
	OSTaskCreate(	(OS_TCB *)&RTC_Task_TCB,								//任务控制块
					(CPU_CHAR *)"RTC_Task",								//任务的名字
					(OS_TASK_PTR)RTC_Task,									//任务函数
					(void *)0,												//传递参数
					(OS_PRIO)2,											 	//任务的优先级		
					(CPU_STK *)RTC_Task_stk,								//任务堆栈基地址
					(CPU_STK_SIZE)128/10,									//任务堆栈深度限位,用到这个位置,任务不能再继续使用
					(CPU_STK_SIZE)128,										//任务堆栈大小			
					(OS_MSG_QTY)0,											//禁止任务消息队列
					(OS_TICK)0,												//默认时间片长度																
					(void  *)0,												//不需要补充用户存储区
					(OS_OPT)OS_OPT_TASK_NONE,								//没有任何选项
					&err													//返回的错误码
				);
						//创建一个信号量,且信号量初值为1,若为0,一开始调用等待信号量就会永远等待下去,不会执行程序。
	OSSemCreate ((OS_SEM*	)&SYNC_SEM,
                 (CPU_CHAR*	)"SYNC_SEM",
                 (OS_SEM_CTR)1,		
                 (OS_ERR*	)&err);	
  
	OSStart(&err);     //启动OS,进行任务调度
}

任务1  优先级1
//void task1(void *parg)
//{
//	OS_ERR err;
//	printf("task1 is create ok\r\n");

//	while(1)
//	{
//		printf("task1 is running ...\r\n");
//	
//		OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //让出CPU,延时1s
//	}
//}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2167457.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微电网与大电网主动同步控制

前言 大电网正常运行时&#xff0c;微电网通过大电网得到正常的电压频率参数支撑&#xff0c;大电网故障时&#xff0c;微电网的电压和频率支撑需要通过分布式电源提供&#xff0c;从而保持自身独立运行。分布式电源提供的电压信息会因为自身的下垂特性随本地负荷的改变不断变…

leetcode331. 验证二叉树的前序序列化

序列化二叉树的一种方法是使用 前序遍历 。当我们遇到一个非空节点时&#xff0c;我们可以记录下这个节点的值。如果它是一个空节点&#xff0c;我们可以使用一个标记值记录&#xff0c;例如 #。 例如&#xff0c;上面的二叉树可以被序列化为字符串 "9,3,4,#,#,1,#,#,2,#,…

【含文档】基于Springboot+Vue的高校师资管理系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…

构建高效线上培训体系的知识库策略

在数字化时代&#xff0c;线上培训已成为企业提升员工技能、促进知识传递的重要手段。然而&#xff0c;如何构建一个高效、系统的线上培训体系&#xff0c;确保培训内容的准确性与时效性&#xff0c;是许多企业面临的共同挑战。其中&#xff0c;知识库作为培训资源的核心载体&a…

Arduino中实现定时器中断

1、使用MsTimer2库文件 使用之前需要先添加库 &#xff08;1&#xff09;实现功能 &#xff08;2&#xff09;代码 /*MsTimer2 is a small and very easy to use library to interface Timer2 withhumans. Its called MsTimer2 because it "hardcodes" a resolutio…

99页PPT | 智慧城市运营大数据平台解决方案

方案内容综述 这是一套综合性的解决方案&#xff0c;旨在通过先进的数据分析和处理技术&#xff0c;提升城市管理的智能化水平。平台基于运营商的运营理论构建&#xff0c;通过整合城市各个层面的数据资源&#xff0c;实现对城市运行状态的全面监测、分析和优化。 城市大数据公…

MySQL的登录、访问、退出

一、登录&#xff1a; 访问MySQL服务器对应的命令&#xff1a;mysql.exe ,位置&#xff1a;C:\Program Files\MySQL\MySQL Server 8.0\bin &#xff08;mysql.exe需要带参数执行&#xff0c;所以直接在图形界面下执行该命令会自动结束&#xff09; 执行mysql.exe命令的时候出…

【Linux】进程的标识符、状态(超详解)

目录 进程的概念 进程标识符PID 系统调用创建进程-fork初识 进程状态 R状态&#xff08;运行状态&#xff09; S&#xff0c;D状态&#xff08;休眠状态&#xff09; T&#xff0c;t状态 Z状态&#xff08;僵尸进程&#xff09; 孤儿进程 X状态&#xff08;死亡状态&a…

深度学习500问——Chapter15:异构计算,GPU和框架选型(1)

文章目录 异构计算&#xff0c;GPU和框架选型指南 15.1 什么是异构计算 15.2 什么是GPU 15.3 GPU架构简介 15.3.1 如何通俗理解GPU的架构 15.3.2 CUDA的核心是什么 15.3.3 为什么要使用GPU 异构计算&#xff0c;GPU和框架选型指南 深度学习训练和推理的过程中&#xff0c;会涉…

塑封芯片多大才需要点胶加固保护?

塑封芯片多大才需要点胶加固保护&#xff1f; 塑封芯片是否需要点胶加固保护&#xff0c;并不完全取决于芯片的大小&#xff0c;而是由多种因素共同决定的。以下是一些影响是否需要点胶加固保护的主要因素&#xff1a; 芯片的应用场景&#xff1a;如果芯片所处的环境较为恶劣&a…

四种msvcp120.dll丢失的解决方法,简单几步将丢失的msvcp120.dll修复

如果你在使用电脑的时候遇到了msvcp120.dll文件丢失的问题应该怎么办呢&#xff1f;如何修复丢失的msvcp120.dll的问题呢&#xff1f;今天那就和大家聊聊msvcp120.dll丢失的解决办法&#xff0c;详细说说msvcp120.dll的解决办法步骤。 修复“msvcp120.dll”丢失问题的详细方法 …

Vue3使用vue-quill富文本编辑器

安装依赖 npm install vueup/vue-quill quill quill-image-uploader自定义字体 把自定义字体样式放入font.css中在main.js中导入 .ql-snow .ql-picker.ql-font .ql-picker-label[data-valueSimSun]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-valueSimSun]…

GitLab发送邮件功能详解:如何配置自动化?

GitLab发送邮件的设置指南&#xff1f;怎么优化GitLab发送邮件&#xff1f; GitLab作为一个强大的代码管理平台&#xff0c;不仅提供了代码托管、CI/CD等功能&#xff0c;还集成了发送邮件的功能&#xff0c;使得开发团队能够及时获取项目动态。AokSend将详细介绍如何配置GitL…

暗黑破坏神4第六赛季开荒攻略,如何高效开荒刷图打装备?

暗黑破坏神4的第六赛季将于10月8日开启&#xff01;要是你总觉得电脑开荒刷图打装备效率低&#xff0c;想知道有什么办法在手机上玩暗黑破坏神4&#xff1f;那这款专为游戏玩家打造的远程控制软件——网易GameViewer远程&#xff0c;就太适合你了&#xff01;不仅可以在手机上玩…

Linux下文件/目录操作的相关函数

1.文件系统 把一个磁盘分成一个或多个分区。每个分区可用包含一个文件系统 文件系统是&#xff0c;一组规则&#xff0c;规定对文件的存储及读取的一般方法。文件系统在磁盘格式化过程中指定。 常见的文件系统有&#xff1a;fat32 ntfs exfat ext2 、ext3 、ext4 inode是固定…

WSL进阶体验:gnome-terminal启动指南与中文显示问题一网打尽

起因 我们都知道 wsl 启动后就死一个纯命令行终端&#xff0c;一直以来我都是使用纯命令行工具管理Linux的。今天看到网上有人在 wsl 中启动带图形界面的软件。没错&#xff0c;就是在wsl中启动带有图形界面的Linux软件。比如下面这个编辑器。 ​​ 出于好奇&#xff0c;我就…

革新体验:细数3D在线预览在多个行业的广泛应用

‌3D在线预览展示技术的应用领域非常广泛&#xff0c;涵盖了从电子商务、产品设计、建筑设计到文化遗产保护等多个方面。‌ ‌1、电子商务‌&#xff1a; 在电商领域&#xff0c;3D展示技术为商品提供了全方位的展示&#xff0c;包括产品的外观、功能和卖点。这种交互式的购物…

影刀RPA实战:java结合影刀同步采购订单数据

1.实战目标 本次实战我们用java语言结合影刀&#xff0c;实现从自用ERP系统同步订单到旺店通中&#xff0c;在工作中&#xff0c;有时候我们的运营数据不是直接在旺店通ERP中操作&#xff0c;比如我们有自己的ERP&#xff0c;完成一些特定的内部工作后&#xff0c;再把数据同步…

做一个能适配「手机」的网站需要注意什么

这个问题的答案其实简单。 只要在网站前端开发过程中&#xff0c;将网站做成响应式布局&#xff0c;也就是 RWD &#xff08;Responsive Web Design&#xff09;就可以啦&#xff01;当手机或者不同设备打开网站时&#xff0c;通过检测视口分辨率来自动呈现不同的尺寸布局内容…

小程序弹出框是没办法遮挡住底部的tabbar的,解决的办法是使用自定义tabbar。。uni-app小程序如何自定义tabbar

原生小程序方法自定义 tabBar | 微信开放文档 如果是uni-app的小程序应该怎么自定义呢&#xff1f; 不是用page.json里面的tabbar就需要修改page.json.加上 "custom": true 注意list数组还是按照正常的来写。所以不使用但是也不能删除。 我们知道uni-app里面的页…