打印

STM32的RTC问题,望版主,广大网友解答,在线等。

[复制链接]
6238|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
芯行天下|  楼主 | 2009-1-17 09:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下是写的RTC部分程序,有点乱,但还能读懂。
问题1:
在进行RTC操作时,每次都要执行这个  RTC_WaitForLastTask()函数,在上电初始化时基本还行,但也会出现执行  RTC_WaitForLastTask();函数时不过的问题,就是RTOFF位一直为0,造成死循环。
问题2:假如上电初始化都正常通过了,在程序正常执行时进行校表,这时往RTC中写校表数据时还时还要执行  RTC_WaitForLastTask();函数,这时也会死循环,不是偶尔,而是每次都是死循环。

以上两点问题造成RTC部分工作一直耽误着,百思不得其解,望版主及广大网友帮忙解决一下。

#include "includes.h"

uint8 rtcdata[8];
const uint8 monthday[2][12] = {{31,28,31,30,31,30,31,31,30,31,30,31},    // 不润年
                               {31,29,31,30,31,30,31,31,30,31,30,31}};   // 润年


/*************************************************************************
** 备份时万年历数据函数
**
*****************************************************************************/
void bak_time(void)
{
  BKP_WriteBackupRegister(BKP_DR2, (yearhdata << 8) | yearldata); 
  BKP_WriteBackupRegister(BKP_DR3, (monthdata << 8) | daydata);
  BKP_WriteBackupRegister(BKP_DR4, (weekdata << 8) | hourdata);
  BKP_WriteBackupRegister(BKP_DR5, (mindata << 8) | secdata);
}

/*****************************************************************************
** 上电时从备份寄存器中取出万年历数据,并进行计算。
**
********************************************************************************/
void copy_time(void)
{
  uint16 temp;
  temp = BKP_ReadBackupRegister(BKP_DR2);
  yearhdata = 20;
  yearldata = temp & 0x00ff;                  // 年备份
  temp = BKP_ReadBackupRegister(BKP_DR3);
  monthdata = (temp & 0xff00) >>8;            // 月备份
  daydata = temp & 0x00ff;                    // 日备份
  temp = BKP_ReadBackupRegister(BKP_DR4); 
  weekdata = (temp & 0xff00) >> 8;            // 星期备份
  hourdata = temp & 0x00ff;                   // 时备份
  temp = BKP_ReadBackupRegister(BKP_DR5);
  mindata = (temp & 0xff00)>>8;                // 分备份
  secdata = temp & 0x00ff;                     // 秒备份
  get_rtc();
}

/***************************************************************************
** 天加1函数
**
****************************************************************************/
void dayadd(void)
{
  daydata ++;
  weekdata = (weekdata+1)%7;
  if (daydata >= monthday[(yearldata%4)==0 ? 1:0][monthdata-1])
  {
    daydata = 1;
    monthdata ++;
    if (monthdata >= 12)
    {
      yearldata ++;
      monthdata = 1;
    }
  }
  bak_time();
}

/***********************************************************************
** 时钟初始化函数,
**
*****************************************************************************/
void RTC_Init(void)
{
  if(BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)
  {
    RTC_Configuration();
    Time_Adjust(Time_Regulate());     
    BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
    bak_time();
  }
  else
    RTC_WaitForSynchro();
  copy_time();
}

/*******************************************************************************
* Function Name  : RTC_Configuration
* Description    : Configures the RTC.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RTC_Configuration(void)
{
  /* Enable PWR and BKP clocks */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
  
  /* Allow access to BKP Domain */
  PWR_BackupAccessCmd(ENABLE);

  /* Reset Backup Domain */
  BKP_DeInit();
  
  /* Enable LSE */
  RCC_LSEConfig(RCC_LSE_ON);
  /* Wait till LSE is ready */
  while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
  {
  }

  /* Select LSE as RTC Clock Source */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

  /* Enable RTC Clock */
  RCC_RTCCLKCmd(ENABLE);

  /* Wait for RTC registers synchronization */
  RTC_WaitForSynchro();

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
  
  /* Enable the RTC Second */
  //RTC_ITConfig(RTC_IT_SEC, ENABLE);

  /* Wait until last write operation on RTC registers has finished */
  //RTC_WaitForLastTask();
  
  /* Set RTC prescaler: set RTC period to 1sec */
  RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */
  
  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
}


/*******************************************************************************
* Function Name  : Time_Regulate
* Description    : Returns the time entered by user, using Hyperterminal.
* Input          : None
* Output         : None
* Return         : Current time RTC counter value
*******************************************************************************/
INT32U Time_Regulate(void)
{
  /* Return the value to store in RTC counter register */
//  yearhdata = 20;   //2009年1月1日星期4,0点0分0秒.
//  yearldata = 9;      
//  monthdata = 12;
//  daydata = 31;
//  weekdata = 4;
//  hourdata = 0;
//  mindata = 0;
//  secdata = 0;
  return((hourdata*3600 + mindata*60 + secdata));
}

/*******************************************************************************
* Function Name  : Time_Adjust
* Description    : Adjusts time.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void Time_Adjust(uint32 data)
{
  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
  /* Change the current time */
  RTC_SetCounter(data);
  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
}

/*******************************************************************
**  取得RTC的时间,并进行相关的计算.
**
**
**************************************************************************/
void get_rtc(void)
{
  uint8 temp;
  uint32 rtctemp;
  rtctemp = RTC_GetCounter();
  if (rtctemp > 86399)
  {
    //RTC_SetCounter(rtctemp%86400);
    Time_Adjust(rtctemp%86400);
    temp = rtctemp/86400;
    rtctemp %= 86400;
    while(temp > 0)
    {
      temp --;
      dayadd();  // 天数加1.
    }
  }    
  hourdata = rtctemp/3600;                /* Compute  hours */  
  mindata = (rtctemp % 3600)/60;          /* Compute minutes */  
  secdata = (rtctemp % 3600)% 60;         /* Compute seconds */  
}
沙发
香水城| | 2009-1-17 10:14 | 只看该作者

这个操作是等待上次的写结束,只需在操作RTC寄存器前使用

请看参考手册中的说明,再参考我的博客中例子:

使用特权

评论回复
板凳
芯行天下|  楼主 | 2009-1-17 11:08 | 只看该作者

谢谢版主,我试一下。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
李晓倩 + 1 www.jinjidejuren.tv/douluodalu/
地板
芯行天下|  楼主 | 2009-1-17 11:42 | 只看该作者

STM32的RTC问题,望版主解答,问题依旧

版主,这是我改过的程序,在一个小板上运行,运行
顺序为
1:上电初始化,执行RTC初始化,这时能够正确通过。
2:程序执行,4个LED灯依次点亮。
3:调用RTC子程序,取得RTC时间,然后再次写入,这时会执行RTC_WaitForLastTask();这一条语句,程序进入死循环。不知是什么原因。

我看了你的例子,和IAR中自带的例子一样,你那个程序只是在小板第一次上电,并且初始化RTC时才会执行写RTC操作,不知多次执行写RTC操作是否可行。而我写的程序也是第一次写没有问题,第二次及以后就不行了。望版主解释。
相关链接:https://bbs.21ic.com/upfiles/img/20091/200911711344240.rar

使用特权

评论回复
5
芯行天下|  楼主 | 2009-1-17 14:26 | 只看该作者

原因找到了

原因找到了,是因为在RTC初始化程序中假如没有初始化过RTC时,这时进行RTC初始化,能够正常操作,当第二次上电时,RTC已经初始化过,故跳过初始化部分,而忘记了再次打开PWR,BKP的时钟,所以造成每次都出错。

汗呀,这个问题让我找了两天!

使用特权

评论回复
6
computer00| | 2009-1-17 14:29 | 只看该作者

嘿嘿,恭喜恭喜~~~

使用特权

评论回复
7
芯行天下|  楼主 | 2009-1-17 15:09 | 只看该作者

一个新的芯片要想用好,真的不容易呀。

这是第一次用这个芯片来做产品,还真费了不少劲呀。
做ADC转换时,开始使用DMA进行数据传输,结果搞的一直下不进去程序,每次都要通过串口把程序擦掉再下载,网上查了一下,算是明白了,最后干脆不用DMA了,免得麻烦。这其中用了不少时间。
这次RTC又耗我N多时间呀。

看来还得继续历练才行呀。

使用特权

评论回复
8
xfcylyf| | 2011-8-23 13:40 | 只看该作者
写操作前运行RTC_Configuration(),可以解决写不进去的问题

使用特权

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

本版积分规则

87

主题

660

帖子

0

粉丝