STM32 RTC时钟源LSE

发布者:luanzgc最新更新时间:2016-09-24 来源: eefocus关键字:STM32  RTC时钟源  LSE 手机看文章 扫描二维码
随时随地手机看文章
一开始,所有实验都是在神舟板上去完成,根本就没有发现RTC的问题。直到我们自己画板来后调试时,才发现STM32 RTC的外部时钟源存在问题。

这也算是STM32的一个鸡肋,对于LSE外部晶振太过于苛刻,手册上要求使用6pf,这个规格的晶振市场上太少,鱼龙混杂,中招的高手菜鸟不在少数。我们自己的板也是如此,几经波折,反反复复尝试使用不同的规格的晶振,替换外部的电容,电阻都没有能让这个32.768K的LSE起振。但是又需要有RTC来提供时间,考虑的方法主要有2种,第一采用外部RTC时钟芯片,如DS1302。第二是使用内部其它的时钟源来提供RTC时钟。毫无疑问,目前板已经制好,添加时钟芯片肯定造成板上布局更改,还得重新打板,这里采用了第二种方法。

查看STM32的手册上时钟树,如下:

除去不能起振的外部低速LSE外,可供使用的只有LSI和HSE的128分频,LSI这个是内部的40KHz RC振荡器,频率在30~60KHz浮动,自然这个不能用于RTC计时,误差太大。

我们的板上配的是STM32F107这款芯片,外部高速晶振是25MHz的。128分频后频率为 25000000 / 128 = 195312.5 Hz,很显然这里也不能做到很精确,有小许误差。

然后设置RTC_PRL寄存器,写入195312这个分频值,便可以得到1Hz的频率。使用HSE作为RTC时钟,缺点就是无法在断开电源后使用后备电池进行供电,维持RTC的正常。下次需要上位机重新去设置时间。

 

代码大致如下:

 
  1. void RTC_Configuration(void)  
  2. {  
  3.     u8 i = 0;  
  4.     /* Enable PWR and BKP clocks */  
  5.     /* PWR时钟(电源控制)与BKP时钟(RTC后备寄存器)使能 */  
  6.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);  
  7.   
  8.     /* Allow access to BKP Domain */  
  9.     /*使能RTC和后备寄存器访问 */  
  10.     PWR_BackupAccessCmd(ENABLE);  
  11.   
  12.     /* Reset Backup Domain */  
  13.     /* 将外设BKP的全部寄存器重设为缺省值 */  
  14.     BKP_DeInit();  
  15.   
  16.     /* Enable LSE */  
  17.     /* 使能LSE(外部32.768KHz低速晶振)*/  
  18.     RCC_LSEConfig(RCC_LSE_ON);  
  19.     
  20.     /* Wait till LSE is ready */  
  21.     /* 等待外部晶振震荡稳定输出 */  
  22.     TIM5_Init_Query(CALC_TYPE_MS); //ms 级别  
  23.     for (i = 0;i < 10;i++) //10次检测,如果LSE仍然没有起振,证明这玩意有问题,跳出循环  
  24.     {  
  25.         if (RCC_GetFlagStatus(RCC_FLAG_LSERDY) != RESET)  
  26.             break;  
  27.         TIM5_MS_CALC(1); //1ms延时  
  28.     }  
  29.     //while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET){}  
  30.     if (i == 10)  
  31.     {  
  32.         //RCC->CSR |= 0x1; //开启内部低速晶振  
  33.         //while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);  
  34.         //RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); //使用LSI提供RTC时钟  
  35.         //使用外部高速晶振 128分频  
  36.         RCC_RTCCLKConfig(RCC_RTCCLKSource_HSE_Div128);   
  37.     }else  
  38.     {  
  39.         /* Select LSE as RTC Clock Source */  
  40.         /*使用外部32.768KHz晶振作为RTC时钟 */                           
  41.         RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);  
  42.     }  
  43.   
  44.     /* Enable RTC Clock */  
  45.     /* 使能 RTC 的时钟供给 */  
  46.     RCC_RTCCLKCmd(ENABLE);  
  47.   
  48.     /* Wait for RTC registers synchronization */  
  49.     /*等待RTC寄存器同步 */  
  50.     RTC_WaitForSynchro();  
  51.   
  52.     /* Wait until last write operation on RTC registers has finished */  
  53.     /* 等待上一次对RTC寄存器的写操作完成 */  
  54.     RTC_WaitForLastTask();  
  55.   
  56.     /* Enable the RTC Second */  
  57.     /* 使能RTC的秒中断 */  
  58.     RTC_ITConfig(RTC_IT_SEC, ENABLE);  
  59.   
  60.     /* Wait until last write operation on RTC registers has finished */  
  61.     /* 等待上一次对RTC寄存器的写操作完成 */  
  62.     RTC_WaitForLastTask();  
  63.     
  64.     /* Set RTC prescaler: set RTC period to 1sec */  
  65.     /* 32.768KHz晶振预分频值是32767,如果对精度要求很高可以修改此分频值来校准晶振 */  
  66.     if (i != 10) //LSE不能正常  
  67.         RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */  
  68.     else  
  69.         RTC_SetPrescaler(195312); //25000000 / 128 = 195312.5,如果是8M / 128 = 62500,则这里应该填为62499  
  70.   
  71.     /* Wait until last write operation on RTC registers has finished */  
  72.     /* 等待上一次对RTC寄存器的写操作完成 */  
  73.     RTC_WaitForLastTask();  
  74. }  
  75.   
  76. void Init_RTC(void)  
  77. {  
  78.     /* 以下if...else.... if判断系统时间是否已经设置,判断RTC后备寄存器1的值 
  79.      是否为事先写入的0XA5A5,如果不是,则说明RTC是第一次上电,需要配置RTC, 
  80.      提示用户通过串口更改系统时间,把实际时间转化为RTC计数值写入RTC寄存器, 
  81.      并修改后备寄存器1的值为0XA5A5。 
  82.      else表示已经设置了系统时间,打印上次系统复位的原因,并使能RTC秒中断 
  83.     */  
  84.     if (BKP_ReadBackupRegister(BKP_DR1) != RTC_SEQ_ID)  
  85.     {  
  86.         /* Backup data register value is not correct or not yet programmed (when 
  87.            the first time the program is executed) */  
  88.       
  89.         /* RTC Configuration */  
  90.         RTC_Configuration();  
  91.   
  92.    
  93.         /* Adjust time by values entred by the user on the hyperterminal */  
  94.         RTC_SetCounter(Time_Regulate(YEAR_BASE,01,01,0,0,0)); //2008-1-1 0:0:0  
  95.         /* 修改后备寄存器1的值为0XA5A5 */  
  96.         BKP_WriteBackupRegister(BKP_DR1, RTC_SEQ_ID);  
  97.     }else  
  98.     {  
  99.         /* Check if the Power On Reset flag is set */  
  100.         //RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET  
  101.         //  printf("\r\n\n Power On Reset occurred....");  
  102.           
  103.         /* Check if the Pin Reset flag is set */  
  104.         //else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)  
  105.         //  printf("\r\n\n External Reset occurred....");  
  106.         if (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)  
  107.         {  
  108.             //RCC->CSR |= 0x1; //开启内部低速晶振  
  109.             //while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);  
  110.             //RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); //使用LSI提供RTC时钟  
  111.             //RCC_RTCCLKConfig(RCC_RTCCLKSource_HSE_Div128);  
  112.             RTC_Configuration();  
  113.         }  
  114.         //printf("\r\n No need to configure RTC....");  
  115.         /* Wait for RTC registers synchronization */  
  116.         RTC_WaitForSynchro();  
  117.   
  118.         /* Enable the RTC Second */  
  119.         RTC_ITConfig(RTC_IT_SEC, ENABLE);  
  120.       
  121.         /* Wait until last write operation on RTC registers has finished */  
  122.         RTC_WaitForLastTask();  
  123.     }  
  124.   
  125. #ifdef RTCClockOutput_Enable  
  126.   /* Enable PWR and BKP clocks */  
  127.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);  
  128.         
  129.   /* Allow access to BKP Domain */  
  130.   PWR_BackupAccessCmd(ENABLE);  
  131.   
  132.   /* Disable the Tamper Pin */  
  133.   BKP_TamperPinCmd(DISABLE); /* To output RTCCLK/64 on Tamper pin, the tamper 
  134.                                  functionality must be disabled */  
  135.   
  136.   /* Enable RTC Clock Output on Tamper Pin */  
  137.   BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);  
  138. #endif  
  139.   
  140.   /* Clear reset flags */  
  141.   RCC_ClearFlag();  
  142. }  


实际测试,RTC效果还行,然后配合上位机隔一定的时间后同步时间基本上能够满足要求。

万恶的LSE晶振,这东西简直不能忍受......

关键字:STM32  RTC时钟源  LSE 引用地址:STM32 RTC时钟源LSE

上一篇:stm32 ADC 非DMA方式
下一篇:用keil烧录stm32注意改地址

推荐阅读最新更新时间:2024-03-16 15:11

关于STM32串口的理解
总的来说,STM32单片机的串口还是很好理解的,编程也不算复杂。当然我更愿意希望其中断系统和51单片机一样的简单。 对于接收终端,就是RXNE了,这只在接收完成后才产生,在执行USART_ITConfig(USART1, USART_IT_RXNE, ENABLE)代码时不会进入ISR。但麻烦的就是发送有关的中断了:TXE或者TC,根据资料和测试的结果,TXE在复位后就是置1的,即在执行USART_ITConfig(USART1, USART_IT_TXE, ENABLE)后会立即产生中断请求。因此这造成一个麻烦的问题:如果没有真正的发送数据,TXE中断都会发生,而且没有休止,这将占用很大部分的C
[单片机]
STM32的窗口看门狗(WWDG)
一、窗口看门狗由从APB1时钟分频后得到时钟驱动。 通过可配置的时间窗口来检测应用程序非正常的过迟或过早操作。 窗口看门狗最适合那些要求看门狗在精确计时窗口起作用的程序。 二、什么是窗口看门狗? 窗口就是因为其喂狗时间是一个有上下限的范围内(窗口),你可以通过设定相关寄存器,设定其上限时间(下限固定)。喂狗的时间不能过早也不能过晚。 而独立看门狗限制喂狗时间在0-x内,x由相关寄存器决定。喂狗的时间不能过晚 三、窗口看门狗的好处 对于一般的看门狗,因为是在复位前的任意时刻刷新看门狗,但有可能程序跑乱了又跑回到正常的地方,或跑乱的程序正好执行了刷新看门狗操作,这样的情况下就检测不
[单片机]
<font color='red'>STM32</font>的窗口看门狗(WWDG)
基于STM32和CC2520的TinyOS移植方法
TinyOS系统以其组件结构模型、事件驱动、并发型等优点成为目前最受关注的无线传感器网络操作系统。但TinyOS不支持STM32和CC2 520芯片。因此在分析TinyOS基本原理、NesC编程语言实现机制及其编译过程的基础上,介绍了基于STM32和CC2520的TinyOS移植方法,完成了STM32的I/O组件、Timer组件、USART组件、SPI组件和CC2520芯片驱动的移植。在实现CC2520的基本通信功能基础上,实现简单MAC协议。最后测试了各组件的移植效果。实验测试结果表明,节点可以稳定可靠地通信。 无线传感器网络(Wireless Sensor Network,WSN)是一种应用相关的网络。需要对某些操
[单片机]
基于<font color='red'>STM32</font>和CC2520的TinyOS移植方法
STM32开发板基础教程(七) - ADC with DMA
下面来讲一下STM32的ADC应用。 先闲扯一点其他事情,是我自己的理解。 STM32的优点在哪里? 除去宣传环节,细细分析。 STM32时钟不算快,72MHZ, 也不能扩展大容量的RAM FLASH, 同样没有DSP那样强大的指令集。 它的优势在哪里呢? ---就在快速采集数据,快速处理上。 ARM的特点就是方便。 这个快速采集,高性能的ADC就是一个很好的体现, 12位精度,最快1uS的转换速度,通常具备2个以上独立的ADC控制器, 这意味着, STM32可以同时对多个模拟量进行快速采集, 这个特性不是一般的MCU具有的。 以上高性能的ADC,配合相对比较块的指令集和一些特色的算法支持, 就构成了STM32在电机控制上的强大特
[单片机]
STM32之CAN详解
简介:bxCAN有3个主要的工作模式:初始化模式、正常模式和睡眠模式。 当bxCAN处于睡眠模式,软件必须对CAN_MCR寄存器的INRQ位置’1’并且同时对SLEEP位清’0’,才能进入初始化模式。 有2种方式可以唤醒(退出睡眠模式)bxCAN:通过软件对SLEEP位清’1’,或硬件检测到CAN总线的活动。 1 bxCAN工作模式 bxCAN有3个主要的工作模式:初始化模式、正常模式和睡眠模式。 在硬件复位后,bxCAN工作在睡眠模式以节省电能,同时CANTX引脚的内部上拉电阻被激活。软件通过对CAN_MCR寄存器的INRQ或SLEEP位 置’1’,可以请求bxCAN进入初始化或睡眠模式。一旦进入了初始化或睡眠模
[单片机]
<font color='red'>STM32</font>之CAN详解
STM32_EXIT中断
今天的软件工程下载地址(360云盘): https://yunpan.cn/cPhvyer3vIwXh 访问密码 57e1 STM32F10x的资料可以在我360云盘下载: https://yunpan.cn/crBUdUGdYKam2 访问密码 ca90 工程概要说明:定义一个按键(可自己定义),每按键一次,响应中断一次,在中断函数中LED提示灯变化一次,用户可更加实际情况在中断函数做出相应操作,这里只是一个模板。 关于“STM32F103 EXIT中断” 我把重要的几点在下面分别讲述,若不明白,请关注微信公众号“EmbeddDeveloper”查阅或留言。 一、RCC时钟配置 该函数位于在bsp.c
[单片机]
STM32_EXIT中断
stm32的外设初始化步骤,以定时器为例。
我这个程序的目的在于让定时器开启更新中断,实现定时器1S中断一次然后在中断函数中LED电平翻转一次。 1.首先先开启这个外设的时钟:RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //开启定时器1 的时钟APB2 2.定义这个外设的初始化结构体:TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定时器模式初始化结构体 定义别名为TIM_TimeBaseInitStructure 3.把这个结构体内成员参数设置: TIM_TimeBaseInitStructure.TIM_Period = 999
[单片机]
ST 最新STM32 Primer开发工具可玩Maze和Breakout
完整、独立、预编程的评估工具套件,既有充满趣味性的功能介绍,又有严肃的开发工具,可以链接到在线开发社区 中国,2007年10月15日 — 意法半导体(纽约证券交易所代码:STM)今天推出了一套价格低廉的开发工具,这款代号为STM32 Primer开发工具是一套完整的学习与娱乐相结合的趣味性应用开发工具,用于ST的STM32系列基于具有突破性的ARM Cortex-M3内核的闪存微控制器。这套工具包含一个创新的用户界面、多个游戏和向新用户介绍该系列产品的产品入门功能,以及用于高级开发和编程的Raisonance软件工具。 STM32 Primer是一个手持评估开发工具,力图通过简单和有趣的介绍,让用户了解STM32的强大功能。紧
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved