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

发布者:mmsg3814最新更新时间:2023-08-21 来源: elecfans关键字:STM32  RTC  实时时钟 手机看文章 扫描二维码
随时随地手机看文章

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;

[1] [2]
关键字:STM32  RTC  实时时钟 引用地址:STM32学习笔记之RTC实时时钟2

上一篇:应用笔记|巧用 STM32CubeIDE 之编译警告
下一篇:基于STM32定时器捕获测量脉宽的应用示例

推荐阅读最新更新时间:2024-11-12 03:12

STM32的CAN总线的接收双FIFO使用方法
通过下面的框图我们可以看到,STM32F013有两个接收FIFO 但是实际的使用中如何让着两个FIFO都被使用呢,解决办法就在这里, 1. STM32F103有0-13共14个过滤器组,每个过滤器组都可以绑定指定的FIFO。 2. 特别需要注意的一点是,FIFO0和FIFO1的接收对应不同的中断入口,切记。 分别是 DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0 DCD CAN1_RX1_IRQHandler ; CAN1 RX1 ================================================
[单片机]
<font color='red'>STM32</font>的CAN总线的接收双FIFO使用方法
STM32开发笔记62: 使用MicroLIB
单片机型号:STM32F407VGT6 microLIB 是缺省 C 库的备选库,它旨在与需要装入到极少量内存中的深层嵌入式应用程序配合使用。LwIP中使用了microLIB,如果不勾选microLIB选项,则程序不能够正常运行,其主要原因在于LwIP使用了microLIB提供的标准输入和输出函数。本文对microLIB做详细介绍。 1、microLIB介绍 Microlib is an alternative library to the default C library. It is intended for use with deeply embedded applications that must fit
[单片机]
<font color='red'>STM32</font>开发笔记62: 使用MicroLIB
STM32的sd卡的IAP升级固件教程
一. 1.功能:通过sd卡升级stm32的固件 2.所需要的设备:STM32的最小系统、sd卡模块、sd卡、keil软件,boot升级程序,APP程序 二. 1.据程序中的接口连接好电气关系,具体的电路图根据附件1连接(根据个人,这个附件就不上传了) 2.首先打开附件2的stm32 boot升级程序 3.根据如图所示设置stm32 boot程序下的keil软件 3.如图上第三步的标示是留给64k的boot引导程序区,这一步是根据你的stm32的flash的大小设定的,一般留有64k空间足够用了 4.这个要注意 5.如上图设置好的后,下载到板子里面 三. 1.打开附件3的
[单片机]
<font color='red'>STM32</font>的sd卡的IAP升级固件教程
一文读懂STM32之独立看门狗/窗口看门狗的原理
一、独立看门狗 STM32的独立看门狗由内部专门的40Khz低速时钟驱动,即使主时钟发生故障,它也仍然有效。 看门狗的原理:单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路就是为了避免这种情况的发生。看门狗的作用就是在一定时间内(通过定时计数器实现)没有接收喂狗信号(表示MCU已经挂了),便实现处理器的自动复位重启(发送复位信号)。 在键值寄存器(IWDG_KR)中写入0xCCCC,开始启用独立看门狗;此时计数器开始从其复位值0xFFF递减计数。当计数器计数到末尾0x000时,会产生一个复位信号(IWDG_RESET)。无论何时,只要键寄存器IWDG_KR中被写入0xAAAA,IWDG_RLR中的值就会被
[单片机]
一文读懂<font color='red'>STM32</font>之独立看门狗/窗口看门狗的原理
STM32L151中RTC_WakeUpCmd()函数带来了系统延时
ErrorStatus RTC_WakeUpCmd(FunctionalState NewState) { __IO uint32_t wutcounter = 0x00; uint32_t wutwfstatus = 0x00; ErrorStatus status = ERROR; assert_param(IS_FUNCTIONAL_STATE(NewState)); RTC- WPR = 0xCA; RTC- WPR = 0x53; if (NewState != DISABLE) { RTC- CR |= (uint32_t)RTC_CR_WUTE; status = SUCCE
[单片机]
以太网简介以及SMI接口
以太网简介 STM32F20X和STM32F21的以太网外设可接受和发送数据按照IEE802.3-2002标准。 以太网提供一个完整的、灵活的外设去满足不同应用和要求。它支持与外部相连(PHY)的两个标准的工业接口:默认情况使用在IEEE802.3规范中定义的独立介质接口(MII)和精简介质独立接口(RMII)。它可以被用于大量的需求,例如开关(交换机)、网络接口卡等等。 以太网满足下列标准: ● IEEE 802.3-2002,用于以太网MAC。 ● IEEE 1588-2008标准,用于规定联网时钟同步的精度。 ● AMBA 2.0,用于AHB主/从端口。 ● RMII联盟的RMII规范。 02 STM32F207的ETH介绍
[单片机]
以太网简介以及SMI接口
Arduino_Core_STM32---pinMode()实现分析
pinMode()定义 Arduino平台的易于使用性主要就体现在屏蔽的大量底层细节的实现,对于该函数来说也不例外。虽然该函数只有两个参数(arduino引脚号和模式),但这两个参数需要多层的映射才能转化为具体适合STM32芯片的配置信息,并调用底层接口完成配置。 从下面源码中可以看出主要由两个函数来完成引脚模式配置的:digitalPinToPinName()和pinfunction()。在具体深入下面两个函数之前我们需要一些预备知识—该库对于STM32硬件端口和引脚的封装。 void pinMode(uint32_t ulPin, uint32_t ulMode) { PinName p = digitalPinTo
[单片机]
stm32中断解释
一,中断优先级: STM32(Cortex-M3)中的优先级概念 STM32(Cortex-M3)中有两个优先级的概念——抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。 具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。 当 两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后 才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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