STM32 RTC时钟设置

来源:互联网 发布:v盾网络验证破解 编辑:程序博客网 时间:2024/06/06 18:20

RTC移植时注意两点

(1)RTC需要中断函数。每秒中断一次,更新需要显示的标志。

(2)RTC运行中校正时间,更新RTC_CNTx时不能直接调用Time_Adjust()函数,需要开启PWR 和 BKP 时钟,且允许访问BKP域。

void RTC_SetCurrentTime(struct rtc_time *tm){/* Enable PWR and BKP clocks */RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);/* Allow access to BKP Domain */PWR_BackupAccessCmd(ENABLE);Time_Adjust(tm);RCC_ClearFlag();}

RTC的配置代码如下:

/**  ******************************************************************************  * 文件名程: bsp_rtc.c   * 作    者: 硬石嵌入式开发团队  * 版    本: V1.0  * 编写日期: 2015-10-04  * 功    能: 实时时钟底层驱动程序  ******************************************************************************  * 说明:  * 本例程配套硬石stm32开发板YS-F1Pro使用。  *   * 淘宝:  * 论坛:http://www.ing10bbs.com  * 版权归硬石嵌入式开发团队所有,请勿商用。  ******************************************************************************  *//* 包含头文件 ----------------------------------------------------------------*/#include "bsp/usart/bsp_usartx.h"#include  "bsp/rtc/bsp_rtc.h"/* 私有类型定义 --------------------------------------------------------------*//* 私有宏定义 ----------------------------------------------------------------*//* 私有变量 ------------------------------------------------------------------*//*星期,生肖用文字ASCII码*/uint8_t const *WEEK_STR[] = {"日", "一", "二", "三", "四", "五", "六"};uint8_t const *zodiac_sign[] = {"猪", "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗"};/* 扩展变量 ------------------------------------------------------------------*//* 私有函数原形 --------------------------------------------------------------*/void Time_Adjust(struct rtc_time *tm);static uint8_t USART_Scanf(uint32_t value);void Time_Regulate(struct rtc_time *tm);/* 函数体 --------------------------------------------------------------------*//**  * 函数功能: 配置RTC秒中断的主中断优先级为1,次优先级为0  * 输入参数: 无  * 返 回 值: 无  * 说    明:无  */static void RTC_NVIC_Config(void){NVIC_InitTypeDef NVIC_InitStructure;/* Enable the RTC Interrupt */NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);}/**  * 函数功能: 简单的延时函数  * 输入参数: time:延时时间  * 返 回 值: 无  * 说    明:无  */static void Delay(uint16_t time){  uint16_t i;  while(--time)  {    for(i=0;i<2000;i++);  }}/**  * 函数功能: 配置RTC  * 输入参数: 无  * 返 回 值: 1:RTC配置成功或运行正常,0:RTC无法正常使用  * 说    明:无  */static uint8_t RTC_Configuration(void){  uint32_t count=0;  /* 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){     Delay(100);     count++;     if(count>4000)return 0;  }/* Select LSE as RTC Clock Source */RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);/* Enable RTC Clock */RCC_RTCCLKCmd(ENABLE);/* Wait for RTC registers synchronization  * 因为RTC时钟是低速的,内环时钟是高速的,所以要同步 */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) = 1HZ *//* Wait until last write operation on RTC registers has finished */RTC_WaitForLastTask();    return 1;}void RTC_SetCurrentTime(struct rtc_time *tm){/* Enable PWR and BKP clocks */RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);/* Allow access to BKP Domain */PWR_BackupAccessCmd(ENABLE);Time_Adjust(tm);RCC_ClearFlag();}void RTC_SetAlarmTime(struct rtc_time *tm){Time_Regulate(tm);}/**  * 函数功能: 检查并配置RTC  * 输入参数: tm:用于读取RTC时间的结构体指针  * 返 回 值: 无  * 说    明:无  */uint8_t RTC_CheckAndConfig(struct rtc_time *tm){  /* 配置RTC秒中断的主中断优先级 */  RTC_NVIC_Config();    /*在启动时检查备份寄存器BKP_DR1,如果内容不是0xA5A5,  则需重新配置时间并询问用户调整时间*/if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5){printf("RTC not yet configured....\n");/* RTC Configuration */if(RTC_Configuration()!=1){      return 0;}printf("RTC configured....\n");/* Adjust time by users typed on the hyperterminal */Time_Adjust(tm);BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);}else{  /*启动无需设置新时钟*//*检查是否掉电重启*/if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET){    printf("Power On Reset occurred....\n");}/*检查是否Reset复位*/else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET){printf("External Reset occurred....\n");}printf("No need to configure RTC....\n");/*等待寄存器同步*/RTC_WaitForSynchro();/*允许RTC秒中断*/RTC_ITConfig(RTC_IT_SEC, ENABLE);/*等待上次RTC寄存器写操作完成*/RTC_WaitForLastTask();}   /*定义了时钟输出宏,则配置校正时钟输出到PC13*/#ifdef RTCClockOutput_Enable  /* Enable PWR and BKP clocks */  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);  /* Allow access to BKP Domain */  PWR_BackupAccessCmd(ENABLE);  /* Disable the Tamper Pin */  BKP_TamperPinCmd(DISABLE); /* To output RTCCLK/64 on Tamper pin, the tamper                                 functionality must be disabled */  /* Enable RTC Clock Output on Tamper Pin */  BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);#endif  /* Clear reset flags */  RCC_ClearFlag();    return 1;}/**  * 函数功能: 时间调节实现  * 输入参数: tm:用于读取RTC时间的结构体指针  * 返 回 值: 无  * 说    明:无  *//**  *  static  * 函数功能: 时间调整,保存在RTC时钟结构体  * 输入参数: tm:用于读取RTC时间的结构体指针  * 返 回 值: 无  * 说    明:无  */ void Time_Regulate(struct rtc_time *tm){#if 0  tm->tm_year = 2015;  tm->tm_mon  =   10;  tm->tm_mday =    4;  tm->tm_hour =   10;   tm->tm_min  =   15;   tm->tm_sec  =   46;#else  u32 Tmp_YY = 0xFF, Tmp_MM = 0xFF, Tmp_DD = 0xFF, Tmp_HH = 0xFF, Tmp_MI = 0xFF, Tmp_SS = 0xFF;  printf("=========================Time Settings==================\n");  printf("请输入年份(Please Set Years):  20\n");  while (Tmp_YY == 0xFF)  {    Tmp_YY = USART_Scanf(99);  }  printf("年份被设置为:  20%0.2d\n", Tmp_YY);  tm->tm_year = Tmp_YY+2000;  Tmp_MM = 0xFF;  printf("请输入月份(Please Set Months):  \n");  while (Tmp_MM == 0xFF)  {    Tmp_MM = USART_Scanf(12);  }  printf("月份被设置为:  %d\n", Tmp_MM);  tm->tm_mon= Tmp_MM;  Tmp_DD = 0xFF;  printf("请输入日期(Please Set Dates):  \n");  while (Tmp_DD == 0xFF)  {    Tmp_DD = USART_Scanf(31);  }  printf("日期被设置为:  %d\n", Tmp_DD);  tm->tm_mday= Tmp_DD;  Tmp_HH  = 0xFF;  printf("请输入时钟(Please Set Hours):  \n");  while (Tmp_HH == 0xFF)  {    Tmp_HH = USART_Scanf(23);  }  printf("时钟被设置为:  %d\n", Tmp_HH );  tm->tm_hour= Tmp_HH;      Tmp_MI = 0xFF;  printf("请输入分钟(Please Set Minutes):  \n");  while (Tmp_MI == 0xFF)  {    Tmp_MI = USART_Scanf(59);  }  printf("分钟被设置为:  %d\n", Tmp_MI);  tm->tm_min= Tmp_MI;  Tmp_SS = 0xFF;  printf("请输入秒钟(Please Set Seconds):  \n");  while (Tmp_SS == 0xFF)  {    Tmp_SS = USART_Scanf(59);  }  printf("秒钟被设置为:  %d\n", Tmp_SS);  tm->tm_sec= Tmp_SS;  #endif}void Time_Adjust(struct rtc_time *tm){  /* Wait until last write operation on RTC registers has finished */  RTC_WaitForLastTask();  /* Get time entred by the user on the hyperterminal */  Time_Regulate(tm);    /* Get wday */  GregorianDay(tm);  /* 修改当前RTC计数寄存器内容 */  RTC_SetCounter(mktimev(tm));  /* Wait until last write operation on RTC registers has finished */  RTC_WaitForLastTask();}/*** 函数功能: 从串口调试助手获取数字值(把ASCII码转换为数字)* 输入参数: value 用户在超级终端中输入的数值* 返 回 值: 输入字符的ASCII码对应的数值* 说    明:本函数专用于RTC获取时间,若进行其它输入应用,要修改一下*/static 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("Please enter valid number between 0 and 9 -->:  \n");index--;  }}/* 计算输入字符的ASCII码转换为数字*/index = (tmp[1] - 0x30) + ((tmp[0] - 0x30) * 10);/* Checks */if (index > value){printf("Please enter valid number between 0 and %d\n", value);return 0xFF;}return index;}/**  * 函数功能: 显示当前时间值  * 输入参数: TimeVar RTC计数值,单位为 s,tm:用于读取RTC时间的结构体指针  * 返 回 值: 无  * 说    明:无  */void Time_Display(uint32_t TimeVar,struct rtc_time *tm){   static uint8_t FirstDisplay = 1;   uint32_t BJ_TimeVar;   uint8_t str[15]; // 字符串暂存     /*  把标准时间转换为北京时间*/   BJ_TimeVar =TimeVar + 8*60*60;   to_tm(BJ_TimeVar, tm);/*把定时器的值转换为北京时间*/  if((!tm->tm_hour && !tm->tm_min && !tm->tm_sec)  || (FirstDisplay))  {          GetChinaCalendar((u16)tm->tm_year, (u8)tm->tm_mon, (u8)tm->tm_mday, str);      printf("今天新历:%0.2d%0.2d,%0.2d,%0.2d\n", str[0], str[1], str[2],  str[3]);    GetChinaCalendarStr((u16)tm->tm_year,(u8)tm->tm_mon,(u8)tm->tm_mday,str);      printf("今天农历:%s\n", str);   if(GetJieQiStr((u16)tm->tm_year, (u8)tm->tm_mon, (u8)tm->tm_mday, str))      printf("今天农历:%s\n", str);    FirstDisplay = 0;  }     /* 输出时间戳,公历时间 */  printf(" UNIX时间戳 = %d 当前时间为: %d年(%s年) %d月 %d日 (星期%s)  %0.2d:%0.2d:%0.2d\n",TimeVar,                    tm->tm_year, zodiac_sign[(tm->tm_year-3)%12], tm->tm_mon, tm->tm_mday,                     WEEK_STR[tm->tm_wday], tm->tm_hour,                     tm->tm_min, tm->tm_sec);}/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/


RTC程序文件:http://pan.baidu.com/s/1jIzfaxo