打印
[STM32F0]

STM32F0 RTC晶振

[复制链接]
8674|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Cheribat|  楼主 | 2015-1-9 23:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 Cheribat 于 2015-1-14 18:52 编辑

    本人是STM32的铁粉,但这次的问题如果得不到合理的解决,可能会直接导致以后不再用ST的东西。
  应该还是当初了解的不够全面,用了ST的RTC,虽说有人在论坛里说F0的RTC改善了一些,但我这几天几乎没睡好觉,问题也没能解决。产品已经量产了,交期非常紧,此刻压在心头的就是这个RTC晶振。
  其实第一批做样板的时候就出现了很不准的情况,做了两片板子,出现1分钟快4秒左右,也有的时候跑的飞快,正常速度的好几倍。当时用的12.5pF的贴片晶振,10pF的起振电容。后来试了很多次之后将起振电容和晶振重焊了之后,奇迹般地准确无误了,所以以为是自己没焊好的缘故。直到那两块板子神奇的死机再重焊才意识到问题的严重性。
  重新做了七块样板,无一起振,和之前同一批的PCB,试了12.5pF晶振,分别配5pF,10pF,20pF起振电容,同时买了新的6pF晶振,配5pF,10pF晶振,均无法工作。
  具体的问题还在进一步排查中,但对ST的感觉却一落千丈了。可能有朋友会吐槽了,如果你大批量做过与STM32的RTC有关的实际产品而且可靠性很好的话,欢迎评论及指教,我一定虚心学习,如果没有的话,我只是发表个人看法,请暂时不要说话,因为我心情很差。
  ST的技术支持做的实在太差。每次ADI的有遇到问题就直接给他们客服电话,态度极好,而且有时候他们的FAE不是很懂,弄懂之后也会马上给我回电话。TI的FAE虽说有时候不是很专业,但好歹可以一起讨论一下。给ST上海分公司打电话,人家就会说,我们不提供技术支持,有问题联系供应商。我想这就是差距,为什么ADI的产品那么贵,我们依然很愿意用。
  扯远了,心情很差,为了这件事明后两天的周末还要加班。
  用的型号STM32F051C8T6。明天排查是否是电源纹波的影响。压力山大。如果有朋友有解决类似问题的实际经验,欢迎指教,不胜感激。
------------------------------------------------------------------------------------------------------------------
RTC问题后续
  1 单独测试RTC功能正常
       2 增加其他功能后,5块样板中有一块可正常工作,异常的样板中有一块1分钟快4秒,其他三块很混乱。
       3 将中断初始化配置中中断优先级修改后,5块均可正常工作。还在进一步测试中。







沙发
gonggu8181| | 2015-1-10 21:37 | 只看该作者
有道理

使用特权

评论回复
板凳
gonggu8181| | 2015-1-10 21:38 | 只看该作者
用st的人这么多,不差lz一个人。

使用特权

评论回复
地板
Cheribat|  楼主 | 2015-1-11 21:02 | 只看该作者
gonggu8181 发表于 2015-1-10 21:38
用st的人这么多,不差lz一个人。

哈哈 说的是啊

使用特权

评论回复
5
b275163com| | 2015-1-12 08:19 | 只看该作者
我也在用F051C8,RTC是非常好的,12.5PF的晶体,运行很好。极端测试,即使将晶体短路,也可以恢复到正常工作。
1)建议看看是不是晶体的问题;
2)将051的RTC驱动能力设置到最大;
从另外的方面想,如果F051的RTC有如此大的问题,他们的工程师一定比你还急,而不会将同样的结构用在F0全序列,还有就是F3全序列
对自己保持信心,对我们用的芯片保持信心!

使用特权

评论回复
6
清风致影| | 2015-1-12 09:42 | 只看该作者
建议RTC晶振不接电容,如果有误差直接软件校正

使用特权

评论回复
7
Cheribat|  楼主 | 2015-1-12 11:51 | 只看该作者
b275163com 发表于 2015-1-12 08:19
我也在用F051C8,RTC是非常好的,12.5PF的晶体,运行很好。极端测试,即使将晶体短路,也可以恢复到正常工 ...

亲 可以把代码发过来 我这边对比一下么 
我之前用12.5pF的晶振做的两片也是可以的 但后来的就不行了 保险起见 现在都换了6pF的晶振

使用特权

评论回复
8
Cheribat|  楼主 | 2015-1-12 11:53 | 只看该作者
清风致影 发表于 2015-1-12 09:42
建议RTC晶振不接电容,如果有误差直接软件校正

这是不现实的 我这边有几百块板子 而且现象并不是完全一样

使用特权

评论回复
9
b275163com| | 2015-1-12 13:16 | 只看该作者
配置:
//-----   option_reload_rtc____pro / rtc____配置重栽    -----
void  option_reload_rtc____pro( void )
  {
    if(   ( ( RTC->CR   & dRTC_CR_and   ) != dRTC_CR    )
       || ( ( RTC->PRER & dRTC_PRER_and ) != dRTC_PRER  ) )
      {
        RTC->WPR = 0xCA;
        RTC->WPR = 0x53;
        
        RTC->CR   = dRTC_CR;
        RTC->PRER = dRTC_PRER;
      }         

    RTC->WPR = 0xFF;               
  }
//-----   RTC  -----                                             
#define dRTC_CR         ((u32)(   0X00                  \
                                                        ))
#define dRTC_CR_and     ((u32)(   RTC_CR_COE            \
                                | RTC_CR_OSEL           \
                                | RTC_CR_POL            \
                                | RTC_CR_COSEL          \
                                | RTC_CR_TSE            \
                                | RTC_CR_ALRAIE         \
                                | RTC_CR_ALRAE          \
                                | RTC_CR_FMT            \
                                | RTC_CR_BYPSHAD        \
                                | RTC_CR_REFCKON        \
                                | RTC_CR_TSEDGE         \
                                                        ))

#define dRTC_PRER       ((u32)(   0X007F00FF            \
                                                        ))
#define dRTC_PRER_and   ((u32)(   RTC_PRER_PREDIV_A     \
                                | RTC_PRER_PREDIV_S     \
                                                        ))


读取部分:
//-----     system_firmware_RtcRead_pro / 系统固件_RtcRead      -----
void  system_firmware_RtcRead_pro( void )
  {                                                         // Tb:  16ms                 
u32 wBuff,wBuff1;

//  if( s_uHmi.bSetting == _False )
      {
        wBuff = RTC->TR;
                                                            // 整点报时
        if( (( wBuff & 0x7f7f ) == 0     )
          &&( sSystemFirmWare.cRtcHour>7 )
          &&( sSystemFirmWare.cRtcHour<22))
          {
            suHmi.bBuzzerShortActive = _True;
          }
   
        wBuff1 = (((wBuff>>20)&0x3)*10+((wBuff>>16)&0xf));      sSystemFirmWare.cRtcHour = wBuff1;
        wBuff1 = (((wBuff>>12)&0x7)*10+((wBuff>> 8)&0xf));      sSystemFirmWare.cRtcMin  = wBuff1;
        wBuff1 = (((wBuff>> 4)&0x7)*10+((wBuff>> 0)&0xf));      sSystemFirmWare.cRtcSec  = wBuff1;
      }
  }

供你参考

使用特权

评论回复
10
wxh0000mm| | 2015-1-12 13:37 | 只看该作者
我也在用STM32F051C8T6   RTC没出现楼主说的那种现象

使用特权

评论回复
11
Cheribat|  楼主 | 2015-1-12 16:44 | 只看该作者
wxh0000mm 发表于 2015-1-12 13:37
我也在用STM32F051C8T6   RTC没出现楼主说的那种现象

RTC部分配置代码有吗 我对比一下

使用特权

评论回复
12
Cheribat|  楼主 | 2015-1-12 16:49 | 只看该作者
我这边用的STM32F0xx_StdPeriph_LibV1.4.0库中的RTC_Calendar代码修改的,亲们帮忙看下哪里有问题
#include "rtc.h"
#include "stdio.h"

uint32_t AsynchPrediv = 0, SynchPrediv = 0;

/**
  * @brief  Configure the RTC peripheral by selecting the clock source.
  * @param  None
  * @retval None
  */
void RTC_Config(void)
{
  /* Enable the PWR clock */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

  /* Allow access to RTC */
  PWR_BackupAccessCmd(ENABLE);
   
#if defined (RTC_CLOCK_SOURCE_LSI)  /* LSI used as RTC source clock*/
/* The RTC Clock may varies due to LSI frequency dispersion. */   
  /* Enable the LSI OSC */
  RCC_LSICmd(ENABLE);

  /* Wait till LSI is ready */  
  while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
  {
  }

  /* Select the RTC Clock Source */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
  
  SynchPrediv = 0x18F;
  AsynchPrediv = 0x63;

#elif defined (RTC_CLOCK_SOURCE_LSE) /* LSE used as RTC source clock */
  /* Enable the LSE OSC */
  RCC_LSEConfig(RCC_LSE_ON);

  /* Wait till LSE is ready */  
  while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
  {
  }

  /* Select the RTC Clock Source */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
  
  SynchPrediv = 0xFF;
  AsynchPrediv = 0x7F;

#else
  #error Please select the RTC Clock source inside the main.c file
#endif /* RTC_CLOCK_SOURCE_LSI */
  
  /* Enable the RTC Clock */
  RCC_RTCCLKCmd(ENABLE);

  /* Wait for RTC APB registers synchronisation */
  RTC_WaitForSynchro();
}

void RTC_TimeRegulate(void)
{
  RTC_TimeTypeDef RTC_TimeStructure;
//  RTC_AlarmTypeDef  RTC_AlarmStructure;
  uint32_t tmp_hh = 0xFF, tmp_mm = 0xFF, tmp_ss = 0xFF;

//  printf("\n\r==============Time Settings=====================================\r\n");
  RTC_TimeStructure.RTC_H12     = RTC_H12_AM;
//  printf("  Please Set Hours:\r\n");
  while (tmp_hh == 0xFF)
  {
//    tmp_hh = USART_Scanf(23);
//                tmp_hh = 11;
    RTC_TimeStructure.RTC_Hours = 11;
  }
//  printf("  %0.2d\r\n", tmp_hh);
  
//  printf("  Please Set Minutes:\r\n");
  while (tmp_mm == 0xFF)
  {
//    tmp_mm = USART_Scanf(59);
//                tmp_mm = 48;
    RTC_TimeStructure.RTC_Minutes = 42;
  }
//  printf("  %0.2d\r\n", tmp_mm);
  
//  printf("  Please Set Seconds:\r\n");
  while (tmp_ss == 0xFF)
  {
//    tmp_ss = USART_Scanf(59);
//                tmp_ss = 0;
    RTC_TimeStructure.RTC_Seconds = 30;
  }
//  printf("  %0.2d\n\r", tmp_ss);

  /* Configure the RTC time register */
  if(RTC_SetTime(RTC_Format_BIN, &RTC_TimeStructure) == ERROR)
  {
//    printf("\n\r>> !! RTC Set Time failed. !! <<\r\n");
  }
  else
  {
//    printf("\n\r>> !! RTC Set Time success. !! <<\r\n");
    RTC_TimeShow();
    /* Indicator for the RTC configuration */
    RTC_WriteBackupRegister(RTC_BKP_DR0, BKP_VALUE);
  }

  tmp_hh = 0xFF;
  tmp_mm = 0xFF;
  tmp_ss = 0xFF;

  /* Disable the Alarm A */
/*  RTC_AlarmCmd(RTC_Alarm_A, DISABLE);

  printf("\n\r==============Alarm A Settings=====================================\n\r");
//  RTC_AlarmStructure.RTC_AlarmTime.RTC_H12 = RTC_H12_AM;
  printf("  Please Set Alarm Hours:\n\r");
  while (tmp_hh == 0xFF)
  {
    tmp_hh = USART_Scanf(23);
    RTC_AlarmStructure.RTC_AlarmTime.RTC_Hours = tmp_hh;
  }
  printf("  %0.2d\n\r", tmp_hh);
  
  printf("  Please Set Alarm Minutes:\n\r");
  while (tmp_mm == 0xFF)
  {
    tmp_mm = USART_Scanf(59);
    RTC_AlarmStructure.RTC_AlarmTime.RTC_Minutes = tmp_mm;
  }
  printf("  %0.2d\n\r", tmp_mm);
  
  printf("  Please Set Alarm Seconds:\n\r");
  while (tmp_ss == 0xFF)
  {
    tmp_ss = USART_Scanf(59);
    RTC_AlarmStructure.RTC_AlarmTime.RTC_Seconds = tmp_ss;
  }
  printf("  %0.2d", tmp_ss);
*/
  /* Set the Alarm A */
//  RTC_AlarmStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;
//  RTC_AlarmStructure.RTC_AlarmDateWeekDay = RTC_Weekday_Monday;   
//  RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay;

  /* Configure the RTC Alarm A register */
//  RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStructure);
//  printf("\n\r>> !! RTC Set Alarm success. !! <<\n\r");
//  RTC_AlarmShow();

  /* Enable the RTC Alarm A Interrupt */
//  RTC_ITConfig(RTC_IT_ALRA, ENABLE);
   
  /* Enable the alarm  A */
//  RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
}

/**
  * @brief  Display the current time on the Hyperterminal.
  * @param  None
  * @retval None
  */
void RTC_TimeShow(void)
{
  RTC_TimeTypeDef RTC_TimeStructure;
  /* Get the current Time */
  RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);
  printf("\n\r  The current time is :  %0.2d:%0.2d:%0.2d \n\r", RTC_TimeStructure.RTC_Hours, RTC_TimeStructure.RTC_Minutes, RTC_TimeStructure.RTC_Seconds);
}


uint8_t USART_Scanf(uint32_t value)
{
  uint32_t index = 0;
  uint32_t tmp[2] = {0, 0};

  while (index < 2)
  {
    /* Loop until RXNE = 1 */
    while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET)
    {}
    tmp[index++] = (USART_ReceiveData(USART1));
    if ((tmp[index - 1] < 0x30) || (tmp[index - 1] > 0x39))
    {
      printf("\n\r Please enter valid number between 0 and 9 \n\r");
      index--;
    }
  }
  /* Calculate the Corresponding value */
  index = (tmp[1] - 0x30) + ((tmp[0] - 0x30) * 10);
  /* Checks */
  if (index > value)
  {
    printf("\n\r Please enter valid number between 0 and %d \n\r", value);
    return 0xFF;
  }
  return index;
}

void RTC_Initial(void)
{
        if (RTC_ReadBackupRegister(RTC_BKP_DR0) != BKP_VALUE)
  {  
                RTC_InitTypeDef RTC_InitStructure;
    /* RTC configuration  */
    RTC_Config();

    /* Configure the RTC data register and RTC prescaler */
    RTC_InitStructure.RTC_AsynchPrediv = AsynchPrediv;
    RTC_InitStructure.RTC_SynchPrediv = SynchPrediv;
    RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_12;
   
    /* Check on RTC init */
    if (RTC_Init(&RTC_InitStructure) == ERROR)
    {
//      printf("\n\r        /!\\***** RTC Prescaler Config failed ********/!\\ \n\r");
    }

    /* Configure the time register */
    RTC_TimeRegulate();
  }
  else
  {
    /* Check if the Power On Reset flag is set */
    if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)
    {
//     printf("\r\n Power On Reset occurred....\n\r");
    }
    /* Check if the Pin Reset flag is set */
    else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)
    {
//      printf("\r\n External Reset occurred....\n\r");
    }

//    printf("\n\r No need to configure RTC....\n\r");
   
    /* Enable the PWR clock */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

    /* Allow access to RTC */
    PWR_BackupAccessCmd(ENABLE);

#ifdef RTC_CLOCK_SOURCE_LSI
    /* Enable the LSI OSC */
    RCC_LSICmd(ENABLE);
#endif /* RTC_CLOCK_SOURCE_LSI */

    /* Wait for RTC APB registers synchronisation */
    RTC_WaitForSynchro();

    /* Clear the RTC Alarm Flag */
    RTC_ClearFlag(RTC_FLAG_ALRAF);

    /* Clear the EXTI Line 17 Pending bit (Connected internally to RTC Alarm) */
    EXTI_ClearITPendingBit(EXTI_Line17);

    /* Display the RTC Time and Alarm */
    RTC_TimeShow();
//    RTC_AlarmShow();
  }
}
/*****************************END OF FILE******************************/


RTC.zip

2.61 KB

使用特权

评论回复
13
清风致影| | 2015-1-13 11:56 | 只看该作者
Cheribat 发表于 2015-1-12 11:53
这是不现实的 我这边有几百块板子 而且现象并不是完全一样

我意思是说 rtc晶振不接电容没有不起振的情况
rtc本身是个计数器 精度不高

使用特权

评论回复
14
Cheribat|  楼主 | 2015-1-13 13:52 | 只看该作者
清风致影 发表于 2015-1-13 11:56
我意思是说 rtc晶振不接电容没有不起振的情况
rtc本身是个计数器 精度不高 ...

这边现在换的晶振都可以起振了 用示波器量频率也接近32768Hz 但时间不对 感觉配置哪个地方有问题

使用特权

评论回复
15
lanrq| | 2015-11-13 15:53 | 只看该作者
Cheribat 发表于 2015-1-13 13:52
这边现在换的晶振都可以起振了 用示波器量频率也接近32768Hz 但时间不对 感觉配置哪个地方有问题 ...

请问楼主,你是使用哪家晶振,参数是多少的,我使用的是6pF 负载电容的 32.768KHZ晶振,配10pF电容;3块板只有1块起振,问题很棘手。

使用特权

评论回复
16
Cheribat|  楼主 | 2015-11-18 09:52 | 只看该作者
lanrq 发表于 2015-11-13 15:53
请问楼主,你是使用哪家晶振,参数是多少的,我使用的是6pF 负载电容的 32.768KHZ晶振,配10pF电容;3块 ...

https://item.taobao.com/item.htm ... &_u=im4emniac4e

后来我也试了直插的晶振 大多是可以的 你可以试下把初始化部分代码顺序调整一下 把RTC的初始化放在最后

使用特权

评论回复
17
仙景| | 2015-11-18 18:47 | 只看该作者
楼主来这里发捞烧

使用特权

评论回复
18
yceast| | 2016-8-1 21:56 | 只看该作者
Cheribat 发表于 2015-1-13 13:52
这边现在换的晶振都可以起振了 用示波器量频率也接近32768Hz 但时间不对 感觉配置哪个地方有问题 ...

是不是选成LSI了?我就遇到过这种状况,程序运行时间非常快,后来才发现实际用的是LSI

使用特权

评论回复
19
myxiexing| | 2016-9-30 09:34 | 只看该作者
yceast 发表于 2016-8-1 21:56
是不是选成LSI了?我就遇到过这种状况,程序运行时间非常快,后来才发现实际用的是LSI ...

很有可能

使用特权

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

本版积分规则

个人签名:专业燃气泄漏、一氧化碳检测;厨房安全小助手 送礼当然送“安全”,您还在愁送朋友什么好吗?不妨进来看看吧! https://shop125092320.taobao.com/index.htm?spm

16

主题

489

帖子

2

粉丝