5560|4

132

帖子

0

TA的资源

一粒金砂(高级)

楼主
 

STM32的RTC问题 难搞啊 [复制链接]

被STM32的RTC搞晕的过来看看本来打算放弃内置的RTC而采用DS1302了,无奈1302的通信太慢,屡次不成功,就把扔在一边的老板子拿来又试了试,这次没用自己原来的程序,在网上又新找了一个,结果程序都不用动的居然就行了···

芯片是VCT6,晶振是那种4脚封装的,电容是30p的···本来以为是硬件的问题,唉··

现在把程序贴出来,给刚刚接触RTC的做个参考,亲测可用···


//时间结构体

typedef struct

{

       u8 hour;

       u8 min;

       u8 sec;                

       //公历日月年周

       u16 w_year;

       u8  w_month;

       u8  w_date;

       u8  week;           

}tm;

tm timer;

 

void RTC_Config(void)

{

     u16 u16_WaitForOscSource;

     //我们在BKP的后备寄存器1中,存了一个特殊字符0xA5A5

    //第一次上电或后备电源掉电后,该寄存器数据丢失,

    //表明RTC数据丢失,需要重新配置

    if (BKP_ReadBackupRegister(BKP_DR1) != 0x5A5A)

    {

        //重新配置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(u16_WaitForOscSource=0;u16_WaitForOscSource<5000;u16_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, 0x5A5A);

        RTC_Set(2011,01,01,0,0,0);//默认时间

    }

    else

    {

        //若后备寄存器没有掉电,则无需重新配置RTC

        //这里我们可以利用RCC_GetFlagStatus()函数查看本次复位类型

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

            for(u16_WaitForOscSource=0;u16_WaitForOscSource<5000;u16_WaitForOscSource++);

        if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)

        {

            //这是上电复位

        }

        else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)

        {

            //这是外部RST管脚复位

        }

        //清除RCC中复位标志

        RCC_ClearFlag();

 

        //虽然RTC模块不需要重新配置,且掉电后依靠后备电池依然运行

        //但是每次上电后,还是要使能RTCCLK???????

        //RCC_RTCCLKCmd(ENABLE);

        //等待RTC时钟与APB1时钟同步

        //RTC_WaitForSynchro();

 

        //使能秒中断

        RTC_ITConfig(RTC_IT_SEC, ENABLE);

        //等待操作完成

        RTC_WaitForLastTask();

    }

 

 

 

    return;

}

//判断是否是闰年函数

//月份   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

//输入:年份

//输出:该年份是不是闰年.1,是.0,不是

u8 Is_Leap_Year(u16 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;

}                         

//设置时钟

//把输入的时钟转换为秒钟

//以1970年1月1日为基准

//1970~2099年为合法年份

//返回值:0,成功;其他:错误代码.

//月份数据表                                                                      

u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表 

//平年的月份日期表

const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};

u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)

{

       u16 t;

       u32 seccount=0;

       if(syear<2000||syear>2099)return 1;//syear范围1970-2099,此处设置范围为2000-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+=(u32)mon_table[t]*86400;//月份秒钟数相加

              if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数       

       }

       seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加

       seccount+=(u32)hour*3600;//小时秒钟数

    seccount+=(u32)min*60;      //分钟秒钟数

       seccount+=sec;//最后的秒钟加上去

                                                                                             

       //设置时钟

  /*  RCC->APB1ENR|=1<<28;//使能电源时钟

    RCC->APB1ENR|=1<<27;//使能备份时钟

       PWR->CR|=1<<8;    //取消备份区写保护

       //上面三步是必须的!*/

       PWR_BackupAccessCmd(ENABLE);

       RTC_WaitForLastTask();

       RTC_SetCounter(seccount);

       RTC_WaitForLastTask();

       return 0;    

}

//得到当前的时间

//返回值:0,成功;其他:错误代码.

u8 RTC_Get(void)

{

       static u16 daycnt=0;

       u32 timecount=0;

       u32 temp=0;

       u16 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;}

                     }

                     else temp-=365;       //平年

                     temp1++;

              } 

              timer.w_year=temp1;//得到年份

              temp1=0;

              while(temp>=28)//超过了一个月

              {

                     if(Is_Leap_Year(timer.w_year)&&temp1==1)//当年是不是闰年/2月份

                     {

                            if(temp>=29)temp-=29;//闰年的秒钟数

                            else break;

                     }

                     else

                     {

                            if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年

                            else break;

                     }

                     temp1++;

              }

              timer.w_month=temp1+1;//得到月份

              timer.w_date=temp+1;  //得到日期

       }

       temp=timecount%86400;     //得到秒钟数    

       timer.hour=temp/3600;     //小时

       timer.min=(temp%3600)/60; //分钟    

       timer.sec=(temp%3600)%60; //秒钟

       timer.week=RTC_Get_Week(timer.w_year,timer.w_month,timer.w_date);//获取星期 

       return 0;

}   

//获得现在是星期几

//功能描述:输入公历日期得到星期(只允许1901-2099年)

//输入参数:公历年月日

//返回值:星期号                                                                                                                                                   

u8 RTC_Get_Week(u16 year,u8 month,u8 day)

{   

       u16 temp2;

       u8 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);

}                                                                                            联系QQ 940436962

此帖出自stm32/stm8论坛

最新回复

就是群里面的那个1569164539号~  详情 回复 发表于 2012-6-26 12:27
点赞 关注
个人签名QQ  940436962
http://www.y-ec.com/
上海银洋电子
 

回复
举报

272

帖子

0

TA的资源

纯净的硅(初级)

沙发
 
现在觉得,32就是那些配置不是很好理解,配置好了,函数的问题都不是很大
你就是那个银洋电子???
此帖出自stm32/stm8论坛

点评

你认识银洋电子 你是哪位?  详情 回复 发表于 2012-6-26 11:43
 
 

回复

132

帖子

0

TA的资源

一粒金砂(高级)

板凳
 

回复 沙发 xinjitmzy 的帖子

你认识银洋电子 你是哪位?
此帖出自stm32/stm8论坛

点评

就是群里面的那个1569164539号~  详情 回复 发表于 2012-6-26 12:27
 
个人签名QQ  940436962
http://www.y-ec.com/
上海银洋电子
 

回复

272

帖子

0

TA的资源

纯净的硅(初级)

4
 

回复 板凳 fuqing5542 的帖子

就是群里面的那个1569164539号~
此帖出自stm32/stm8论坛
 
 
 

回复

132

帖子

0

TA的资源

一粒金砂(高级)

5
 
此银洋电子非彼银洋电子 但是还属于银洋电子
此帖出自stm32/stm8论坛
 
个人签名QQ  940436962
http://www.y-ec.com/
上海银洋电子
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表