IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32HAL库RTC闹钟事件 -> 正文阅读

[嵌入式]STM32HAL库RTC闹钟事件

????????最近遇到stm32f系列看门狗不能关闭的事情,需要开启RTC闹钟定时唤醒喂狗。这里给RTC闹钟打一个标签把,我设置为每20秒开启一次闹钟。

?首先是HAL库的配置

配置时钟:

选择下载方式

选择时钟和选择闹钟A

?闹钟配置

开启中断

?设置时钟

?我的是 外部晶振为25MHz

项目文件设置

?完成之后生成工程

我用的是STM32F4的芯片,RTC的时间都在HAL里面设置完成之后生成。

生成的代码段

时间日期设置

 //闹钟和时间结构体用全局变量设置
 RTC_AlarmTypeDef sAlarm = {0};
 RTC_TimeTypeDef sTime = {0};
/* USER CODE END 0 */

RTC_HandleTypeDef hrtc;

/* RTC init function */
void MX_RTC_Init(void)
{

  /* USER CODE BEGIN RTC_Init 0 */
	HAL_LockTypeDef rtc_time={0};

  /* USER CODE END RTC_Init 0 */

  RTC_TimeTypeDef sTime = {0};
  RTC_DateTypeDef sDate = {0};
  RTC_AlarmTypeDef sAlarm = {0};

  /* USER CODE BEGIN RTC_Init 1 */

  /* USER CODE END RTC_Init 1 */
  /** Initialize RTC Only
  */
  hrtc.Instance = RTC;
  hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
  hrtc.Init.AsynchPrediv = 127;
  hrtc.Init.SynchPrediv = 255;
  hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
  hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN Check_RTC_BKUP */

  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date
  */
  sTime.Hours = 12;
  sTime.Minutes = 12;
  sTime.Seconds = 0;
  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sTime.StoreOperation = RTC_STOREOPERATION_RESET;
  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
  {
    Error_Handler();
  }
  sDate.WeekDay = RTC_WEEKDAY_MONDAY;
  sDate.Month = RTC_MONTH_JANUARY;
  sDate.Date = 1;
  sDate.Year = 0;

  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
  {
    Error_Handler();
  }

闹钟和时间结构体用全局变量设置

闹钟时间设置

 /** Enable the Alarm A
  */
  sAlarm.AlarmTime.Hours = 12;
  sAlarm.AlarmTime.Minutes = 12;
  sAlarm.AlarmTime.Seconds = 10;
  sAlarm.AlarmTime.SubSeconds = 5;
  sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
  sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY|RTC_ALARMMASK_HOURS
                              |RTC_ALARMMASK_MINUTES;
  sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
  sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
  sAlarm.AlarmDateWeekDay = 1;
  sAlarm.Alarm = RTC_ALARM_A;
  if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK)
  {
    Error_Handler();
  }

闹钟的配置有不懂的可以看下面的注释

/**
  * @brief  RTC Alarm structure definition
  */
typedef struct
{
  RTC_TimeTypeDef AlarmTime; //设置时间
    
  uint32_t AlarmMask; //闹钟掩码设置
  //RTC_ALARMMASK_NONE,闹钟比较时匹配所有比较项目,包括日期(日/星期)、时、分、秒,完全匹配才会产生闹钟中断/事件
  //RTC_ALARMMASK_DATEWEEKDAY,屏蔽日期(日/星期),闹钟比较时将不关心日期(日/星期)
  //RTC_ALARMMASK_HOURS,屏蔽时钟,闹钟比较时将不关心小时数
  //RTC_ALARMMASK_MINUTES,屏蔽分钟,闹钟比较时将不关心分钟数
  //RTC_ALARMMASK_SECONDS,屏蔽秒钟,闹钟比较时将不关心秒钟数
  //RTC_ALARMMASK_ALL,屏蔽所有,设置后将不会产生闹钟中断/事件
 
  uint32_t AlarmSubSecondMask; //亚秒掩码设置
  //在RTC_Alarm_Sub_Seconds_Masks_Definitions中设置亚秒匹配规则
 
  uint32_t AlarmDateWeekDaySel; //日期(日/星期)选择,此位只有当AlarmMask中不设置RTC_ALARMMASK_DATEWEEKDAY时才有效
  //RTC_ALARMDATEWEEKDAYSEL_DATE,选择匹配日期
  //RTC_ALARMDATEWEEKDAYSEL_WEEKDAY,选择匹配星期
 
  uint8_t AlarmDateWeekDay; //日期(日/星期)设置,此位只有当AlarmMask中不设置RTC_ALARMMASK_DATEWEEKDAY时才有效
  //如果AlarmDateWeekDaySel选择RTC_ALARMDATEWEEKDAYSEL_DATE,该值范围【1-31】,代表设置一个月当中的第几号
  //如果AlarmDateWeekDaySel选择RTC_ALARMDATEWEEKDAYSEL_WEEKDAY,该值范围在RTC_WeekDay_Definitions定义,代表设置一周当中的星期几
 
  uint32_t Alarm; //设置闹钟
  //RTC_ALARM_A,选择闹钟A
  //RTC_ALARM_B,选择闹钟B
 
}RTC_AlarmTypeDef;

下一次闹钟时间

这里我建立了新的dev_rtc.c\dev_rtc.h文件,专门放中断和设置闹钟时间

闹钟中断函数

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
  HAL_RTC_GetTime(hrtc,&sTime,RTC_FORMAT_BIN); //	 获取当前时间	

	dev_wdt_feed();	
	sAlarm_flag=1;//闹钟标志位

	// 再次启动闹钟中断事件
    if (HAL_RTC_SetAlarm_IT(hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK)
    {
        Error_Handler();
    }
	 HAL_RTC_SetAlarm_IT(hrtc,&sAlarm,RTC_FORMAT_BIN);
		
}

中断不能放太多代码,“sAlarm_flag”作为一个标志位来闹钟事件来开启下一次闹钟时间

设置闹钟时间结构体

在dev_rtc.h里面建立闹钟时、分、秒结构体

/*定义闹钟时、分、秒结构体*/
typedef struct
{
	uint8_t	Hourss;
	uint8_t	Minutess;
	uint8_t	Secondss;
	
}	nTime;

引用结构体的时候一定要在全局变量里面用

?sAlarm_flag标志位不能放在第一个,不然会出现进入中断后标志位直接清零的现象,小编因为这个debug了好久。

?设置闹钟时间

?由于代码较长,看起来不美观,这里我是建立了函数来单独设置时间“dev_set_alarm_time”;在20一次闹钟(可以根据自己的需要设置,分钟闹的话就把秒钟去掉就好了)

/****************************************************************************
**Description:			设置闹钟时间
**Input parameters:		
**Output parameters:	无
**Returned value:		
						
**Created by:			
**Modified by:
**Remark:		time_flag=1表示第二次闹钟时间		
*****************************************************************************/
void dev_set_alarm_time(void)
{

		if(second_time_flag==1)	设置第二次闹钟时间,此标志位只进来一次
		{
			Time.Hourss=12;
			Time.Minutess=12;
			Time.Secondss=20;
			second_time_flag=0;			
		}
		Time.Secondss+=20;	//每20秒进入一次
		if(Time.Secondss>= 60)
		{
			Time.Minutess+=1;
			if(Time.Minutess>=60)
				{
					Time.Hourss+= 1;
					if(Time.Hourss >= 24)
						{
							Time.Hourss = 0;
						}
					Time.Minutess= 0;
				}
			Time.Secondss= 0;
		}
}

进入下一次闹钟函数

/****************************************************************************
**Description:			闹钟函数
**Input parameters:		
**Output parameters:	无
**Returned value:		
						
**Created by:			
**Modified by:
**Remark:				闹钟掩码和日期选择是不可避免的
*****************************************************************************/

void dev_rtc_alarm(void)
{

	if(sAlarm_flag==1)//收到闹钟标志位
	{
		HAL_RTC_GetTime(&hrtc,&sTime,RTC_FORMAT_BIN); //	 获取当前时间	
		
		dev_set_alarm_time();//时间设置

		sAlarm.AlarmTime.Hours =Time.Hourss;
		sAlarm.AlarmTime.Minutes = Time.Minutess;	
		sAlarm.AlarmTime.Seconds = Time.Secondss;
	  sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY|RTC_ALARMMASK_HOURS
                              |RTC_ALARMMASK_MINUTES;		//闹钟掩码设置							
		sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;//日期(日/星期)选择,此位只有当AlarmMask中不设置RTC_ALARMMASK_DATEWEEKDAY时才有效
		sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
		sAlarm.AlarmDateWeekDay = 1;
		sAlarm.Alarm = RTC_ALARM_A;
		if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK)
		{
			Error_Handler();
		}
		sAlarm_flag=0;//清除闹钟标志位
		
		dev_alarm_wdt_feed();//喂狗

	}
	
}

开启闹钟

当下载代码后中断会自动开启第一次闹钟,而第二次和后面的闹钟在while(1)里面启用“dev_rtc_alarm()”函数就可以了

?总体dev_rtc.c代码


#include "dev_wdt.h"
#include "dev_rtc.h"
#include "rtc.h"

static s8 sAlarm_flag=0;//闹钟事件
static s8 second_time_flag=1;//第二次事件
extern RTC_AlarmTypeDef sAlarm ;//声明闹钟结构体
extern RTC_TimeTypeDef	 sTime ;//声明时间结构体
nTime  Time;
/****************************************************************************
**Description:			闹钟函数
**Input parameters:		
**Output parameters:	无
**Returned value:		
						
**Created by:			
**Modified by:
**Remark:				闹钟掩码和日期选择是不可避免的
*****************************************************************************/

void dev_rtc_alarm(void)
{
	dev_eeprom_read(SLEEP_FLAG_ADDR,&sAlarm_sleeps_flag,SLEEP_FLAG_LEN);
	if(sAlarm_flag==1)//收到闹钟标志位
	{
		HAL_RTC_GetTime(&hrtc,&sTime,RTC_FORMAT_BIN); //	 获取当前时间	
		
		dev_set_alarm_time();//时间设置

	  sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY|RTC_ALARMMASK_HOURS
                              |RTC_ALARMMASK_MINUTES;									//闹钟掩码设置
		sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;//日期(日/星期)选择,此位只有当AlarmMask中不设置RTC_ALARMMASK_DATEWEEKDAY时才有效
		sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
		sAlarm.AlarmDateWeekDay = 1;
		sAlarm.Alarm = RTC_ALARM_A;
		if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK)
		{
			Error_Handler();
		}
		sAlarm_flag=0;//清除闹钟标志位
		
		dev_alarm_wdt_feed();//喂狗

	}
	
}
/****************************************************************************
**Description:			设置闹钟时间
**Input parameters:		
**Output parameters:	无
**Returned value:		
						
**Created by:			
**Modified by:
**Remark:		time_flag=1表示第二次闹钟时间		
*****************************************************************************/
void dev_set_alarm_time(void)
{

		if(second_time_flag==1)	
		{
			Time.Hourss=12;
			Time.Minutess=12;
			Time.Secondss=20;
			second_time_flag=0;			
		}
		Time.Secondss+=20;	//每20秒进入一次
		if(Time.Secondss>= 60)
		{
			Time.Minutess+=1;
			if(Time.Minutess>=60)
				{
					Time.Hourss+= 1;
					if(Time.Hourss >= 24)
						{
							Time.Hourss = 0;
						}
					Time.Minutess= 0;
				}
			Time.Secondss= 0;
		}
		sAlarm.AlarmTime.Hours =Time.Hourss;
		sAlarm.AlarmTime.Minutes = Time.Minutess;	
		sAlarm.AlarmTime.Seconds = Time.Secondss;
}
/****************************************************************************
**Description:			喂狗且再次进入睡眠
**Input parameters:		
**Output parameters:	无
**Returned value:		
						
**Created by:			
**Modified by:
**Remark:			
*****************************************************************************/
void dev_alarm_wdt_feed(void)
{
		dev_wdt_feed();	
		if(sAlarm_sleeps_flag==1)
		{
			dev_charger_sleep();
		}
}


/****************************************************************************
**Description:			闹钟中断函数
**Input parameters:		
**Output parameters:	无
**Returned value:		
						
**Created by:			
**Modified by:
**Remark:				
*****************************************************************************/
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
  HAL_RTC_GetTime(hrtc,&sTime,RTC_FORMAT_BIN); //	 获取当前时间	

	dev_wdt_feed();	
	sAlarm_flag=1;//钟标志位闹

	// 再次启动闹钟中断事件
    if (HAL_RTC_SetAlarm_IT(hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK)
    {
        Error_Handler();
    }
	 HAL_RTC_SetAlarm_IT(hrtc,&sAlarm,RTC_FORMAT_BIN);
		
}




实验现象

我用的是debug调试

下面是两次闹钟现象

?以上就是小编针对RTC闹钟得出的结果,写得不好还请多多包涵!!!

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-11 12:52:08  更:2021-11-11 12:52:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:01:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码