读者们,大家好!
接着上一章多功能时钟(绪论)的内容,在这一章中,我将介绍多功能时钟的时钟显示部分。话不多说,我们正式开始吧~
多功能时钟,时钟显示功能是必不可少的。所以,我们利用stm32的定时器来计时。本来打算采用stm32的RTC实时时钟,但后来想,刚开始弄得时候,尽量简单一些,别一开始就给自己出难题,毕竟RTC实时时钟要配置的东西还挺多的。如果此次做得不错的话,后面可以再加RTC实时时钟。
stm32不同于51,共有11个定时器,其中2个高级控制定时器(TIM1和TIM8),4个普通定时器(TIM2~TIM5)和2个基本定时器(TIM6和TIM7),以及2个看门狗定时器和1个系统滴答定时器。这里,我们采用普通定时器TIM2,并且开启定时器的中断,中断时间为1s,并且在中断函数里,模拟时钟的计时功能。
(1)配置嵌套中断控制器NVIC
void tim2_nvic_config(void)
{
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级为2
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;//子优先级为0
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(NVIC_InitStruct);
}
这里,我们只需对NVIC_InitStruct结构体的每个元素赋值,其中TIM2_IRQn为定时器TIM2中断线,设置优先级组为2,即抢占优先级组为4组,这里抢占优先级为2,子优先级为0,然后使能NVIC(优先级不能理解上网查询)。
(2)定时器初始化配置
void tim2_config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
tim2_nvic_config(); //配置NVIC
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//开启时钟
TIM_DeInit(TIM2); //定时器2复位
TIM_TimeBaseInitStruct.TIM_Period = 2000-1; //自动重装载寄存器值
TIM_TimeBaseInitStruct.TIM_Prescaler = 36000-1; //时钟预分频数
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; //采样分频
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //计数模式
TIM_TimeBaseInit(TIM2, TIM_TimeBaseInitStruct); //初始化TIM2
TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除溢出中断标志
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE); //使能时钟
}
TIM2初始化,首先配置NVIC,打开TIM2时钟,复位TIM2。然后对TIM_TimeBaseInitStruct结构体的每个元素赋值。这里,主要阐述如何计算定时中断时间。定时器的溢出中断时间由TIM_Period和TIM_Prescaler来决定的。这里,我直接给出公式:发生中断时间=(TIM_Period+1)*(TIM_Prescaler+1)/FCLK,而FCLK为72M,所以定时1s,可以这样:TIM_Period=2000-1,TIM_Prescaler=36000-1;最后清除溢出中断标志,使能时钟即可计时。
(3)编写中断计时函数
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2 ,TIM_IT_Update)!=RESET)
{
sec++;
if(sec=60)
{
sec = 0;
min++;
if(min=60)
{
min = 0;
hour++;
if(hour=24)
{
hour = 0;
}
}
}
}
TIM_ClearITPendingBit(TIM2 ,TIM_FLAG_Update);
}
这里,先定义时、分、秒三个变量,然后在中断函数里,对时间变量的关系进行换算即可。
(4)编写时钟显示函数
这里,我们采用LCD12864实时显示。LCD12864的相关内容,我后面在LCD库函数章节中,会专门介绍的。这里,只将时间显示即可。
lcd_display_num_m(2, 16, hour/10);
lcd_display_num_m(2, 24, hour%10);
lcd_display_string(2,32,"时");
lcd_display_num_m(2, 48, min/10);
lcd_display_num_m(2, 56, min%10);
lcd_display_string(2,64,"分");
lcd_display_num_m(2, 80, sec/10);
lcd_display_num_m(2, 88, sec%10);
lcd_display_string(2,96,"秒");
LCD12864的驱动函数,我跟着黄老师的视频后面写的,在老师的基础上,增加了汉字字符串显示函数。这里,看成库函数即可,只需简单的调用,显示时间就行。
(5)按键调整时间
成功显示时间后,我们需要按键来调整时间。 我们需要设置时钟启/停键(K1),时间位选择键(K2),数值增加键(K3),数值减小键(K4)。
1.我们先对按键的GPIO进行配置,开启相应的时钟,选择相关引脚,设置浮空输入模式等。
void key_gpio_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*使能GPIO的RCC时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
/*配置PB11~PB14引脚*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB,GPIO_InitStructure);
}
2.配置好按键的GPIO口后,编写按键扫描函数,从而达到调整时间的功能。
u8 flag,mark;//flag为定时器启停标志位,mark为位选择标志位
//mark为0表示未选中,mark为1表示选择时位,mark为2表示选择分位,mark为3表示选择秒位
void keyscan(void)
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==RESET)
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==RESET)
{
flag = ~flag;
if(!flag)
{
TIM_Cmd(TIM2, ENABLE);
}
else
{
TIM_Cmd(TIM2, DISABLE);
mark = 0;
}
}while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==RESET);
}
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==RESET)
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==RESET)
{
mark = mark=3?0:mark+1;
}while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==RESET);
}
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==RESET)
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==RESET)
{
if(flag)
{
switch(mark)
{
case 1:hour = hour23?hour+1:0;break;
case 2:min = min59?min+1:0;break;
case 3:sec = sec59?sec+1:0;break;
default:break;
}
}
}while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==RESET);
}
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==RESET)
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==RESET)
{
if(flag)
{
switch(mark)
{
case 1:hour = hour0?hour-1:23;break;
case 2:min = min0?min-1:59;break;
case 3:sec = sec0?sec-1:59;break;
default:break;
}
}
}while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==RESET);
}
}
至此,我们完成了时钟显示的功能,当然,后期如果可以的话,我们可以使用stm32的RTC实时时钟资源,还可以设置闹钟、整点报时的功能。
本章,我主要介绍了如何利用stm32的TIM定时器和GPIO资源,实现时钟显示和按键调整的功能。下一章中,我将介绍如何利用DHT11模块来测量温度和湿度,从而实现系统对环境参量的获取。
STM32的RTC晶振经常出现不起振的问题,这已经是“业界共识”了。很多人在各种电子论坛上求助类似于“求高手指点!RTC晶振不起振怎么办”的问题,而其答案基本可以概括为“这次高手帮不了你了”
更有阴谋论者提出让人啼笑皆非的解释——STM32的RTC晶振不起振是ST与晶振厂商串通后故意搞出来的,目的是提高某晶振厂商高端晶振的销量。
最近做的几块板子也用到了STM32的RTC,前后两版一共做了大概6片,幸运的是并未遇到晶振不起振的现象。而我采用的是3毛钱一个的普通晶振,并未选用传说中低负载高精度晶振。后来在另外一片实验性质的板子上首次遇到了晶振不起振的问题,而且做了2片都不起振,这才让我意识到这个问题的严重性。
从上述现象来看,我认为对RTC晶振起振影响最大的因素应该是PCB的布线。但是遇到问题时通常是PCB已做好,甚至已经做了几百块,没有回头路了。于是大家更关注的问题似乎就是“如何补救”了。在网上搜索一下,你就会发现世界是如此美好!每个人的经验和建议都不一样,甚至是完全相反的!这种现象告诉我们,除了PCB布线,对晶振起振影响最大的似乎不是电气参数,而是另外一种不可忽略的因素——人品!
各种相互矛盾的经验也告诉我们,导致晶振不起振的原因是多种多样的,也是因“人”而异的。也许,我们无法找到一个绝对有效的经验一举解决STM32的RTC晶振这个让人头疼的问题,但我们可以从各种经验中找到一些线索,为最终摸索到适合自己这块板子的解决方案提供一些帮助和提示。
如果晶振不起振,尤其是你已经使用了传说中的爱普生6pF晶振后还是不行,也许你应该尝试对以下几个方面排列组合,找到适合你这块板子的,更容易起振的方式。
下面就罗列一下可能影响RTC晶振起振的因素
1. 晶振的品牌和负载电容
大家貌似都知道要用6pF的晶振,但我发现其实12.5pF的也可以用。大家都说KDS日本原装的好,我那个3毛钱的国产晶振貌似也没啥大问题。。。
2. 晶振外接的匹配电容
有人说6pF的晶振要配6pF的电容。但有经验公式指出这个电容的值应该是晶振本身负载电容的两倍,6pF的晶振应该配10pF的匹配电容,当然12.5pF的就应该配20pF或者22pF的电容了~电容值不匹配可能造成晶振不起振。更神奇的是,有人指出去掉外接的匹配电容会使晶振起振!这似乎没啥道理,但在我的板子上,有且仅有这个方案是可行的!!!
3. 晶振并联的反馈电阻
晶振可以并联一个高阻值的电阻,据说这样更容易起振。。。这个电阻的阻值有人说是1MΩ,有人说是5MΩ,也有人说是10MΩ,,,当然也有人说不能并联这个电阻,并联了反而不起振
4. XTALout到晶振间串联电阻
这种做法是官方的应用笔记指出的,而且给出了这个电阻的计算公式。对这个电阻的的必要性也是众说纷纭,同样存在两种矛盾的说法,即必须要有这电阻,否则不起振。还有一说不能有这个电阻,否则不起振。。。从官方的应用笔记来看,这个电阻的主要作用是保护晶振,以防晶振发热。由此看来这个这个电阻似乎并非影响晶振起振的主要因素,甚至可能让晶振更难起振。
5. 晶振的外壳是否接地
这个就不用说了吧。晶振的外壳是金属的,做封装时可以把那个焊盘做成机械焊盘而悬空,也可以做成电气焊盘,然后连接到GND。对这个说法同样存在争议,有人说外壳必须接地,也有人说接地后反而不起振。
6. 提高Vbat引脚的电源质量
这种说法是有一定道理的,因为RTC部分是由Vbat的来供电的。有人说Vbat引脚对电源质量要求比较高,如果纹波较大可能会影响晶振的起振。网上还有其他人验证过,直接上图(原贴链接: )

更有人说反而需要一些噪声,激励晶振产生正反馈从而顺利起振(本人对此表示呵呵)。但不管怎样,提高电源质量对大家都是好事。
7. 晶振周围的环境
有人指出应该仔细清洗RTC晶振周围的电路,甚至是使用环氧树脂胶将晶振密封起来。这种说法得到了一些人的支持,看来也是有相当多的事实依据。
8. 减少晶振焊接时加热的时间
有人认为长时间加热晶振进行焊接会对晶振本身带来影响,却不是彻底损坏晶振,从而使得晶振不容易起振。这种说法我没验证过,个人表示怀疑。。。
9. 焊接的焊锡量
这个种说法感觉就更不靠谱了,但真的有人在晶振引脚上多加了点焊锡晶振就能起振了。从原理上说,多加点焊锡确实会改变晶振和PCB间的寄生参数,但我感觉影响微乎其微。。。可能晶振已经徘徊在临界值的边缘了,这种做法才会起到一点作用。
10. 使用有源晶振
个人认为这是一劳永逸解决晶振不起振问题的不二法门!有人对STM32的RTC晶振不易起振的原因做了一个解释,即出于低功耗的考虑,STM32对晶振的驱动功率比较低,所谓“好鼓不用重锤”,一些差的晶振就需要更高的驱动功率,所以不易起振。我认为这种解释是有道理的。使用有源晶振则不存在驱动功率的问题,如果问题确实是因为驱动功率造成的,那使用有源晶振毫无疑问可以彻底解决问题。而且目前网上还没看到说有源晶振不起振的求助帖。但是有源晶振通常比较昂贵,甚至要比一颗外置的RTC芯片还要贵。至于这个问题的取舍,就要看各位看官自己的想法了。
转载:
参考:
STM32的RTC晶振不起振的原因及解决方法的更多相关文章
宏晶STC单片机使用STC-ISP串口烧录失败的原因与解决方法汇总
官方网址: 个人小结 芯片:STC12C5A60S2 封装:LQFP-48 晶振大小:SD22.1184M 最小系统 ...
单片机stm32F103单片机晶振不起振的原因分析
这是我在做单片机最小系统板时候碰到的问题,之前虽然也做过相似的板子,可是未曾出现过无源晶振不起振的问题.下面是我在遇到问题后的一些检查,排除问题的过程.本人小菜鸟一个,文章中如有错误和不足,还望各位大 ...
STM32的RTC中断标志只能手动清除
背景: 最近在做一个stm32的项目,其中用到RTC的实时时钟功能.时钟源采用外部32.768K晶振,时钟预分频设置为32767,目的是为了产生1秒的中断,然后在中断处理函数中更新实时年月日时分秒. ...
龙邱STM32单片机用J-LINK下载无法被识别的解决方法
问题如下: 按照正常步骤使用keil5给龙邱的stm32下载程序,SWD下载方式提示no cortex-m sw device found,JTAG方式提示no cortex-m device fou ...
STM32库函数void USART_SendData的缺陷和解决方法
void USART_SendData()函数在快速发送时存在问题 有丢数据的可能 转自 ...
STM32的Keil找不到想要flash的解决方法
STM32的Keil找不到想要flash的解决方法:
stm32 晶振不起振
1. STM32f103有内部晶振.刚刚上电时,所有Clock都是源于内部晶振,所以当片内没有程序或内部程序没有使能外部晶振时,外部晶振是不会起振的.2. STM32f103有内部复位电路,只有当检测 ...
(七)STM32的RTC简单操作
简单说明: /********************************************************************************************* ...
STM32之RTC配置与初始化-rtc.h rtc.c
rtc.h #include "stm32f10x.h" #ifndef _RTC_H #define _RTC_H typedef struct { vu8 ho ...
随机推荐
【错误收集】SVN冲突解决 标签: 错误收集 2016-03-13 08:44 624人阅读 评论(24) 收藏
最近在倒代码,这真的是一件挺低效率的事情的,但是为了之后工作的进行,必须把这些已经做好的界面,做好的功能搬到新的框架上来,所以安排了10来个同学一起倒代码,因为大家共用一个解决方案,所以使用svn来进 ...
LeetCode115 Distinct Subsequences
Given a string S and a string T, count the number of distinct subsequences of T in S. (Hard) A subse ...
WPF Binding ElementName方式无效的解决方法--x:Reference绑定
原文:WPF Binding ElementName方式无效的解决方法--x:Reference绑定 需求: 背景:Grid的有一个TextBlock name:T1和一个ListBox,ListBo ...
直击 KubeCon 现场 | 阿里云 Hands-on Workshop 亮点回顾
相关文章链接[合集]规模化落地云原生,阿里云亮相 KubeCon China沉淀九年,一文看清阿里云原生大事件 2019 年 6 月 24 日至 26 日,KubeCon + CloudNativeC ...
Linux 用户he用户组管理
8)系统中有一类用户称为伪用户(psuedo users). 这些用户在/etc/passwd 文件中也占有一条记录,但是不能登陆,因为他们的登陆shell 为空,他们的存在主要是方便系统管理,满足 ...
Round #590 (Div. 3)
拿DIV找快乐... 当场过了A-B1-B2-C 写D差5分钟写的是正解...留坑补FG A. Equalize Prices Again 直接判断sum%n==0?sum/n:sum/n+1 B1, ...
oracle函数 SYS_CONTEXT(c1,c2)
[功能]返回系统c1对应的c2的值.可以使用在SQL/PLSQL中,但不可以用在并行查询或者RAC环境中 [参数] c1,'USERENV' c2,参数表,详见示例 [返回]字符串 [示例] sele ...
@hdu - 6428@ Problem C. Calculate
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定 A, B, C,求: \[\sum_{i=1}^{A}\s ...
pytorch更新
Pytorch如何更新版本与卸载,使用pip,conda更新卸载Pytorch 2018年05月22日 07:33:52 醉雨轩Y 阅读数 19047 今天我们主要汇总如何使用使用ubuntu,C ...
H3C V.24接口线缆
RTC根据公式F=Frtcclk/(PRL[19:0]+1)来定义计数器的时钟频率,PRL[19:0]是RTC预分频装载寄存器,也就是你需要填的分频数,Frtcclk为RTC时钟源的频率,RTC有三个时钟源:1、HSE除以128;2、LSE振荡时钟;3、LSI振荡时钟;根据你所填的分频数大概可以判定你所选的RTC时钟源为LSE 32.768KHz,然后根据公式就可以算出你的计数器的时钟频率为32768/(32767+1)=1Hz,也就是每秒中断一次。说直接一点就是对RTC时钟源分频得到自己想要的一个时钟频率。
实时。英文缩写:RTC。显示年、月、日、时、分、秒、星期,自动计算闰年,能够区分每个月的天数。
RTC特点:能从RTC获取到具体的日期时间,断掉后再开机时间仍然准确。
RTC模块分为两种,一种集成在芯片内部,另外一种是外接RTC芯片。
芯片集成:
1.外设、模块功能
集成→直接用内部寄存器/寄存器配置
没有集成→外接模块
2.协议
集成
(USART,IIC,SPI…)直接用芯片内部控制器进行控制
没有集成
1.IO模拟。
2.芯片内有没有读写时序一致的协议
例: 8080协议→驱动屏幕,内部没有集成8080
FSMC:静态存储器,读写时序与8080一致
用FSMC模拟8080驱动屏幕
STM32内部实时时钟介绍
BCD:二进制的十进制码
BIN:二进制
HEX:十六进制
BCD码表示时间:
15:39
0001 0101:0011 1001
实时时钟 (RTC) 是一个独立的 BCD 定时器/计数器。 RTC 提供一个日历时钟、两个可编程闹钟中断,以及一个具有中断功能的周期性可编程唤醒标志。 RTC 还包含用于管理低功耗模式的自动唤醒单元。
两个 32 位寄存器包含二进码十进数格式 (BCD) 的秒、分钟、小时( 12 或 24 小时制)、星期几、日期、月份和年份。此外,还可提供二进制格式的亚秒值。
系统可以自动将月份的天数补偿为 28、 29(闰年)、 30 和 31 天。并且还可以进行夏令时(在夏季的某一天会在凌晨时分跳过一小时,而后会在冬季补回来)补偿。
其它 32 位寄存器还包含可编程的闹钟亚秒、 秒、分钟、小时、星期几和日期。此外,还可以使用数字校准功能对晶振精度的偏差进行补偿。
上电复位后,所有 RTC 寄存器都会受到保护,以防止可能的非正常写访问。
无论器件状态如何(运行模式、低功耗模式或处于复位状态),只要电源电压保持在工作范围内, RTC 便不会停止工作。
STM32内部实时时钟特点

RTC的电源部分

LSI,LSE,HSE 都可提供时钟给RTC,但对于某些器件来说,可能没有外部晶振提供时钟,所以最好使用内部低速时钟提供时钟源。


当主电源 VDD 断电时,可通过 VBAT (纽扣电池)电压为实时时钟 (RTC)、 RTC 备份寄存器和备份 SRAM(BKP SRAM) 供电。
访问RTCRTC备份域数据、需要按照以下步骤
将 RCC_APB1ENR 寄存器中的 PWREN 位置 2.使能电源接口时钟
电源控制器中的PWR_CR的DBP位值1(使能对备份域的访问)
选择RTC时钟源(LSI LSE HSE)
1.配置RCC_BDCR中的RTCSEL[1:0]、选择时钟源
2.如果选择了HSE、需要配置RCC_CFGR中的RTCPRE[4:0]位进行分频
对RCC_BDCR中的RTCCEN[15]位进行编程、使能RTC时钟
STM32内部实时时钟框架

RTC基本日历功能框架分析
基本日历功能主要就是让日历模块正常工作(1秒1秒地计数),我们从日历时间读取出当前实时时间日期。也就是说,日历的工作频率就是1HZ。

RTC寄存器写保护
上电复位后、所有的RTC寄存器受到写保护、取消写保护必须按照以下顺序将对应的密钥写入关键字寄存器(RTC_WPR)
1)0xCA写入RTC_WPR
2) 0x53写入 RTC_WPR
RTC进入初始化模式(设置日历寄存器要注意)
要编程包括时间格式和预分频器配置在内的初始时间和日期日历值,需按照以下顺序操作:
将 RTC_ISR 寄存器中的 INIT 位置 1 以进入初始化模式。在此模式下,日历计数器将停止工作并且其值可更新。
轮询 RTC_ISR 寄存器中的INITF 位。当 INITF置1时进入初始化阶段模式。大约需要2个RTCCLK 时钟周期(由于时钟同步)。
要为日历计数器生成 1 Hz 时钟,应首先编程 RTC_PRER 寄存器中的同步预分频系数,然后编程异步预分频系数。即使只需要更改这两个字段中之一,也必须对 RTC_PRER寄存器执行两次单独的写访问。
在影子寄存器( RTC_TR 和 RTC_DR)中加载初始时间和日期值,然后通过 RTC_CR寄存器中的 FMT 位配置时间格式( 12 或 24 小时制)。
通过清零 INIT 位退出初始化模式。随后,自动加载实际日历计数器值,在 4 个 RTCCLK时钟周期后重新开始计数。
RTC同步(读取日历值要注意)
每次将日历寄存器中的值复制到RTC_SSR、RTC_TR和RTC_DR影子寄存器时,RTC_ISR寄存器中的 RSF 位都会置1(日历影子寄存器已同步 )。每两个 RTCCLK 周期执行一次复制。为确保这 3 个值来自同一时刻点,读取 RTC_SSR 或 RTC_TR 时会锁定高阶日历影子寄存器中的值,直到读取RTC_DR。为避免软件对日历执行读访问的时间间隔小于 2 个 RTCCLK 周期:第一次读取日历之后必须通过软件将 RSF 清零,并且软件必须等待到 RSF 置 1 之后才可再次读取RTC_SSR、 RTC_TR 和 RTC_DR 寄存器。
/*
函 数 名:Rtc_Config
函数功能:实时时钟RTC初始化
返 回 值:无
形 参:无
备 注:
*/
void Rtc_Config(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE); //打开电源接口时钟
PWR_BackupAccessCmd(ENABLE); //启动寄存器访问
RCC_LSICmd(ENABLE); //打开LSI时钟
// RCC_LSEConfig(RCC_LSE_ON); //打开LSE时钟
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); //选择LSI时钟为RTC时钟源
RCC_RTCCLKCmd(ENABLE); //RTC时钟使能
RTC_WriteProtectionCmd(DISABLE); //取消写保护
RTC_EnterInitMode();
RTC_InitTypeDef rtc_InitTypeDef; //初始化结构体
rtc_InitTypeDef.RTC_AsynchPrediv = 0x7f; //异步分频
rtc_InitTypeDef.RTC_HourFormat = RTC_HourFormat_24; //24小时格式
rtc_InitTypeDef.RTC_SynchPrediv = 0xff; //同步分频
RTC_Init(rtc_InitTypeDef); //RTC初始化
Rtc_Set_Data(22,9,2,5);
Rtc_Set_Time(RTC_H12_PM,17,0,0);
RTC_ExitInitMode();
}
/*
函 数 名:Rtc_Set_Time
函数功能:设置初始时间
返 回 值:ErrorStatus 设置成功失败的标志
形 参:u8 h12,u8 hour,u8 min,u8 sec
备 注:
*/
ErrorStatus Rtc_Set_Time(u8 h12,u8 hour,u8 min,u8 sec)
{
RTC_TimeTypeDef rtc_TimeTypeDef; //时间结构体
rtc_TimeTypeDef.RTC_H12 = h12; //AM 或 24 小时制
rtc_TimeTypeDef.RTC_Hours = hour; //小时
rtc_TimeTypeDef.RTC_Minutes = min; //分钟
rtc_TimeTypeDef.RTC_Seconds = sec; //秒
return RTC_SetTime(RTC_Format_BIN,rtc_TimeTypeDef); //BIN格式,时间初始化
}
/*
函 数 名:Rtc_Set_Data
函数功能:设置初始日期
返 回 值:ErrorStatus 设置成功失败的标志
形 参:u8 year,u8 month,u8 date,u8 weekday
备 注:
*/
ErrorStatus Rtc_Set_Data(u8 year,u8 month,u8 date,u8 weekday)
{
RTC_DateTypeDef rtc_DateTypeDef; //日期结构体
rtc_DateTypeDef.RTC_Year = year; //年
rtc_DateTypeDef.RTC_Month = month; //月
rtc_DateTypeDef.RTC_Date = date; //日
rtc_DateTypeDef.RTC_WeekDay = weekday; //星期
return RTC_SetDate(RTC_Format_BIN,rtc_DateTypeDef); //BIN格式,日期初始化
}
/*
函 数 名:RTC_print
函数功能:时间打印
返 回 值:无
形 参:无
备 注:
*/
void RTC_print(void)
{
RTC_TimeTypeDef RTC_Time;
RTC_DateTypeDef RTC_Data;
RTC_GetTime(RTC_Format_BIN,RTC_Time);
RTC_GetDate(RTC_Format_BIN,RTC_Data);
printf("20%d年%d月%d日星期%d ",RTC_Data.RTC_Year,RTC_Data.RTC_Month,RTC_Data.RTC_Date,RTC_Data.RTC_WeekDay);
printf("%d:%d:%d\r\n",RTC_Time.RTC_Hours,RTC_Time.RTC_Minutes,RTC_Time.RTC_Seconds);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
RTC可编程闹钟
可编程闹钟介绍
RTC 单元提供两个可编程闹钟,即闹钟 A 和闹钟 B。
可通过将RTC_CR寄存器中的ALRAE和ALRBE位置1来使能可编程闹钟功能。如果日历亚秒、秒、分钟、小时、日期或日分别与闹钟寄存器 RTC_ALRMASSR/RTC_ALRMAR和RTC_ALRMBSSR/RTC_ALRMBR 中编程的值相匹配则 ALRAF 和 ALRBF 标志会被置为 1可通过RTC_ALRMAR 和 RTC_ALRMBR 寄存器的 MSKx 位以及 RTC_ALRMASSR和 RTC_ALRMBSSR 寄存器的 MASKSSx 位单独选择各日历字段。可通过 RTC_CR 寄存器中 的 ALRAIE 和 ALRBIE 位使能闹钟中断。
闹钟 A 和闹钟 B(如果已通过 RTC_CR 寄存器中的位 OSEL[0:1] 使能)可连接到 RTC_ALARM 输出。可通过 RTC_CR 寄存器的 POL 位配置 RTC_ALARM 极性。
编程闹钟
要对可编程的闹钟(闹钟 A 或闹钟 B)进行编程或更新,必须执行类似的步骤:
将 RTC_CR 寄存器中的 ALRAE 或 ALRBE 位清零以禁止闹钟 A 或闹钟 B。
轮询 RTC_ISR 寄存器中的 ALRAWF 或 ALRBWF 位,直到其中一个置 1,以确保闹钟
寄存器可以访问。大约需要 2 个 RTCCLK 时钟周期(由于时钟同步)。
编程闹钟 A 或闹钟 B 寄存器(RTC_ALRMASSR/RTC_ALRMAR 或 RTC_ALRMBSSR/
RTC_ALRMBR)。
将 RTC_CR 寄存器中的 ALRAE 或 ALRBE 位置 1 以再次使能闹钟 A 或闹钟 B。
闹钟中断

u8 alarm_flag;
/*
函 数 名:ALarm_Config
函数功能:RTC闹钟初始化
返 回 值:无
形 参:无
备 注:
*/
void ALarm_Config(u32 week)
{
RTC_AlarmCmd(RTC_Alarm_A,DISABLE); //关闭闹钟A
RTC_AlarmTypeDef rtc_AlarmTypeDef;
rtc_AlarmTypeDef.RTC_AlarmDateWeekDay = week;
rtc_AlarmTypeDef.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_WeekDay; //每固定星期报警
rtc_AlarmTypeDef.RTC_AlarmMask = RTC_AlarmMask_None; //与日历时间完全匹配
rtc_AlarmTypeDef.RTC_AlarmTime = Rtc_alarmA_time(RTC_H12_PM,17,0,10);
RTC_SetAlarm(RTC_Format_BIN,RTC_Alarm_A,rtc_AlarmTypeDef);
EXTI_InitTypeDef EXTI17_InitTypeDef;
EXTI17_InitTypeDef.EXTI_Line = EXTI_Line17; //外部中断线17
EXTI17_InitTypeDef.EXTI_LineCmd = ENABLE; //外部中断使能
EXTI17_InitTypeDef.EXTI_Mode = EXTI_Mode_Interrupt; //中断寄存器模式
EXTI17_InitTypeDef.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
EXTI_Init(EXTI17_InitTypeDef);
RTC_ITConfig(RTC_IT_ALRA,ENABLE); //打开ALARMA中断
NVIC_InitTypeDef nvic_InitTypeDef; //中断初始化
nvic_InitTypeDef.NVIC_IRQChannel = RTC_Alarm_IRQn; //中断号
nvic_InitTypeDef.NVIC_IRQChannelPreemptionPriority = 0; //占先优先级
nvic_InitTypeDef.NVIC_IRQChannelSubPriority = 2; //次级优先级
nvic_InitTypeDef.NVIC_IRQChannelCmd = ENABLE; //NVIC中断响应
NVIC_Init(nvic_InitTypeDef); //初始化NVIC中断
RTC_AlarmCmd(RTC_Alarm_A,ENABLE); //闹钟使能
}
/*
函 数 名:Rtc_alarmA_time
函数功能:设置闹钟时间
返 回 值:RTC_TimeTypeDef 闹钟时间结构体
形 参:u8 h12,u8 hour,u8 min,u8 sec,RTC_TimeTypeDef* RTC_TimeStruct
备 注:
*/
RTC_TimeTypeDef Rtc_alarmA_time(u8 h12,u8 hour,u8 min,u8 sec)
{
RTC_TimeTypeDef Alarm_Time;
Alarm_Time.RTC_H12 = h12;
Alarm_Time.RTC_Hours = hour;
Alarm_Time.RTC_Minutes = min;
Alarm_Time.RTC_Seconds = sec;
return Alarm_Time;
}
/*
函 数 名:RTC_Alarm_IRQHandler
函数功能:RTC闹钟中断服务函数
返 回 值:无
形 参:无
备 注:
*/
void RTC_Alarm_IRQHandler(void)
{
if(RTC_GetFlagStatus(RTC_FLAG_ALRAF))
{
RTC_ClearFlag(RTC_FLAG_ALRAF);
alarm_flag = 1;
}
EXTI-PR |= (0x01 17); //挂起寄存器写1清零
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
打开CSDN APP,看更多技术内容
STM32-RTC实时时钟_ONE_Day|的博客_stm32内置rtc可采用...
RTC时钟源有三种来源,分别是HSE的128分频,LSE时钟源,LSI时钟源,一般RTC选择的是LSE时钟源,也就是外部低速时钟源,外接一个32.768KHz的晶振,因为这个时钟源比较准确 RTC组成 APB1接口:用来和APB1总线相连。通过APB1接口可以访问RTC的相关...
继续访问
16.STM32RTC实时时钟知识与实验_stm32 rtc_普通的不普通少年的博客-CSD...
1.实时时钟 RTC是一个独立的BCD定时器/计数器。RTC提供一个日历时钟,两个可编程闹钟中断,以及一个具有中断功能的周期性可编程唤醒标志。RTC还包括用于管理低功耗模式的自动唤醒单元。 有两个32位的寄存器,包含二进制吗十进制格式BCD的...
继续访问
i2c_rtc.rar_dsp28335_iic rtc_iic 读取rtc实验
首先 通过模拟IIC接口,往RTC寄存器中写一个预设时间,再通过模拟IIc读取RTC寄存器中的时间,观察秒钟的变化情况。
i2c底层数据传输解析之RTC实时时钟
在i2c上进行数据传输,都是通过一个叫i2c_smbus_xfer的函数进行传输,这个函数被i2c_smbus函数族所调用,不同的i2c_smbus函数族的函数调用时都会传入一个i2c_smbus_xfer_emulated函数的switch中所需要的size,在case分支中将不同的数据写入i2c_msg结构体成员,然后执行i2c_smbus_xfer_emulated中的i2c_transfer,i2c_transfer最终调用了i2c_algorithm算法实现中的master_xfer周期性的发送i
继续访问
STM32实时时钟_面向offer编程的博客_获取clk时钟 stm32
STM32实时时钟 RTC(real time clock)实时时钟 STM32的RTC外设,实质是一个掉电后还继续运行的定时器,从定时器的角度来看,相对于通用定时器TIM外设,它的功能十分简单,只有计时功能(也可以触发中断).但是从掉电还能继续运行来看,它是STM...
继续访问
STM32之RTC实时时钟
RTC实时时钟简介: STM32的RTC外设,实质是一个掉电后还继续运行的定时器,从定时器的角度来看,相对于通用定时器TIM外设,它的功能十分简单,只有计时功能(也可以触发中断).但是从掉电还能继续运行来看,它是STM32中唯一一个具有这个功能功能的外设.(RTC外设的复杂之处不在于它的定时,而在于它掉电还可以继续运行的特性) 所谓掉电,是指电源Vpp断开的情况下,为了RTC外设掉电可以继续运行,必须给STM32芯片通过VBAT引脚街上锂电池.当主电源VDD有效时,由VDD给RTC外设供电.当VDD掉电后,
继续访问
【STM32】详解RTC实时时钟的概念和配置示例代码
RTC实时时钟
继续访问

STM32之RTC
简介:STM32 的实时时钟(RTC)是一个独立的定时器。STM32 的 RTC 模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。 框图: 相关寄存器: 控制寄存器 第 0 位是秒钟标志位,我们在进入闹钟中断的时候,通过判断这位来决定是不是发生了秒钟中断。然后必须通过软件将该位清零(写0) 第 3 位为寄存器同步标志位,我们在修改控制寄存器 RTC_CRH/CRL 之前,必须先判断该位,是否已经同步了,如果没有则等待同步,在没同步的情
继续访问

STM32基础10--实时时钟(RTC)
目录 前言 RTC框图 STM32实时时钟电路 功能需要 STM32CubeMx配置RTC 配置RCC 配置RTC 配置时间,闹钟,唤醒 开启中断 设置中断优先级 功能代码实现 STM32Cude生成RTC初始化 自定义触发闹钟次数变量 重写周期唤醒回调函数 重写闹钟中断函数 前言 在做51单片机项目时,如果需要年月日时分秒的时间记录,会在51单片机上面外挂一个DS1302的时钟芯片,再加上时间芯片的外围电路。但在STM32F407中,不再需...
继续访问

STM32精英版(正点原子STM32F103ZET6开发板)学习篇15——RTC实时时钟+备份区域BKP
摘抄自正点原子官方PPT 什么是RTC? RTC (Real Time Clock):实时时钟,是个独立的定时器。RTC模块拥有一个连续计数的计数器,在相应的软件配置下,可以提供时钟日历的功能。修改计数器的值可以重新设置当前时间和日期。 RTC模块和时钟配置系统(RCC_BDCR寄存器)是在后备区域(断电后还会工作),即在系统复位或从待机模式唤醒后RTC的设置和时间维持不变。但是在系统复位后,会自动禁止访问后备寄存器和RTC,以防止对后备区域(BKP)的意外写操作。所以在要设置时间之前, 先要取消备
继续访问

嵌入式--RTC实时时钟原理及相关库函数功能
嵌入式--RTC实时时钟原理及相关库函数功能
继续访问

STM32日历读取,设置和输出
一、了解时钟RTC RTC (Real Time Clock):实时时钟 RTC是个独立的定时器。RTC模块拥有一个连续计数的计数器,在相应的软件配置下,可以提供时钟日历的功能。修改计数器的值可以重新设置当前时间和日期 RTC还包含用于管理低功耗模式的自动唤醒单元。 在断电情况下 RTC仍可以独立运行 只要芯片的备用电源一直供电,RTC上的时间会一直走。 RTC实质是一个掉电后还继续运行的定时器,从定时器的角度来看,相对于通用定时器TIM外设,它的功能十分简单,只有计时功能(也可以触发中断)。但其高
继续访问

STM32基于固件库学习笔记(11)RTC实时时钟
使用RTC实时时钟的秒中断打印当前时间。(相当于使用简单的定时器每一秒中断打印时间)
继续访问

STM32:RTC实时时钟原理
STM32:RTC实时时钟原理
继续访问

DS1307实时时钟RTC读取(STM32)记录
最开始将函数从51单片机移植过来,如何整都读取出来的数据是65,不是实时时钟数据,查了下手册,发现必须4.5V-5.5V供电才可以,没有办法,跳线解决,但SCL与SDA采用3.3V+10K电阻上拉倒没有问题; 读取函数设置如下(PB12 PB13): //初始化IIC void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_...
继续访问
STM32-RTC实时时钟-毫秒计时实现
阅读目录 1、RTC时钟简介 2、软硬件设计 3、时钟配置与函数编写 4、秒钟计时原理 5、毫秒计时原理 6、修改时间 OS:Windows 64 Developmentkit:MDK5.14 IDE:UV4 MCU:STM32F103C8T6 回到顶部 1、RTC时钟简介 STM32的实时时钟(RTC)是一个独立的定时器,在相应软件配置下,可提供时钟日历的功能。 详细资料请参考ALIENTEK的官方文档——《STM32F1开发指南(精英版-库函数版)》,以下为博主摘录要..
继续访问
FPGA-使用RTC时钟芯片进行时钟读取(数码管显示)
做时钟显示如果用单片机做,会产生很大的累积误差,本程序采用时钟芯片PCF8563 一:芯片主要电气特性: 1)大工作电压范围:1.0~5.5V 2)400KHz 的 I2C 总线接口(VDD=1.8~5.5V 时)。 时钟频率最大400KH 3)i2C 总线从地址:读,0A3H;写,0A2H . 二:管脚 电路接线图: top.v: mod...
继续访问

51-DS1302实时时钟
51单片机
继续访问

STM32——实时时钟RTC的日历读取
STM32的 RTC 外设(Real Time Clock),实质是一个掉电后还继续运行的定时器。从定时器的角度来说,相对于通用定时器 TIM 外设,它十分简单,只有很纯粹的计时和触发中断的功能;但从掉电还继续运行的角度来说,它却是 STM32 中唯一一个具有如此强大功能的外设。所以 RTC 外设的复杂之处并不在于它的定时功能,而在于它掉电还继续运行的特性。STM32的 RTC 外设(Real Time Clock),实质是一个掉电后还继续运行的定时器。
继续访问

STM32CubeMX之RTC电子钟
RTC由两个主要部分组成(见下图)。第一部分(APB1 接口 )用来和APB1 总线相连。此单元还包含一组16位寄存器,可通过APB1 总线对其进行读写操作。APB1 接口由APB1 总线时钟驱动,用来与APB1 总线接口。另一部分(RTC核心)由一组可编程计数器组成,分成两个主要模块。第一个模块是RTC的预分频模块,它可编程产生最长为1 秒的RTC时间基准TR_CLK。RTC的预分频模块包含了一个20位的可编程分频器(RTC 预分频器)。
继续访问

最新发布 基于STM32实现RTC实时时钟
rtc实时时钟是一个很重要的内容,今天要配置的时RTC唤醒中断,它在很多地方都会被用到。今天需要配置的东西会有点多,代码长度也会比较长。实时时钟 (RTC) 是一个独立的 BCD 定时器/计数器。RTC 提供一个日历时钟、两个可编程 闹钟中断,以及一个具有中断功能的周期性可编程唤醒标志。RTC 还包含用于管理低功耗模式的自动唤醒单元。两个 32 位寄存器包含二进码十进数格式 (BCD) 的秒、分钟、小时(12 或 24 小时制)、星 期几、日期、月份和年份。此外,还可提供二进制格式的亚
本文标签:stm32f1时钟rtc程序