STM32F429 >> 19. RTC_实时时钟(Code)

配置及读取日期和时间

此工程没有读取亚秒值。

若想让时钟断电后持续计时,则不要使能RTC_Config() 函数中的后备域访问。

bsp_rtc.h

/**
  ******************************************************************************
  * @file    bsp_rtc.h
  * @author  Waao
  * @version V1.0.0
  * @date    17-Feb-2019
  * @brief   This file contains some board support package's definition for the RTC.
  *            
  ******************************************************************************
  * @attention
  *
  * None
	*
  ******************************************************************************
  */
#ifndef __BSP_RTC_H_
#define __BSP_RTC_H_

#include "stm32f4xx_rtc.h"
#include 
#include 


//============== Date values =================
#define YEAR                 19
#define MONTH                2 // RTC_Month_February
#define DATE                 19
#define WEEKDAY              2 // RTC_Weekday_Tuesday
//============================================

//============== Time values =================
#define HOURS                0x00
#define MINUTES              0x00
#define SECONDS              0x00
//============================================

void RTC_Config(void);
void RTC_DateConfig(void);
void RTC_TimeConfig(void);


#endif

bsp_rtc.c

/**
  ******************************************************************************
  * @file    bsp_rtc.c
  * @author  Waao
  * @version V1.0.0
  * @date    17-Feb-2019
  * @brief   This file contains some board support package's functions for the RTC.
  *            
  ******************************************************************************
  * @attention
  *
  * None
	*
  ******************************************************************************
  */

#include "bsp_rtc.h"

/**
  * @brief  Initialize the RTC.
  * @param  None  
  * @retval None
  */
void RTC_Config(void)
{
	RTC_InitTypeDef RTC_InitStructure;
	
	//RCC_APB1PeriphClockLPModeCmd(RCC_APB1Periph_PWR, ENABLE);
	
	/* If we ENABLE the Backup Access, we can write the RTC, RCC_BDCR, PWR_CSR register. 
	 * So that we can modify the time values again. But we cannot modify the time values 
	 * if we disable that, the time values will keep count forever even through we power 
	 * down the device.
	 * If you want to make it counter run forever, you can DISABLE that.
	 */
	PWR_BackupAccessCmd(ENABLE);
	
	RCC_LSEConfig(RCC_LSE_ON);
	while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
	
	RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
	RCC_RTCCLKCmd(ENABLE);
	
	RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
	RTC_InitStructure.RTC_AsynchPrediv = 127;
	RTC_InitStructure.RTC_SynchPrediv = 255;
	
	RTC_Init(&RTC_InitStructure);
}


/**
  * @brief  Configure the now date.
  * @param  None  
  * @retval None
  */
void RTC_DateConfig(void)
{
	RTC_DateTypeDef SetDate_InitStructure; 

	// SetDate_InitStructure
	SetDate_InitStructure.RTC_Year = YEAR;
	SetDate_InitStructure.RTC_Month =MONTH;
	SetDate_InitStructure.RTC_WeekDay = WEEKDAY;
	SetDate_InitStructure.RTC_Date = DATE;

	RTC_SetDate(RTC_Format_BIN, &SetDate_InitStructure);
}


/**
  * @brief  Configure the now time.
  * @param  None  
  * @retval None
  */
void RTC_TimeConfig(void)
{
	RTC_TimeTypeDef SetTime_InitStructure;
	
	// SetTime_InitStructure
	SetTime_InitStructure.RTC_H12 = RTC_H12_PM;
	SetTime_InitStructure.RTC_Hours = HOURS;
	SetTime_InitStructure.RTC_Minutes = MINUTES;
	SetTime_InitStructure.RTC_Seconds = SECONDS;

	RTC_SetTime(RTC_Format_BIN, &SetTime_InitStructure);
}

main.c

/**
  ******************************************************************************
  * @file    main.c
  * @author  Waao
  * @version V1.0.0
  * @date    19-Feb-2019
  * @brief   RTC operation.
  *            
  ******************************************************************************
  * @attention
  *
  * None
	*
  ******************************************************************************
  */

#include 
#include 
#include 


/**
 1. @brief  Main
 2. @param  None  
 3. @retval None
  */
int main(void)
{
	RTC_DateTypeDef GetDate_InitStructure;
	RTC_TimeTypeDef GetTime_InitStructure;

	// We can use the print function
	USART_GPIO_Config();
	USART1_Config();
	
	// We can use the Delay function
	SysTick_Init();
	
	RTC_Config();
	RTC_DateConfig();
	RTC_TimeConfig();
	
	while(1)
	{
		RTC_GetDate(RTC_Format_BIN, &GetDate_InitStructure);
		printf("\nToday is 20%d-%d-%d, and the WeekDay is %d", GetDate_InitStructure.RTC_Year, GetDate_InitStructure.RTC_Month, GetDate_InitStructure.RTC_Date, GetDate_InitStructure.RTC_WeekDay);
		RTC_GetTime(RTC_Format_BIN, &GetTime_InitStructure);
		printf("\nThe real time is %0.2d:%0.2d:%0.2d", GetTime_InitStructure.RTC_Hours, GetTime_InitStructure.RTC_Minutes, GetTime_InitStructure.RTC_Seconds);
		printf("\n");
		Delay(100000);
	}
}
	

闹钟


闹钟编程指南

  1. 配置好基本的日期和时间;
  2. 开启闹钟中断(NVIC, EXTI);
  3. 配置闹钟中断结构体并使能中断;
  4. 编写闹钟中断函数执行代码;

bsp_rtc.h

//================= Alarm ====================
#define RTC_Alarm_Channel    RTC_Alarm_IRQn
#define RTC_Alarm_EXTI_LINE  EXTI_Line17
#define Specified_RTC_Alarm  RTC_Alarm_A
#define Alarm_HOURS          0
#define Alarm_MINUTES        0
#define Alarm_SECONDS        1
//============================================

bsp_rtc.c

/**
  * @brief  Configure the Alarm.
  * @param  None  
  * @retval None
  */
void RTC_AlarmConfig(void)
{
	RTC_AlarmTypeDef Alarm_InitStructure;
	
	NVIC_Config();
	EXTI_Config();
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
	RTC_AlarmCmd(Specified_RTC_Alarm, DISABLE);
	
	// Alarm_InitStructure
	Alarm_InitStructure.RTC_AlarmTime.RTC_H12 = RTC_H12_PM;
	Alarm_InitStructure.RTC_AlarmTime.RTC_Hours = Alarm_HOURS;
	Alarm_InitStructure.RTC_AlarmTime.RTC_Minutes = Alarm_MINUTES;
	Alarm_InitStructure.RTC_AlarmTime.RTC_Seconds = Alarm_SECONDS;
	/* You can dicide which field is invalid.
	 * For example, if you configure the RTC_AlarmMask_DateWeekDay is invalid, the alarm will 
	 * trigger each day.
	 */
	Alarm_InitStructure.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay;
	Alarm_InitStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_WeekDay;
	Alarm_InitStructure.RTC_AlarmDateWeekDay = 19;
	
	RTC_SetAlarm(RTC_Format_BIN, Specified_RTC_Alarm, &Alarm_InitStructure);
	RTC_ITConfig(RTC_IT_ALRA, ENABLE);
	RTC_AlarmCmd(Specified_RTC_Alarm, ENABLE);
  RTC_ClearFlag(RTC_FLAG_ALRAF);
  EXTI_ClearITPendingBit(EXTI_Line17);	
}

bsp_exti.c

/**
  * @brief  Configure the NVIC
  * @param  None
  * @retval None
  */
void NVIC_Config(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	
	//Configure the NVIC to prioritygroup1
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	
	//Configure the preemption priority to 1
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	//Configure the subpriority to 1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	//Enable the interrupt channel
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	
	NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_Channel;
	NVIC_Init(&NVIC_InitStructure);
}


/**
  * @brief  Configure the EXTI
  * @param  None
  * @retval None
  */
void EXTI_Config(void)
{
	EXTI_InitTypeDef EXTI_InitStructure;
	
	EXTI_InitStructure.EXTI_Line = RTC_Alarm_EXTI_LINE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	
	EXTI_Init(&EXTI_InitStructure);
}

stm32f4xx_it.c

/**
  * @brief  This function handles RTC Alarm.
  * @param  None
  * @retval None
  */
void RTC_Alarm_IRQHandler(void)
{
	if(RTC_GetITStatus(RTC_IT_ALRA) == SET)
	{
		LED1_ON;
		printf("\nAlarm");
	}
  RTC_ClearITPendingBit(RTC_IT_ALRA);
  EXTI_ClearITPendingBit(EXTI_Line17);
}

main.c

/**
  ******************************************************************************
  * @file    main.c
  * @author  Waao
  * @version V1.0.0
  * @date    19-Feb-2019
  * @brief   RTC operation.
  *            
  ******************************************************************************
  * @attention
  *
  * None
	*
  ******************************************************************************
  */
#include 
#include 
#include 
#include 
#include 
#include 


/**
  * @brief  Main
  * @param  None  
  * @retval None
  */
int main(void)
{
	RTC_DateTypeDef GetDate_InitStructure;
	RTC_TimeTypeDef GetTime_InitStructure;

	// We can use the print function
	USART_GPIO_Config();
	USART1_Config();
	
	// We can use the Delay function
	SysTick_Init();
	
	KEY_GPIO_Config();
	LED_GPIO_Config();
	
	RTC_Config();
	RTC_DateConfig();
	RTC_TimeConfig();
	RTC_AlarmConfig();
	
	while(1)
	{
		RTC_GetDate(RTC_Format_BIN, &GetDate_InitStructure);
		printf("\nToday is 20%d-%d-%d, and the WeekDay is %d", GetDate_InitStructure.RTC_Year, GetDate_InitStructure.RTC_Month, GetDate_InitStructure.RTC_Date, GetDate_InitStructure.RTC_WeekDay);
		RTC_GetTime(RTC_Format_BIN, &GetTime_InitStructure);
		printf("\nThe real time is %0.2d:%0.2d:%0.2d", GetTime_InitStructure.RTC_Hours, GetTime_InitStructure.RTC_Minutes, GetTime_InitStructure.RTC_Seconds);
		printf("\n");
//		if(RTC_GetFlagStatus(RTC_FLAG_ALRAF) == SET)
//		{
//			LED1_ON;
//		}
		Delay(100000);
		LED1_OFF;
	}
}

周期性自动唤醒


自动唤醒编程指南

  1. 开启唤醒中断(NVIC, EXTI);
  2. 配置唤醒所需参数并使能中断;
  3. 编写唤醒中断函数执行代码;

bsp_rtc.h

//================== WKUP ====================
#define RTC_WKUP_Channel        RTC_WKUP_IRQn
#define RTC_WKUP_EXTI_LINE      EXTI_Line22
#define RTC_WKUP_CounterValues  3
//============================================

bsp_rtc.c

配置完中断参数后顺手清除中断位绝对是个好习惯,尤其是在和硬件打交道时。否则在某种特定情况下可能会出现一些程序上根本找不到的问题…

在此程序中,有一次我给单片机睡眠了,结果后面多次烧录原来的程序后,唤醒中断函数都不执行,直到一次我在配置完中断后清除了中断标志位…

/**
  * @brief  Configure the WKUP.
  * @param  None  
  * @retval None
  */
void RTC_WKUPConfig(void)
{
	NVIC_Config();
	EXTI_Config();

	// CK_SPRE is the 1Hz system clock generally.
	RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits);
	RTC_SetWakeUpCounter(RTC_WKUP_CounterValues);
	RTC_WakeUpCmd(ENABLE);
	RTC_ITConfig(RTC_IT_WUT, ENABLE);
	
	// Clear the IT bits when we finished the configuring is a good habit.
	RTC_ClearITPendingBit(RTC_IT_WUT);
}

stm32f4xx_it.c

/**
  * @brief  This function handles RTC WKUP.
  * @param  None
  * @retval None
  */
void RTC_WKUP_IRQHandler(void)
{
	if(RTC_GetITStatus(RTC_IT_WUT) != RESET)
	{
		printf("\nI am wake up!!");
		RTC_ClearITPendingBit(RTC_IT_WUT);
		EXTI_ClearITPendingBit(RTC_WKUP_EXTI_LINE);
	}
}

我们也可以配置睡眠停止等状态下的自动唤醒,但要注意,从停止模式中唤醒后需要将系统时钟重新配置为HSE,否则会有部分的外设由于时钟配置不正确而产生异常

你可能感兴趣的:(STM32,C,嵌入式,STM32)