打印
[应用相关]

STM32——设置RTC的过程

[复制链接]
1147|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
小浣熊|  楼主 | 2015-1-25 13:11 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这两天一直在调试STM32的RTC部分,本来打算弄一个万年历的,但是现在看来是暂时实现不了了。为什么这样说,因为RTC对晶振的要求非常高,必须是6p负载电容的32768晶振,这种晶振很难买,而且还很贵。下面是摘自一位网友的话:

今天到电子市场找了一下,几乎都是12.5p负载电容的32768晶振,只有一家有少量,负载电容是6p,20ppm的晶振要价是12.5p晶振的5倍,而且从外观上也看不出来,也没有测试方法能测出负载电容是6p还是12.5p。卖晶振的老板在这行干了10几年,一说到6p的32768晶振就笑了。这个要求以前就有多个公司中过招,特别是DALLAS的片子,让一家公司吃尽了苦头,焊上的许多高精度12.5p晶振被迫全部换掉,订的数万只晶振也只能委托卖掉。老板说这种方式是IC厂家和大的晶振厂家联合的一个小阴谋,因为以前6p的晶振只有很少几个大厂家能做好,这样可以帮助大晶振厂家形成垄断。DALLAS的东西不敢恭维,向来卖得很贵,一片增强型的51经常还要卖四五十。

   6p的晶振既昂贵又不好采购,而且也难以辨认和测试。STM32这样设计实在是难以理喻。其它我们用过的所有涉及RTC的MCU和时钟芯片都不存在这个问题,如三星的44B0,2410,2440,飞利浦的LPC213x,LP214x等等。

   STM32是高度强调性价比的芯片,但是却在RTC晶振上给中小客户带来很大不必要的麻烦,既增加成本和采购难度,又留下致命的隐患(RTC启动死机)。特别是试样和试生产阶段,量又不大,怎么去专门订做?

   希望ST公司能正视这个问题,在以后的改进中修正这个问题,能支持12.5p的常规32768晶振。
调试了好长时间,我说怎么没有反应,原来是因为晶振的原因,而且电容必须接6PF,我用的是15P的电容,等待晶振起振的时间特别长(1分钟左右),开始我还以为是程序死在哪了呢!
后来程序是调通了,但是1S中断特别不准,我相信一定是因为晶振和电容的原因,先不管准不准,至少程序是调通了。把设置RTC的过程和大家分享:

还是将寄存器定义添加若头文件:
  • //*************************************************************
  • //PWR-Register
  • //*************************************************************
  • #define PWR_CR        (*((volatile unsigned long *)0x40007000))
  • #define PWR_CSR        (*((volatile unsigned long *)0x40007004))
  • //*******************************************************************
  • //
  • // RTC-Register
  • //
  • //*******************************************************************
  • #define RTC_CRH     (*((volatile unsigned long *)0x40002800))
  • #define RTC_CRL     (*((volatile unsigned long *)0x40002804))
  • #define RTC_PRLH    (*((volatile unsigned long *)0x40002808))
  • #define RTC_PRLL    (*((volatile unsigned long *)0x4000280C))
  • #define RTC_DIVH    (*((volatile unsigned long *)0x40002810))
  • #define RTC_DIVL    (*((volatile unsigned long *)0x40002814))
  • #define RTC_CNTH    (*((volatile unsigned long *)0x40002818))
  • #define RTC_CNTL    (*((volatile unsigned long *)0x4000281C))
  • #define RTC_ALRH    (*((volatile unsigned long *)0x40002820))
  • #define RTC_ALRL    (*((volatile unsigned long *)0x40002824))


复制代码


接下来就是RTC的寄存器配置:
  • void RTC_Configuration(void)
  • {
  • RCC_APB1ENR|=0x18000000;  //电源接口时钟使能, 备份接口时钟使能
  • PWR_CR|=0x00000100;//位8,允许访问RTC 寄存器和备份寄存器
  • RCC_APB1RSTR|=0x08000000;//位27 BKPRST 备份接口复位
  • RCC_BDCR|=0x00000001;     //位0 LSEON 外部低速振荡器使能
  • while(RCC_BDCR&0x00000002==0); // 位1 LSERDY 外部低速振荡器可用
  •   RCC_BDCR|=0x00000100; //选择LSE位RTC时钟
  •   RCC_BDCR|=0x00008000; //位15 RTCEN RTC 时钟使能
  • RTC_CRL|=0x10;   //位4 配置标志,1: 进入配置模式
  • while(RTC_CRL&0x04==0);   //位3 RSF: 寄存器同步标志
  • while(RTC_CRL&0x20==0); //位5, 在RTC 寄存器上最近一次写操作已经完成
  • RTC_CRH=0x01;//使能1S中断
  • while(RTC_CRL&0x20==0);  //位5, 在RTC 寄存器上最近一次写操作已经完成
  • RTC_PRLL=0xFF;//(1S中断应该是32767,但我的晶振不准,0xFF都是1S多)
  • while(RTC_CRL&0x20==0);  //位5,在RTC 寄存器上最近一次写操作已经完成
  • RTC_CRL&=0xFFEF; //位4,退出配置模式(开始更新RTC 寄存器).
  • SETENA0|=0x00000008;    //允许RTC中断
  • }
  • RTC中断处理函数:
  • void RTC_IRQHandler(void)
  • {
  • if(RTC_CRL&0x01==1) //查询1S中断标志
  • {
  •   RTC_CRL&=0xFFFE; // 1S中断标志清除
  •   if(IO_flag==0)   //1S,LED闪烁一次
  • {
  •   GPIO_PORTB_ODR|=(1<<5);
  •   IO_flag=1; // IO_flag为自己设的一个全局变量,用于LED取反
  • }
  • else {    GPIO_PORTB_ODR&=~(1<<5);
  •        IO_flag=0;
  •        }
  • }
  • }
  • int main()
  • {
  • SystemInit0();    //系统(时钟)初始化
  • stm32_GpioSetup (); //GPIO初始化
  • RTC_Configuration();//RTC配置
  • while(1)
  • {
  • }
  • }





沙发
zh113214| | 2015-1-25 15:20 | 只看该作者
很详细啊

使用特权

评论回复
板凳
waszyaw| | 2015-1-26 08:52 | 只看该作者
楼上的用的是STM32F几的? 我用的是STM32F0的RTC,进度要求不太高。我通讯部分超时用到了这个RTC,5秒超时。RTC的中断没有打开。晶振匹配电容现在用的是10pF。通讯部分老是隔会儿,大概20分钟左右,就会报通讯故障。是不是跟这RTC有关?现在还不清楚,一直查找毛病。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

528

主题

2095

帖子

8

粉丝