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闹钟得出的结果,写得不好还请多多包涵!!!

  • 16
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PD南客

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值