OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6590|回复: 6

STM32F0 RTC写实时时钟年份总是出现不规则的错误

[复制链接]

2

主题

5

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2017-9-20
在线时间
4 小时
发表于 2017-10-24 09:11:34 | 显示全部楼层 |阅读模式
1金钱
下面是用STM32F0写的一个 RTC写实时时钟程序,问题是年份总是出现不规则的错误,比如我设置成2012年,总是出现2017,2016这样的,日期,时间,闹钟都不会有问题,就是年份一直有问题。下面是具体函数,大家帮忙看看
/**
  ******************************************************************************
  * @file    RTC_Time.c
  * @Author  MCD Application Team
  * @version V1.0.1
  * @date    13-April-2012
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2012 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */
#include "stm32f0xx.h"
#include <stdio.h>
#include "RTC_Time.h"
#include "led.h"


/** @addtogroup RTC_TimeStamp
  * @{
  */

#define RTC_CLOCK_SOURCE_LSE   /* LSE used as RTC source clock */

__IO uint32_t TimeDisplay = 0;
__IO uint32_t AsynchPrediv = 0, SynchPrediv = 0;

/**
  * @brief  配置RTC秒中断的主中断优先级为1,次优先级为0
  * @param  None
  * @retval None
  */
void RTC_NVIC_Config(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;
        /* Enable the USART1 Interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;         
        NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
}

/**
  * @brief  检查并配置RTC
  * @param  None
  * @retval None
  */
void RTC_CheckAndConfig(void)
{
        RTC_InitTypeDef RTC_InitStructure;
        EXTI_InitTypeDef  EXTI_InitStructure;
  /*在启动时检查备份寄存器RTC_BKP_DR0,如果内容不是0x32F0,则需重新配置时间并询问用户调整时间*/
        if (RTC_ReadBackupRegister(RTC_BKP_DR0) != BKP_VALUE)
        {
                /* RTC configuration  */
    RTC_Configuration();
               
                /* Configure the time register */
    RTC_TimeRegulate();
    /* Configure the RTC data register and RTC prescaler */
    RTC_InitStructure.RTC_AsynchPrediv = AsynchPrediv;//RTC异步分频系数
    RTC_InitStructure.RTC_SynchPrediv = SynchPrediv;//RTC同步分频系数
    RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;//24小时格式

    /* Check on RTC init */
    if (RTC_Init(&RTC_InitStructure) == ERROR)//判断RTC初始化是否成功
    {
      printf("\n\r   /!\\***** RTC Prescaler Config failed ********/!\\ \n\r");
    }

        }
        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();

        }
                  /* RTC Alarm A Interrupt Configuration */
  /* EXTI configuration *********************************************************/
  EXTI_ClearITPendingBit(EXTI_Line17);
  EXTI_InitStructure.EXTI_Line = EXTI_Line17;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
       
        RTC_NVIC_Config();
}


/**
  * @brief  Configure the RTC peripheral by selecting the clock source.
  * @param  None
  * @retval None
  */
void RTC_Configuration(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();
       

}

/**
  * @brief  从微机超级终端获取数字值(把ASCII码转换为数字),本函数专用于RTC获取时间,
  * @param   - value 用户在超级终端中输入的数值
  * @retval 输入字符的ASCII码对应的数值
  */
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))   /*数字0到9的ASCII码为0x30至0x39*/
            {                   
                      printf("\n\rPlease enter valid number between 0 and 9 -->:  ");
              index--;                  
            }
          }
          
          /* 计算输入字符的ASCII码转换为数字*/
          index = (tmp[1] - 0x30) + ((tmp[0] - 0x30) * 10);
               
          /* Checks */
          if (index > value)
          {
            printf("\n\rPlease enter valid number between 0 and %d", value);
            return 0xFF;
          }
          return index;
}

/**
  * @brief  Returns the time entered by user, using Hyperterminal.
  * @param  None
  * @retval None
  */
void RTC_TimeRegulate(void)
{

        RTC_TimeTypeDef RTC_TimeStructure;
        RTC_DateTypeDef RTC_DateStructure;
  RTC_AlarmTypeDef  RTC_AlarmStructure;
  uint32_t tmp_yy = 0xFF,tmp_mo = 0xFF,tmp_dd = 0xFF,tmp_hh = 0xFF, tmp_mm = 0xFF, tmp_ss = 0xFF;

  printf("\n\r==============Time Settings=====================================\n\r");
  RTC_TimeStructure.RTC_H12     = RTC_H12_AM;
       
        printf("  Please Set Year:  20__\n\r");


  while (tmp_yy == 0xFF)
  {
    tmp_yy = USART_Scanf(99);
    RTC_DateStructure.RTC_Year = tmp_yy;
  }
  printf("  20%0.2d\n\r", tmp_yy);
       
        printf("  Please Set Months: \n\r");

  while (tmp_mo == 0xFF)
  {
    tmp_mo = USART_Scanf(12);
    RTC_DateStructure.RTC_Month = tmp_mo;
  }
  printf("  %0.2d\n\r", tmp_mo);
       
        printf("  Please Set Dates: \n\r");

  while (tmp_dd == 0xFF)
  {
    tmp_dd = USART_Scanf(31);
    RTC_DateStructure.RTC_Date = tmp_dd;
  }
  printf("  %0.2d\n\r", tmp_dd);
       
  printf("  Please Set Hours:\n\r");

  while (tmp_hh == 0xFF)
  {
    tmp_hh = USART_Scanf(23);
    RTC_TimeStructure.RTC_Hours = tmp_hh;
  }
  printf("  %0.2d\n\r", tmp_hh);

  printf("  Please Set Minutes:\n\r");
  while (tmp_mm == 0xFF)
  {
    tmp_mm = USART_Scanf(59);
    RTC_TimeStructure.RTC_Minutes = tmp_mm;
  }
  printf("  %0.2d\n\r", tmp_mm);

  printf("  Please Set Seconds:\n\r");
  while (tmp_ss == 0xFF)
  {
    tmp_ss = USART_Scanf(59);
    RTC_TimeStructure.RTC_Seconds = tmp_ss;
  }
  printf("  %0.2d\n\r", tmp_ss);

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

        tmp_yy = 0xFF;
        tmp_mo = 0xFF;
        tmp_dd = 0xFF;
  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);

  RTC_ITConfig(RTC_IT_WUT,ENABLE);//开启WAKE UP 定时器中断
        RTC_WakeUpCmd( ENABLE);//开启WAKE UP 定时器 
}

/**
  * @brief  Display the current time on the Hyperterminal.
  * @param  None
  * @retval None
  */
void RTC_TimeShow(void)
{
        uint8_t str[15]; // 字符串暂存
  RTC_TimeTypeDef RTC_TimeStructure;
        RTC_DateTypeDef RTC_DateStructure;

  /* Get the current Time */
  RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);
        RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure);
  printf("\n\r  The current time is : %0.2d-%0.2d-%0.2d  %0.2d:%0.2d:%0.2d \n\r", RTC_DateStructure.RTC_Year,RTC_DateStructure.RTC_Month,RTC_DateStructure.RTC_Date,RTC_TimeStructure.RTC_Hours, RTC_TimeStructure.RTC_Minutes, RTC_TimeStructure.RTC_Seconds);
        GetChinaCalendar((uint16_t)(RTC_DateStructure.RTC_Year+2000), RTC_DateStructure.RTC_Month, (uint8_t)RTC_DateStructure.RTC_Date,str);       
        printf("\r\n 今天新历:%0.2d%0.2d,%0.2d,%0.2d", str[0], str[1], str[2],  str[3]);
       
        GetChinaCalendarStr((uint16_t)(RTC_DateStructure.RTC_Year+2000), RTC_DateStructure.RTC_Month, (uint8_t)RTC_DateStructure.RTC_Date,str);
  printf("\r\n 今天农历:%s\r\n", str);
       
        if(GetJieQiStr((uint16_t)(RTC_DateStructure.RTC_Year+2000), RTC_DateStructure.RTC_Month, (uint8_t)RTC_DateStructure.RTC_Date,str))
        printf("\r\n 今天农历:%s\r\n", str);
}

/**
  * @brief  Display the current time on the Hyperterminal.
  * @param  None
  * @retval None
  */
void RTC_AlarmShow(void)
{
  RTC_AlarmTypeDef  RTC_AlarmStructure;
  /* Get the current Alarm */
  RTC_GetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStructure);
  printf("\n\r  The current alarm is :  %0.2d:%0.2d:%0.2d \n\r", RTC_AlarmStructure.RTC_AlarmTime.RTC_Hours, RTC_AlarmStructure.RTC_AlarmTime.RTC_Minutes, RTC_AlarmStructure.RTC_AlarmTime.RTC_Seconds);
}


/**************11****************************************************************/
/*                 STM32F0xx Peripherals Interrupt Handlers                   */
/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
/*  available peripheral interrupt handler's name please refer to the startup */
/*  file (startup_stm32f0xx.s).                                            */
/******************************************************************************/
void RTC_IRQHandler(void)
{
       
  if( (RTC_IT_ALRA) != RESET)
  {
                RTC_AlarmShow();
    RTC_ClearITPendingBit(RTC_IT_ALRA);
    EXTI_ClearITPendingBit(EXTI_Line17);
        }
       
}





/*******************************END OF FILE***************************************/





RTC Demo.rar

3.57 MB, 下载次数: 214

最佳答案

查看完整内容[请看2#楼]

我最近也有这个问题,不过是F0的,我的解决办法是在设置的时候把星期也填上,用不到星期的话就填0,这样可以避免读写年的时候出现错误
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

2

帖子

0

精华

初级会员

Rank: 2

积分
113
金钱
113
注册时间
2016-3-1
在线时间
34 小时
发表于 2017-10-24 09:11:35 | 显示全部楼层
我最近也有这个问题,不过是F0的,我的解决办法是在设置的时候把星期也填上,用不到星期的话就填0,这样可以避免读写年的时候出现错误
回复

使用道具 举报

2

主题

5

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2017-9-20
在线时间
4 小时
 楼主| 发表于 2017-10-24 09:38:04 | 显示全部楼层
有的时候会是正确的,有的时候会错,重新烧程序就会有不同结果
回复

使用道具 举报

2

主题

5

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2017-9-20
在线时间
4 小时
 楼主| 发表于 2017-10-24 10:24:22 | 显示全部楼层
问题真奇葩,快吐血了
回复

使用道具 举报

2

主题

65

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2106
金钱
2106
注册时间
2016-5-21
在线时间
238 小时
发表于 2017-10-24 23:22:40 | 显示全部楼层
为啥不用原子哥的程序哪
回复

使用道具 举报

160

主题

967

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2097
金钱
2097
注册时间
2014-3-7
在线时间
491 小时
发表于 2018-7-25 14:07:26 | 显示全部楼层
解决了吗
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手上路

积分
39
金钱
39
注册时间
2019-9-9
在线时间
12 小时
发表于 2020-3-31 13:25:32 | 显示全部楼层
按照5楼的方法确实解决了这个问题,设置星期后,读取年份就正确了,但是不知道原理!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-24 06:28

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表