完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
实时时钟(RTC)
概述 RTC(real-time clock),实时时钟是一个独立的时钟,RTC被使用时提供连续不断的技术,用这个功能可以提供时间或者日历服务。 可以计数到2的32次方 1.1 RTC使用的时钟 2.1 可以使用的中断 2.1 第一个中断可以选择到什么时间产生中断RTC_IT_ALR 2.2 第二个可以每秒产生一个中断RTC_IT_SEC 2.3 第三个是数据溢出时的中断信号,计数到了2的32次方RTC_IT_OW: @arg RTC_IT_ALR: Alarm interrupt @arg RTC_IT_SEC: Second interrupt @arg RTC_IT_OW: Overflow interrupt 2.4 RTC的中断配置函数 3.功能框图 可见RTC的核心是32位的可编程计数器,它的计数时机来自于APB1,我们来看一下APB1的时钟树 它可以有外部的LSE直接产生,或者HSE128分频,LSI内部震荡时钟。如果使用断电仍能计数的时钟,只能使用LSE。 它可以产生三个信号,分别是RTC_Second,RTC_OverFlow RTC_ALARM. 4.RTC的寄存器 4.1 控制寄存器 4.1.1 RTC控制寄存器高位(RTC_CRH) 这三个寄存器用来执行中断请求 我们相应的对应RTC的中断使能函数来看 fun 1. void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState) //可以带入上边所所述的三个中断 { if (NewState != DISABLE) { RTC-》CRH |= RTC_IT; } else { RTC-》CRH &= (uint16_t)~RTC_IT; } } RTC控制寄存器的低位 我们来看5标志位对应的库函数 fun 2. void RTC_WaitForLastTask(void) { /* Loop until RTOFF flag is set */ while ((RTC-》CRL & RTC_FLAG_RTOFF) == (uint16_t)RESET) { } } 对应来说,就是等待RTOFF操作完 4对应的库函数 fun 3 void RTC_EnterConfigMode(void) { /* Set the CNF flag to enter in the Configuration Mode */ RTC-》CRL |= RTC_CRL_CNF; } fun 4 void RTC_ExitConfigMode(void) { /* Reset the CNF flag to exit from the Configuration Mode */ RTC-》CRL &= (uint16_t)~((uint16_t)RTC_CRL_CNF); } fun 5 rsf寄存器 /** * @brief Waits until the RTC registers (RTC_CNT, RTC_ALR and RTC_PRL) * are synchronized with RTC APB clock. * @note This function must be called before any read operation after an APB reset * or an APB clock stop. * @param None * @retval None */ void RTC_WaitForSynchro(void) { /* Clear RSF flag */ RTC-》CRL &= (uint16_t)~RTC_FLAG_RSF; /* Loop until RSF flag is set */ while ((RTC-》CRL & RTC_FLAG_RSF) == (uint16_t)RESET) { } } 这里每当RTC_CNT寄存器和RTC_DIV寄存器由软件更新或清’0’时,此位由硬件置’1’。在APB1复位后,或APB1时钟停止后,此位必须由软件清’0’。要进行任何的读操作之前,用户程序必须等待这位被硬件置’1’,以确保RTC_CNT、RTC_ALR或RTC_PRL已经被同步。 0:寄存器尚未被同步; 1:寄存器已经被同步。 4.2 RTC预分频装载寄存器(RTC_PRLH/RTC_PRLL) /** * @brief Sets the RTC prescaler value. * @param PrescalerValue: RTC prescaler new value. * @retval None */ void RTC_SetPrescaler(uint32_t PrescalerValue) { /* Check the parameters */ assert_param(IS_RTC_PRESCALER(PrescalerValue)); RTC_EnterConfigMode(); /* Set RTC PRESCALER MSB word */ RTC-》PRLH = (PrescalerValue & PRLH_MSB_MASK) 》》 16; /* Set RTC PRESCALER LSB word */ RTC-》PRLL = (PrescalerValue & RTC_LSB_MASK); RTC_ExitConfigMode(); } 设置分频数,如果晶振是32768HZ,如果prescalervalue是32768,那么计数周期就是1s 4.3 /** * @brief Gets the RTC divider value. * @param None * @retval RTC Divider value. */ uint32_t RTC_GetDivider(void) { uint32_t tmp = 0x00; tmp = ((uint32_t)RTC-》DIVH & (uint32_t)0x000F) 《《 16; tmp |= RTC-》DIVL; return tmp; } 4.4 RTC计数器寄存器 (RTC_CNTH / RTC_CNTL) uint32_t RTC_GetCounter(void) { uint16_t tmp = 0; tmp = RTC-》CNTL; return (((uint32_t)RTC-》CNTH 《《 16 ) | tmp) ; } void RTC_SetCounter(uint32_t CounterValue) { RTC_EnterConfigMode(); /* Set RTC COUNTER MSB word */ RTC-》CNTH = CounterValue 》》 16; /* Set RTC COUNTER LSB word */ RTC-》CNTL = (CounterValue & RTC_LSB_MASK); RTC_ExitConfigMode(); } 4.5 RTC闹钟寄存器(RTC_ALRH/RTC_ALRL) /** * @brief Sets the RTC alarm value. * @param AlarmValue: RTC alarm new value. * @retval None */ void RTC_SetAlarm(uint32_t AlarmValue) { RTC_EnterConfigMode(); /* Set the ALARM MSB word */ RTC-》ALRH = AlarmValue 》》 16; /* Set the ALARM LSB word */ RTC-》ALRL = (AlarmValue & RTC_LSB_MASK); RTC_ExitConfigMode(); } 5.RTC使用 head file #ifndef _USER_RTC_H #define _USER_RTC_H /*头文件*/ #include “stm32f10x.h” /*宏定义*/ //选择时钟源 #define RTC_CLOCK_SOURCE_LSE //设置备份的寄存器 #define RTC_BKP_DXR BKP_DR1 //写入到备份寄存器的数据 #define RTC_BKP_DATA 0xa5a5 //北京地区的时间差 #define TIME_ZOOM (8) /*变量*/ struct rtc_time { int rtc_sec; int rtc_min; int rtc_hour; int rtc_day; int rtc_mon; int rtc_year; int rtc_wday; }; /*函数*/ uint8_t RTC_Configure(uint8_t is_set,uint32_t time); void RTC_GetYear(void); void RTC_GetMonth(void); void RTC_GetDay(void); void RTC_GetHour(void); void RTC_GetMinute(void); void RTC_GetSecond(void); void RTC_GetTime(void); #endif source file #include “user_rtc.h” /** *名称:RTC获取系统时间函数 *作者:陈冲 *时间:2018年12月 *版本:1.0 *更新:1.0:无 **/ //定义的到具体时间的时间 //定义的到具体时间的时间 static uint32_t all_second = 0; //读取寄存器的时间 static uint32_t year_second = 0; //计算到今年的1月1日 00:00是多少秒 static uint32_t month_second = 0; //计算到今年的某月的1日 00:00是多少秒 static uint32_t day_second = 0; //计算到今天的00:00是多少秒 static uint32_t hour_second = 0; //计算到今天这个小时00是多少秒 static uint32_t minute_second = 0; //计算到今天这个小时的这个分钟00是多少秒 //定义系统时间变量 struct rtc_time systime = { 0,0,0,1,1,2000,0 }; /* *name:void RTC_GetYear() *fun :获取当前年份 *para:void *ret :void */ void RTC_GetYear() { year_second = 0; for(systime.rtc_year = 1970;year_second《=all_second-366*60*60*24;systime.rtc_year ++) { if((systime.rtc_year %4 == 0 && systime.rtc_year %100!= 0)||systime.rtc_year%400 == 0) year_second+= 366*60*60*24; else year_second+= 365*60*60*24; } } /* *name:void RTC_GetMonth() *fun :获取当前月份 *para:void *ret :void */ void RTC_GetMonth() { month_second = 0; for(systime.rtc_mon = 1;month_second 《=all_second - year_second-31*24*60*60;systime.rtc_mon++) { switch(systime.rtc_mon) { case 1:case 3:case 5:case 7:case 8:case 10:case 12: month_second+=31*24*60*60;break; case 4:case 6:case 9:case 11: month_second+=30*24*60*60;break; case 2: if((systime.rtc_year%4 == 0 && systime.rtc_year %100!= 0)||systime.rtc_year%400 == 0) month_second+=29*24*60*60; else month_second+=28*24*60*60;break; } } } /* *name:void RTC_GetDay() *fun :获取当前日 *para:void *ret :void */ void RTC_GetDay() { day_second = 0; for(systime.rtc_day = 1;day_second《= all_second - year_second - month_second - 24*60*60 ;systime.rtc_day++) { day_second += 60*24*60; } } /* *name:void RTC_GetHour() *fun :获取当前小时 *para:void *ret :void */ void RTC_GetHour() { hour_second = 0; for(systime.rtc_hour = 0;hour_second《= all_second - year_second - month_second - day_second -60*60;systime.rtc_hour++) { hour_second += 60*60; } systime.rtc_hour+=TIME_ZOOM; } /* *name:void RTC_GetMinute() *fun :获取当前分 *para:void *ret :void */ void RTC_GetMinute() { minute_second = 0; for(systime.rtc_min = 0;minute_second《= all_second - year_second - month_second - day_second -hour_second-60;systime.rtc_min++) { minute_second += 60; } } /* *name:void RTC_GetSecond() *fun :获取当前秒,并刷新其他时间 *para:void *ret :void */ void RTC_GetSecond() { systime.rtc_sec = all_second - year_second - month_second - day_second -hour_second -minute_second; } /* *name:void RTC_GetSecond() *fun :刷新所有时间时间 *para:void *ret :void */ inline void RTC_GetTime() { all_second = RTC_GetCounter(); RTC_WaitForLastTask(); RTC_GetYear(); RTC_GetMonth(); RTC_GetHour(); RTC_GetDay(); RTC_GetMinute(); RTC_GetSecond(); } /* *name:uint8_t RTC_Configure(uint8_t is_set,uint32_t time) *fun :RTC初始化配置函数 *para:is_set:如果要设置当前的时间戳,将其设置为1,下一次设置为0 time:当前的时间戳 *ret :1 :数据没有丢失,0:数据丢失 */ uint8_t RTC_Configure(uint8_t is_set,uint32_t time) { NVIC_InitTypeDef NVIC_InitsStruct; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); NVIC_InitsStruct.NVIC_IRQChannel = RTC_IRQn; NVIC_InitsStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_InitsStruct.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitsStruct.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&NVIC_InitsStruct); uint8_t flag = 1; //检查数据是否丢失; if(BKP_ReadBackupRegister(RTC_BKP_DXR) != RTC_BKP_DATA || is_set == 1 ) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE); //允许访问backup区域 PWR_BackupAccessCmd(ENABLE); //复位backup区域 BKP_DeInit(); //打开外部晶振 RCC_LSEConfig(RCC_LSE_ON); //等待LSE准备好 while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET){} //使用外部晶振 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //使能RTC RCC_RTCCLKCmd(ENABLE); //等待外部时钟同步 RTC_WaitForSynchro(); RTC_WaitForLastTask(); RTC_SetPrescaler(32767); RTC_WaitForLastTask(); BKP_WriteBackupRegister(RTC_BKP_DXR,RTC_BKP_DATA); RTC_WaitForLastTask(); RTC_SetCounter(time); flag = 0; } RTC_ITConfig(RTC_IT_SEC,ENABLE); RTC_GetTime(); return flag; } /* *name:void RTC_IRQHandler(void) *fun :RTC中断服务程序 *para:is_set:void *ret :void */ /* #include “rtc.h” extern struct rtc_time systime; void RTC_IRQHandler(void) { if (RTC_GetITStatus(RTC_IT_SEC) != RESET) { // Clear the RTC Second interrupt RTC_ClearITPendingBit(RTC_IT_SEC); //RTC刷新时间 RTC_GetTime(); // Wait until last write operation on RTC registers has finished RTC_WaitForLastTask(); } } */ |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1752 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1611 浏览 1 评论
1052 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
721 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1666 浏览 2 评论
1924浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
711浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
560浏览 3评论
583浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
544浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-18 12:24 , Processed in 0.859011 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号