STM32F407_05

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
//	}
//}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值