完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
学习笔记:RTC时钟
1.什么是RTC (1) RTC是个独立的定时器。RTC拥有一个连续计数的计数器。 (2)注意:RTC模块和时钟配置系统(RCC_BDCR寄存器)工作在后备区域,系统断电或者复位不会影响RTC的设置和事件,所以可以利用此特性来制作万年历。系统复位后,自动禁止访问后备寄存器和RTC,防止意外操作。 2. RTC时钟源 (1)HSE时钟除以128 (2)LSE振荡器时钟:外部低速时钟(一般为32.767khz) (3)LSI振荡器时钟:一般为(40khz) 3.RTC中断 (1)秒中断 (2)闹钟中断 (3)溢出中断 4.RTC计数器 32位可编程计数器,4,294,967,296位。 5.RTC工作原理 a.分频区 b.计数比较区 c.各环节作用 RTC_PRL:在里面写入分频数据,将RTC_CLK分频 RTC_DIV:没经过一个周期,DIV减一。 TR_CLK:RTC_CLK经过RTC_PRL分频后的时钟周期 RTC_CNT:受到TR_CLK控制的32位计数器 RTC_ALR:可软件写入数据,当RTC_CNT与ALR数据相同时,触发闹钟中断。 注意 RTC内核独立与APB1接口,通过软件访问RTC相关寄存器时,只有在APB1时钟进行重新同步的RTC时钟的上升沿被更新。软件配置必须先等待寄存器同步标志位被1才可以读。 6.BKP 引用自STM32中文参考手册: 备份寄存器(BKP) 小容量产品是指闪存存储器容量在16K至32K字节之间的STM32F101xx、STM32F102xx和STM32F103xx微控制器。 中容量产品是指闪存存储器容量在64K至128K字节之间的STM32F101xx、STM32F102xx和STM32F103xx微控制器。 大容量产品是指闪存存储器容量在256K至512K字节之间的STM32F101xx和STM32F103xx微控制器。 互联型产品是指STM32F105xx和STM32F107xx微控制器。 除非特别说明,本章描述的模块适用于整个STM32F10xxx微控制器系列。 5.1 BKP简介 备份寄存器是42个16位的寄存器,可用来存储84个字节的用户应用程序数据。他们处在备份域里,当VDD电源被切断,他们仍然由VBAT维持供电。当系统在待机模式下被唤醒,或系统复位或电源复位时,他们也不会被复位。此外,BKP控制寄存器用来管理侵入检测和RTC校准功能。复位后,对备份寄存器和RTC的访问被禁止,并且备份域被保护以防止可能存在的意外的写操作。执行以下操作可以使能对备份寄存器和RTC的访问。 ● 通过设置寄存器RCC_APB1ENR的PWREN和BKPEN位来打开电源和后备接口的时钟 ● 电源控制寄存器(PWR_CR)的DBP位来使能对后备寄存器和RTC的访问。 7.配置RTC寄存器 1.查询RTOFF位,直到变1 2.置CNF为1,开始配置 3.开始操作 4.退出配置模式(清除标志位) 5.等待写操作完成 8.实例:用RTC配置一个闹钟 一):分析 1.RTC初始化 (1)。初始化BKP时钟: BKP时钟,pwr时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE); PWR_BackupAccessCmd(ENABLE); (2)。初始化RTC时钟 根据开发板选择相应时钟,一般的可选择lse时钟或者lsi时钟,在选择LSE时钟时,要先启动LSE时钟在RTC选择LSE时钟 example 引用LSI时钟(大约40khz) BKP_DeInit(); RCC_LSICmd(ENABLE);//使能LSI delay_ms(100); RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);//RTC时钟选择LSI RCC_RTCCLKCmd(ENABLE); (3)开启相应中断 a.开起中断要操作相应的RTC寄存器,所以要先等待上一次写完成 RTC_WaitForLastTask(); RTC_WaitForSynchro(); FOR EXAMPLE:开启秒中断和闹钟中断 RTC_WaitForLastTask(); RTC_WaitForSynchro(); RTC_ITConfig(RTC_IT_SEC,ENABLE);//秒中断 RTC_WaitForLastTask(); RTC_WaitForLastTask(); RTC_WaitForSynchro(); RTC_ITConfig(RTC_IT_ALR,ENABLE);//闹钟中断 RTC_WaitForLastTask(); (4)配置分频值 RTC_SetPrescaler(40000);//1hz (5)配置计数器的初始值 本例封装了一个函数来配置初始值 RTC_WaitForLastTask(); RTC_SETTIME(value);//³õʼ»¯¼ÆÊýÆ÷Öµ RTC_ExitConfigMode(); ******/ void RTC_SETTIME(u32 CounterValue) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE); PWR_BackupAccessCmd(ENABLE); RTC_SetCounter(CounterValue); RTC_WaitForLastTask(); } (6)init函数结束,但是还要配置中断函数 a. 中断分组 static void RTC_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; //RTCÈ«¾ÖÖÐ¶Ï NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //ÏÈÕ¼ÓÅÏȼ¶1λ,´ÓÓÅÏȼ¶3λ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //ÏÈÕ¼ÓÅÏȼ¶0λ,´ÓÓÅÏȼ¶4λ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //ʹÄܸÃͨµÀÖÐ¶Ï NVIC_Init(&NVIC_InitStructure); //¸ù¾ÝNVIC_InitStructÖÐÖ¸¶¨µÄ²ÎÊý³õʼ»¯ÍâÉèNVIC¼Ä´æÆ÷ } b.中断服务函数 (注意:中断服务函数是定义好的不可更改名称) void RTC_IRQHandler(void) { if(RTC_GetITStatus(RTC_IT_SEC)!=RESET)//秒中断 { RTC_GETTIME(); } if(RTC_GetITStatus(RTC_IT_ALR)==SET)//闹钟中断 { RTC_ClearITPendingBit(RTC_IT_ALR); ALARM(); } RTC_ClearITPendingBit(RTC_IT_SEC); RTC_WaitForLastTask(); } c.闹钟函数:ALARM(); 自己定义的函数,放在了beep.c中,作用就是让闹钟到时间后蜂鸣器嚎叫 void ALARM(void) { beep_con(1); delay_ms(1000); beep_con(0); } (7)闹钟配置 因为要写一个闹钟,所以要先配置相应寄存器 void RTC_SERALRM(u32 CounterValue)//ÄÖÖÓ { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE); PWR_BackupAccessCmd(ENABLE); RTC_SetAlarm(CounterValue); RTC_WaitForLastTask(); } 闹钟配置和时间初始化差不多,都要开启PWR和BKP时钟,然后设置值(u32型)然后等待写结束 (8)获取时间函数 我们要将时间显示在lcd屏幕上,做一个数据可视化处理,所以要将计数器中的值读出,并显示,因此定义了一个结构体 typedef struct { vu8 hour; vu8 min; vu8 sec; }_calendar_obj; extern _calendar_obj calendar; 然后通过获取计数器值经过计算赋予结构体值显示在LCD屏幕上 void RTC_GETTIME(void) { u32 time=0; RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE); PWR_BackupAccessCmd(ENABLE); time=RTC_GetCounter();//获取计数器值 calendar.hour=time/3600; calendar.min=(time%3600)/60; calendar.sec=(time%3600)%60; } (9)主函数 #include “stm32f10x.h” #include “lcd.h” #include “key.h” #include “stdio.h” #include “beep.h” #include “delay.h” #include “rtc.h” u32 TimingDelay = 0; void Delay_Ms(u32 nTime); void xianshisec(u8 val) { uint8_t temp[20]; sprintf(temp,“sec=%d”,val); LCD_DisplayStringLine(Line0,temp); } void xianshimin(u8 val) { uint8_t temp[20]; sprintf(temp,“min=%d”,val); LCD_DisplayStringLine(Line1,temp); } void xianshihour(u8 val) { uint8_t temp[20]; sprintf(temp,“hour=%d”,val); LCD_DisplayStringLine(Line2,temp); } //Main Body int main(void) { float num=0; int keya=0; u8 t=0; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); beep_init(); delay_init(); RTC_INIT(0x00000000); STM3210B_LCD_Init(); LCD_Clear(Blue); LCD_SetBackColor(Blue); LCD_SetTextColor(White); SysTick_Config(SystemCoreClock/1000); key_inite(); LCD_Clear(White); LCD_SetBackColor(White); Delay_Ms(1000); LCD_SetTextColor(Black); Delay_Ms(1000); RTC_SERALRM(0x00000005); while(1) { if(t!=calendar.sec) { t=calendar.sec; xianshisec(calendar.sec); xianshimin(calendar.min); xianshihour(calendar.hour); } delay_ms(10); } return 0; } // void Delay_Ms(u32 nTime) { TimingDelay = nTime; while(TimingDelay != 0); } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1771 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1070 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1935浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
728浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
568浏览 3评论
593浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
551浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 16:18 , Processed in 0.933968 second(s), Total 76, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号