完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛扫一扫,分享给好友
|
01. RTC时钟简介
STM32F4 的实时时钟(RTC)相对于 STM32F1 来说,改进了不少,带了日历功能了,STM32F4 的 RTC,是一个独立的 BCD 定时器/计数器。RTC 提供一个日历时钟(包含年月日时分秒信息)、两个可编程闹钟(ALARM A 和 ALARM B)中断,以及一个具有中断功能的周 期性可编程唤醒标志。RTC 还包含用于管理低功耗模 式的自动唤醒单元。 两个 32 位寄存器(TR 和 DR)包含二进码十进数格式 (BCD) 的秒、分钟、小时(12 或24 小时制)、星期、日期、月份和年份。此外,还可提供二进制格式的亚秒值。 STM32F4 的 RTC 可以自动将月份的天数补偿为 28、29(闰年)、30 和 31 天。并且还可以进行夏令时 补偿。 RTC 模块和时钟配置是在后备区域,即在系统复位或从待机模式唤醒后 RTC 的设置和时间维持不变,只要后备区域供电正常,那么 RTC 将可以一直运行。但是在系统复位后,会自动禁止访问后备寄存器和 RTC,以防止对后备区域(BKP)的意外写操作。所以在要设置时间之前,先要取消备份区域(BKP)写保护。 02. 硬件设计 用到的硬件资源有: 1) 指示灯 DS0 2) 串口 3) TFTLCD 模块 4) RTC 03. RTC日历配置步骤 ①使能PWR时钟:RCC_APB1PeriphClockCmd(); ② 使能后备寄存器访问: PWR_BackupAccessCmd() ③ 配置RTC时钟源,使能RTC时钟: RCC_RTCCLKConfig(); RCC_RTCCLKCmd(); 如果使用LSE,要打开LSE:RCC_LSEConfig(RCC_LSE_ON); ④ 初始化RTC(同步/异步分频系数和时钟格式):RTC_Init (); ⑤ 设置时间:RTC_SetTime (); ⑥设置日期:RTC_SetDate(); 04. 设置和获取日期示例 rtc.h #ifndef __RTC_H__ #define __RTC_H__ #include "sys.h" //RTC初始化 u8 MY_RTC_Init(void); //RTC时间设置 ErrorStatus RTC_Set_Time(u8 hour, u8 min, u8 sec, u8 ampm); //RTC日期设置 ErrorStatus RTC_Set_Date(u8 year, u8 mon, u8 day, u8 week); #endif /*__RTC_H__*/ rtc.c #include "rtc.h" #include "delay.h" //RTC时间设置 ErrorStatus RTC_Set_Time(u8 hour, u8 min, u8 sec, u8 ampm) { RTC_TimeTypeDef RTC_TimeStruct; RTC_TimeStruct.RTC_H12 = ampm; RTC_TimeStruct.RTC_Hours = hour; RTC_TimeStruct.RTC_Minutes = min; RTC_TimeStruct.RTC_Seconds = sec; return RTC_SetTime(RTC_Format_BIN,&RTC_TimeStruct); } //RTC日期设置 ErrorStatus RTC_Set_Date(u8 year, u8 mon, u8 day, u8 week) { RTC_DateTypeDef RTC_DateStruct; RTC_DateStruct.RTC_Year = year; RTC_DateStruct.RTC_Month = mon; RTC_DateStruct.RTC_Date = day; RTC_DateStruct.RTC_WeekDay = week; return RTC_SetDate(RTC_Format_BIN, &RTC_DateStruct); } //RTC初始化 u8 MY_RTC_Init(void) { u16 retry = 0x1fff; RTC_InitTypeDef RTC_InitStruct; //使能PWR时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //使能后备寄存器访问 PWR_BackupAccessCmd(ENABLE); //判断是否第一次初始化 if (RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x8080) { //开启LSE RCC_LSEConfig(RCC_LSE_ON); //等待LSE准备就绪 while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) { retry++; delay_ms(10); } //开始LSE失败 if (0 == retry) { return 1; } //设置RTC时钟为LSE RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //使能RTC时钟 RCC_RTCCLKCmd(ENABLE); //初始化RTC RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24; RTC_InitStruct.RTC_AsynchPrediv = 0x7F; RTC_InitStruct.RTC_SynchPrediv = 0xFF; RTC_Init(&RTC_InitStruct); //设置时间 RTC_Set_Time(16, 06, 50, RTC_H12_AM); //设置日期 RTC_Set_Date(20, 9, 9, RTC_Weekday_Wednesday); //标记已经初始化 RTC_WriteBackupRegister(RTC_BKP_DR0, 0x8080); } return 0; } main.c #include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "beep.h" #include "key.h" #include "usmart.h" #include "lcd.h" #include "rtc.h" //LED状态设置函数 void led_set(u8 sta) { LED1 = sta; } //函数参数调用测试函数 void test_fun(void(*ledset)(u8), u8 sta) { ledset(sta); } int main(void) { u8 buf[40]; u8 t = 0; RTC_TimeTypeDef RTC_TimeStruct; RTC_DateTypeDef RTC_DateStruct; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2 delay_init(168); uart_init(115200); usmart_dev.init(84); LED_Init(); LCD_Init(); //RTC初始化 MY_RTC_Init(); POINT_COLOR = RED; LCD_ShowString(30,50,200,16,16,"Explorer STM32F4"); LCD_ShowString(30,70,200,16,16,"USMART TEST"); LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK"); LCD_ShowString(30,110,200,16,16,"2020/09/09"); while(1) { t++; //每隔100ms更新显示 if (0 == t % 10) { RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct); sprintf((char*)buf, "Time: %02d:%02d:%02d", RTC_TimeStruct.RTC_Hours, RTC_TimeStruct.RTC_Minutes, RTC_TimeStruct.RTC_Seconds); LCD_ShowString(30, 140, 210, 16, 16, buf); RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct); sprintf((char*)buf, "Date: 20%02d-%02d-%02d", RTC_DateStruct.RTC_Year, RTC_DateStruct.RTC_Month, RTC_DateStruct.RTC_Date); LCD_ShowString(30, 160, 210, 16, 16, buf); sprintf((char*)buf, "Week: %d", RTC_DateStruct.RTC_WeekDay); LCD_ShowString(30, 180, 210, 16, 16, buf); } if (0 == t % 20) { LED1 = !LED1; } //睡眠10毫秒 delay_ms(10); } } 05. 设置闹钟中断示例 //设置闹钟时间(按星期闹铃,24小时制) //week:星期几(1~7) @ref RTC_Alarm_Definitions //hour,min,sec:小时,分钟,秒钟 void RTC_Set_AlarmA(u8 week,u8 hour,u8 min,u8 sec) { RTC_TimeTypeDef RTC_TimeStruct; RTC_AlarmTypeDef RTC_AlarmStruct; EXTI_InitTypeDef EXTI_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; //关闭闹钟A RTC_AlarmCmd(RTC_Alarm_A, DISABLE); //设置闹钟参数 RTC_TimeStruct.RTC_H12 = RTC_H12_AM; RTC_TimeStruct.RTC_Hours = hour; RTC_TimeStruct.RTC_Minutes = min; RTC_TimeStruct.RTC_Seconds = sec; RTC_AlarmStruct.RTC_AlarmTime = RTC_TimeStruct; RTC_AlarmStruct.RTC_AlarmMask = RTC_AlarmMask_None; RTC_AlarmStruct.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_WeekDay; RTC_AlarmStruct.RTC_AlarmDateWeekDay = week; RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStruct); //清除闹钟A的中断标志 RTC_ClearITPendingBit(RTC_IT_ALRA); //清除中断线17上的中断标志 EXTI_ClearITPendingBit(EXTI_Line17); //开启闹钟A中断 RTC_ITConfig(RTC_IT_ALRA, ENABLE); //开启闹钟 RTC_AlarmCmd(RTC_Alarm_A, ENABLE); //初始化中断 EXTI_InitStruct.EXTI_Line = EXTI_Line17; EXTI_InitStruct.EXTI_LineCmd = ENABLE; EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_Init(&EXTI_InitStruct); //初始化中断优先级 NVIC_InitStruct.NVIC_IRQChannel = RTC_Alarm_IRQn; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x2; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x2; NVIC_Init(&NVIC_InitStruct); } //闹钟中断处理函数 void RTC_Alarm_IRQHandler(void) { if (RTC_GetFlagStatus(RTC_FLAG_ALRAF) == SET) { RTC_ClearFlag(RTC_FLAG_ALRAF); printf("ALARM A!rn"); } //清中断 EXTI_ClearITPendingBit(EXTI_Line17); } 06. 设置唤醒中断示例 //周期性唤醒定时器设置 /*wksel: @ref RTC_Wakeup_Timer_Definitions #define RTC_WakeUpClock_RTCCLK_Div16 ((uint32_t)0x00000000) #define RTC_WakeUpClock_RTCCLK_Div8 ((uint32_t)0x00000001) #define RTC_WakeUpClok_RTCCLK_Div4 ((uint32_t)0x00000002) #define RTC_WakeUpClock_RTCCLK_Div2 ((uint32_t)0x00000003) #define RTC_WakeUpClock_CK_SPRE_16bits ((uint32_t)0x00000004) #define RTC_WakeUpClock_CK_SPRE_17bits ((uint32_t)0x00000006) */ //cnt:自动重装载值.减到0,产生中断. void RTC_Set_WakeUp(u32 wksel,u16 cnt) { EXTI_InitTypeDef EXTI_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; //关闭WakeUP RTC_WakeUpCmd(DISABLE); //配置WakeUP时钟分频系数或者来源 RTC_WakeUpClockConfig(wksel); //设置WakeUP自动装载值 RTC_SetWakeUpCounter(cnt); //清除中断标志 RTC_ClearITPendingBit(RTC_IT_WUT); //清除中断线17上的中断标志 EXTI_ClearITPendingBit(EXTI_Line22); //开启WakeUP中断 RTC_ITConfig(RTC_IT_WUT, ENABLE); //使能WakeUp RTC_WakeUpCmd(ENABLE); //初始化中断 EXTI_InitStruct.EXTI_Line = EXTI_Line22; EXTI_InitStruct.EXTI_LineCmd = ENABLE; EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_Init(&EXTI_InitStruct); //初始化中断优先级 NVIC_InitStruct.NVIC_IRQChannel = RTC_WKUP_IRQn; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x2; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x2; NVIC_Init(&NVIC_InitStruct); } //唤醒中断处理函数 void RTC_WKUP_IRQHandler(void) { if (RTC_GetFlagStatus(RTC_FLAG_WUTF) == SET) { RTC_ClearFlag(RTC_FLAG_WUTF); LED2 = !LED2; } //清中断 EXTI_ClearITPendingBit(EXTI_Line22); } |
|
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
4130 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
3221 浏览 1 评论
2747 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
2175 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
14939 浏览 2 评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
3084浏览 4评论
stm32f4下spi+dma读取数据不对是什么原因导致的?
1894浏览 3评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
2064浏览 3评论
1976浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
2165浏览 3评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-2 02:36 , Processed in 0.526679 second(s), Total 42, Slave 35 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
512