STM32学习笔记之RTC实时时钟2

发布时间:2023-08-21  

5. 程序实现


5.1 初始化


u8 RTC_Init(void){

    u8 temp=0;


    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);    //使能PWR和BKP外设时钟   

    PWR_BackupAccessCmd(ENABLE);    //使能后备寄存器访问  

    if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050)      //从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎

        {               


        BKP_DeInit();   //复位备份区域    

        RCC_LSEConfig(RCC_LSE_ON);  //设置外部低速晶振(LSE),使用外设低速晶振

        while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) //检查指定的RCC标志位设置与否,等待低速晶振就绪

            {

            temp++;

            delay_ms(10);

            }        if(temp>=250)            return 1;//初始化时钟失败,晶振有问题        

        RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);     //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟    

        RCC_RTCCLKCmd(ENABLE);  //使能RTC时钟  

        RTC_WaitForLastTask();  //等待最近一次对RTC寄存器的写操作完成

        RTC_WaitForSynchro();       //等待RTC寄存器同步  

        RTC_ITConfig(RTC_IT_SEC, ENABLE);       //使能RTC秒中断

        RTC_WaitForLastTask();  //等待最近一次对RTC寄存器的写操作完成

        RTC_EnterConfigMode();/// 允许配置  

        RTC_SetPrescaler(32767); //设置RTC预分频的值

        RTC_WaitForLastTask();  //等待最近一次对RTC寄存器的写操作完成

        RTC_Set(1972,1,2,1,1,1);  //设置时间    

        RTC_ExitConfigMode(); //退出配置模式  

        BKP_WriteBackupRegister(BKP_DR1, 0X5050);   //向指定的后备寄存器中写入用户程序数据

        }    else//系统继续计时

        {


        RTC_WaitForSynchro();   //等待最近一次对RTC寄存器的写操作完成

        RTC_ITConfig(RTC_IT_SEC, ENABLE);   //使能RTC秒中断

        RTC_WaitForLastTask();  //等待最近一次对RTC寄存器的写操作完成

        }

    RTC_NVIC_Config();//RCT中断分组设置                                

    RTC_Get();//更新时间    

    return 0; //ok}

static void RTC_NVICConfig(void){    

    NVIC_InitTypeDef NVIC_InitStructure;

    NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;      //RTC全局中断

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //先占优先级1位,从优先级3位

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //先占优先级0位,从优先级4位

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;     //使能该通道中断

    NVIC_Init(&NVIC_InitStructure);     //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器}

中断服务函数:void RTC_IRQHandler(void)

{         

    if (RTC_GetITStatus(RTC_IT_SEC) != RESET)//秒钟中断

    {                           

        RTC_Get();//更新时间   

     }    if(RTC_GetITStatus(RTC_IT_ALR)!= RESET)//闹钟中断

    {        RTC_ClearITPendingBit(RTC_IT_ALR);      //清闹钟中断        

      }                                                

    RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW);        //清闹钟中断

    RTC_WaitForLastTask();                                           

}

5.2 RTC部分实现


闰年判断:


//判断是否是闰年函数//月份   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<1970||syear>2099)        return 1;      

    for(t=1970;t

得到当前时间://得到当前的时间//返回值:0,成功;其他:错误代码.u8 RTC_Get(void)

{    static u16 daycnt=0;    u32 timecount=0; 

    u32 temp=0;    u16 temp1=0;


    timecount = RTC_GetCounter();     

    //timecount = 86400*4+88;

     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 ++;  

        }   

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

        temp1=0;        while(temp>=28)//28天,超过了最小的一个月

        {            if(Is_Leap_Year(calendar.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++;  

        }

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

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

    }

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

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

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

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

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


    return 0;

}

得到星期几://获得现在是星期几//功能描述:输入公历日期得到星期(只允许1901-2099年)//输入参数:公历年月日 //返回值:星期号                                                                                         u8 RTC_GetWeek(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;

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>