| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557 |
- /*--------------------------------------------------------------------------------------
- * @file RTCSetup.c
- * @author ZhangJing
- * @version base on stm32f0x
- * @date 2015.09.11
- * @brief RTC驱动
- ---------------------------------------------------------------------------------------*/
- #include "stm32f10x_gpio.h"
- #include "stm32f10x_rtc.h"
- #include "stm32f10x_pwr.h"
- #include "stm32f10x_bkp.h"
- #include "stm32f10x_exti.h"
- #include "TypeDefine.h"
- #include "DrawLCDGUI.h"
- #include "RTCSetup.h"
- #include "FM31256.h"
- //extern SpeakerWorkType speakerWorkStep;//蜂鸣器工作步骤
- const uint8_t table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表
- const uint8_t mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};//平年月份日期表
- static ErrorStatus HSEStartUpStatus;//HSE时钟启动状态
- /*********************************************************************************
- * Function: Is_Leap_Year
- * Object: 判断是否是闰年
- * 输入: 年份
- * 输出: 该年是不是闰年。1是 0不是
- * 备注: //月份 1 2 3 4 5 6 7 8 9 10 11 12
- //闰年 31 29 31 30 31 30 31 31 30 31 30 31
- //非闰年 31 28 31 30 31 30 31 31 30 31 30 31
- **********************************************************************************/
- uint8_t Is_Leap_Year(uint16_t year)
- {
- if( year % 4 == 0 ) //必须能被4整除
- {
- if( year % 100 == 0 )
- {
- if( year % 400 == 0 )
- {
- return 1;//如果以00结尾,还能被400整除
- }
- else
- {
- return 0;
- }
- }
- else
- {
- return 1;
- }
- }
- else
- {
- return 0;
- }
- }
- /*********************************************************************************
- * Function: RTC_Get_Week
- * Object: 获得现在是星期几
- * 输入: 公历年月日
- * 输出: 星期号
- * 备注: 1、uint8_t yearH,yearL;年的高低字节计算
- * 2、uint16_t temp2;作为计算的临时变量
- **********************************************************************************/
- uint8_t RTC_Get_Week(uint16_t year,uint8_t month,uint8_t day)
- {
- uint16_t temp2;
- uint8_t yearH,yearL;
-
- yearH = year / 100;
- yearL = year % 100;
- // 如果为21世纪,年份数加100
- if( yearH > 19 )
- {
- yearL += 100;
- }
- //所过闰年数只算1900年之后的
- temp2 = yearL + yearL / 4;
- temp2 = temp2 % 7;
- temp2 = temp2 + day + table_week[month - 1];
- if( yearL % 4 == 0 && month < 3 )
- {
- temp2--;
- }
- return( temp2 % 7 );
- }
- /*********************************************************************************
- * Function: RTC_Set
- * Object: 设置时钟
- * 输入: 月份数据表
- * 输出: 0:成功 其它:错误代码
- * 备注: 把输入的时钟转换为秒钟
- * 以1970年1月1日为基准
- * 1970~2099年为合法年份
- **********************************************************************************/
- uint8_t RTC_Set(uint16_t syear,uint8_t smon,uint8_t sday,uint8_t hour,uint8_t min,uint8_t sec)
- {
- uint16_t t;
- uint32_t seccount=0;
-
- // RTC_ITConfig(RTC_IT_SEC, DISABLE); //关闭秒中断
- // RTC_WaitForLastTask();
- if( syear < 2015 || syear > 2099 )
- {
- return 1;//syear范围1970-2099,此处范围设置为2015-2099
- }
- for( t = 1970;t < syear;t++) //把所有年份的秒钟相加
- {
- if( Is_Leap_Year( t ) )
- {
- seccount += 31622400;//闰年的秒钟数
- }
- else
- {
- seccount += 31536000;//平年的秒钟数
- }
- }
- smon -= 1;
- for( t = 0;t < smon;t++ ) //把前面月份的秒钟数相加
- {
- seccount += (uint32_t)mon_table[t] * 86400;//月份秒钟数相加
- if( Is_Leap_Year( syear ) && ( t == 1 ) )
- {
- seccount += 86400;//闰年2月份增加一天的秒钟数
- }
- }
- seccount += (uint32_t)( sday - 1 ) * 86400;//把前面日期的秒钟数相加
- seccount += (uint32_t)hour * 3600;//小时秒钟数
- seccount += (uint32_t)min * 60;//分钟秒钟数
- seccount += sec;//最后的秒钟数加上去
-
- //设置时钟
- // RCC->APB1ENR|=1<<28;//使能电源时钟
- // RCC->APB1ENR|=1<<27;//使能备份时钟
- // PWR->CR|=1<<8; //取消备份区写保护
- // //以上三步是必须的!
-
- RTC_WaitForLastTask();
- RTC_SetCounter(seccount);
-
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
- PWR_BackupAccessCmd(ENABLE);
- RTC_WaitForLastTask();
- RTC_ITConfig(RTC_IT_SEC, ENABLE); //打开秒中断
- return 0;
- }
- /*********************************************************************************
- * Function: RTC_Get
- * Object: 得到当前时间
- * 输入: 无
- * 输出: 0:成功 其它:错误代码
- * 备注: 1、static uint16_t daycnt=0;天数计算
- * 2、uint32_t timecount=0;时间计算
- * 3、uint32_t temp=0;临时变量
- * 4、uint16_t temp1=0;临时变量
- **********************************************************************************/
- uint8_t RTC_Get(void)
- {
- static uint16_t daycnt=0;
- uint32_t timecount=0;
- uint32_t temp=0;
- uint16_t temp1=0;
-
- timecount = RTC_GetCounter();
-
- // timecount=RTC->CNTH;//得到计数器中的值(秒钟数)
- // timecount<<=16;
- // timecount+=RTC->CNTL;
-
- temp = timecount / 86400; //得到天数(秒钟数对应的)
- if( daycnt != temp )//超过一天了
- {
- daycnt = temp;
- temp1 = 1970; //从1970开始
-
- while( temp >= 365 )
- {
- if( Is_Leap_Year( temp1 ) )//是闰年
- {
- // if( temp >= 366 )
- // {
- // temp -= 366;//闰年的秒钟数
- // }
- // else
- // {
- // temp1++;
- // break;
- // }
- temp -= 366;//闰年的秒钟数
- }
- else
- {
- temp -= 365; //平年
- // temp1++;
- }
- temp1++;
- }
- displayTimeBuf.year = temp1;//得到年份
- temp1 = 0;
- while( temp >= 28 )//超过了一个月
- {
- if( Is_Leap_Year( displayTimeBuf.year ) && ( temp1 == 1 ) )//当年是不是闰年/2月份
- {
- if( temp >= 29 )
- {
- temp -= 29;//闰年的秒钟数
- }
- else
- {
- break;
- }
- }
- else
- {
- if( temp >= mon_table[temp1] )
- {
- temp -= mon_table[temp1];//平年
- }
- else
- {
- break;
- }
- }
- temp1++;
- }
- displayTimeBuf.month = temp1 + 1;//得到月份
- displayTimeBuf.date = temp + 1; //得到日期
- }
-
- temp = timecount % 86400; //得到秒钟数
- displayTimeBuf.hour = temp / 3600; //小时
- displayTimeBuf.minute = ( temp % 3600 ) / 60; //分钟
- displayTimeBuf.seconds = ( temp % 3600 ) %60; //秒钟
- //displayTimeBuf.week = RTC_Get_Week( displayTimeBuf.year,displayTimeBuf.month,displayTimeBuf.date );//获取星期
-
- return 0;
- }
- /*********************************************************************************
- * Function: RTCInit
- * Object: RTC计时功能初始化
- * 输入: 无
- * 输出: 无
- * 备注: uint16_t waitForOscSource;临时计算变量
- **********************************************************************************/
- void RTCInit(void)
- {
- uint16_t waitForOscSource;
- //在BKP后备寄存器1中,存储了一个特殊字符0xA5A5
- //第一次上电或后备电源掉电后,该寄存器数据丢失
- //表明RTC数据丢失,需重新配置
- if( BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5 )
- {
- //重新配置RTC
- /* 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);
- for( waitForOscSource = 0;waitForOscSource < 5000;waitForOscSource++ )
- {
- }
- // /* 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();
- //配置完成后,向后备电源写特殊字符0xA5A5
- BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
- RTC_Set(2015,01,01,0,0,0);//默认时间
- }
- else
- {
- //若后备电源没有掉电,则无需重新配置RTC
- //这里我们可以利用RCC_GetFlagStatus()函数查看本次复位类型
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
- for( waitForOscSource = 0;waitForOscSource < 5000;waitForOscSource++ );
-
- if(RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)
- {
- //这是上电复位
- }
- else if(RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)
- {
- //这是外部RESET管脚复位
- }
-
- //清除RCC中复位标志
- RCC_ClearFlag();
-
- //虽然RTC模块不需要配置,且掉电后依靠后备电源依然运行
- //但是每次上电后,还是要使能RTCCLK???????
- //RCC_RTCCLKCmd(ENABLE);
-
- //等待RTC时钟与APB1时钟同步
- //RTC_WaitForSynchro();
-
- //使能秒中断
- RTC_ITConfig(RTC_IT_SEC, ENABLE);
- //等待操作完成
- RTC_WaitForLastTask();
- }
- return;
- }
- /*********************************************************************************
- * Function: SystemTimeUpdate
- * Object: 系统时间更新
- * 输入: 无
- * 输出: 无
- * 备注: 1、通过 TaskSchedulerFlag.timeReadFlag标志位来判断是否更新时间
- * 2、每读取一次时间进行一次时间显示界面的刷新
- **********************************************************************************/
- void SystemTimeUpdate( void )
- {
- if( TaskSchedulerFlag.timeReadFlag == TASK_FLAG_SET )//时间读取
- {
- if( realTimeData.stateRun != Poweroff )
- {
- //获取当前时间
- if( speakerWorkStep != emSpeakerNoneWork)
- return;
- GetCurDateTimeFromRTC();
-
- if( emCurrentPicture == TimeDisp )//更新显示时间页面
- {
- emDisplayPicture = TimeDisp;
- }
-
- TaskSchedulerFlag.timeReadFlag = TASK_FLAG_CLEAR;
- }
- }
- }
- /*********************************************************************************
- * Function: RTC_NVIC_Config
- * Object: RTC中断配置
- * 输入: 无
- * 输出: 无
- * 备注: NVIC_InitTypeDef NVIC_InitStructure; 中断配置结构体
- **********************************************************************************/
- void RTC_NVIC_Config(void)
- {
- NVIC_InitTypeDef NVIC_InitStructure;
- NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; //RTC全局中断
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级1位,从优先级3位
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能该通道中断
- NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定参数初始化外设NVIC寄存器
- }
- /*********************************************************************************
- * Function: RTC_Alarm_Configuration
- * Object: RTC闹钟初始化
- * 输入: 无
- * 输出: 无
- * 备注: 启动时钟、配置LSI做RTC时钟、设置预分频40000得到1Hz
- * 设置运行时间WORK_TIMES
- **********************************************************************************/
- void RTC_Alarm_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();
- /* RTC clock source configuration ----------------------------------------*/
- /* 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);
-
- /* Enable the RTC Clock */
- RCC_RTCCLKCmd(ENABLE);
- /* Wait for RTC registers synchronization */
- RTC_WaitForSynchro();
- /* Wait until last write operation on RTC registers has finished */
- RTC_WaitForLastTask();
- /* 使能RTC闹钟中断*/
- RTC_ITConfig(RTC_IT_ALR, ENABLE);
- /* Wait until last write operation on RTC registers has finished */
- RTC_WaitForLastTask();
- /* Set RTC prescaler: set RTC period to 1sec */
- RTC_SetPrescaler(40000);
- /* Wait until last write operation on RTC registers has finished */
- RTC_WaitForLastTask();
- //中断配置
- RTC_NVIC_Config();
- //设置运行WORK_TIMES
- RTC_SetAlarm(RTC_GetCounter() + WORK_TIMES);
- RTC_WaitForLastTask();
- }
- /*********************************************************************************
- * Function: StopMode_Configuration
- * Object: 停止模式RTC闹钟初始化
- * 输入: 无
- * 输出: 无
- * 备注: 启动时钟、配置LSI做RTC时钟、设置预分频40000得到1Hz
- **********************************************************************************/
- void StopMode_Configuration(void)
- {
- EXTI_InitTypeDef EXTI_InitStructure;
- /* 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();
- /* RTC clock source configuration ----------------------------------------*/
- /* 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);
- /* Enable the RTC Clock */
- RCC_RTCCLKCmd(ENABLE);
- /* Wait for RTC registers synchronization */
- RTC_WaitForSynchro();
- /* Wait until last write operation on RTC registers has finished */
- RTC_WaitForLastTask();
- /* Set RTC prescaler: set RTC period to 1sec */
- RTC_SetPrescaler(40000);
- /* Wait until last write operation on RTC registers has finished */
- RTC_WaitForLastTask();
- /* Configure EXTI Line17(RTC Alarm) to generate an interrupt on rising edge */
- EXTI_ClearITPendingBit(EXTI_Line17);
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
- EXTI_InitStructure.EXTI_Line = EXTI_Line17;
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;
- EXTI_Init(&EXTI_InitStructure);
- }
- /*******************************************************************************
- * Function Name : SYSCLKConfig_STOP
- * Description : Configures system clock after wake-up from STOP: enable HSE, PLL
- * and select PLL as system clock source.
- * Input : None
- * Output : None
- * Return : None
- *******************************************************************************/
- void StopMode_SYSCLKConfig_STOP(void)
- {
- /* Enable HSE */
- RCC_HSEConfig(RCC_HSE_ON);
- /* Wait till HSE is ready */
- HSEStartUpStatus = RCC_WaitForHSEStartUp();
- if(HSEStartUpStatus == SUCCESS)
- {
- /* Enable PLL */
- RCC_PLLCmd(ENABLE);
- /* Wait till PLL is ready */
- while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
- {
- }
- /* Select PLL as system clock source */
- RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
- /* Wait till PLL is used as system clock source */
- while(RCC_GetSYSCLKSource() != 0x08)
- {
- }
- }
- }
- /*********************************************************************************
- * Function: StopMode_EnterStopMode
- * Object: 进入停止模式
- * 输入: uint32_t s,闹钟触发时间
- * 输出: 无
- * 备注: 设置待机时间并进入停止,闹钟事件发生自动退出stop模式
- * 进入stop模式,闹钟唤醒后跳出函数运行
- * RAM/GPIO状态保持
- * s为单位秒
- **********************************************************************************/
- void StopMode_EnterStopMode(uint32_t s)
- {
- //设置待机时间
- RTC_SetAlarm(RTC_GetCounter() + s);
- RTC_WaitForLastTask();
- /* LDO不关掉,闹钟事件唤醒*/
- PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFE);
- //唤醒后重新配置系统时钟
- StopMode_SYSCLKConfig_STOP();
- }
|