rtc.c文件如下:具体请查看原子哥正点原子RTC实时时钟例程,发现BUG , 求解决。-OpenEdv-开源电子网

#include "sys.h"
#include "delay.h"
#include "rtc.h"
#include "stdio.h"

_calendar_obj calendar;//时钟结构体

//static void RTC_NVIC_Config(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寄存器
//}

//实时时钟配置
//初始化RTC时钟,同时检测时钟是否工作正常
//BKP->DR1用于保存是否第一次配置的设置
//返回0:正常
//其他:错误代码

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) != 0xA5A2)        //从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎
    {
        BKP_DeInit();    //复位备份区域
        RCC_LSEConfig(RCC_LSE_ON);    //设置外部低速晶振(LSE),使用外设低速晶振
        while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET&&temp<250)    //检查指定的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(2022,4,26,10,30,55);  //设置时间
        RTC_ExitConfigMode(); //退出配置模式
        BKP_WriteBackupRegister(BKP_DR1, 0XA5A5);    //向指定的后备寄存器中写入用户程序数据
    }
    else//系统继续计时
    {

RTC_WaitForSynchro();    //等待最近一次对RTC寄存器的写操作完成
        RTC_ITConfig(RTC_IT_SEC, ENABLE);    //使能RTC秒中断
        RTC_WaitForLastTask();    //等待最近一次对RTC寄存器的写操作完成
    }
    //RTC_NVIC_Config();//RCT中断分组设置
    RTC_Get();//更新时间
    return 0; //ok

}
//RTC时钟中断
//每秒触发一次
//extern u16 tcnt;
//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_Get();                //更新时间
//        printf("Alarm Time:%d-%d-%d %d:%d:%d\n",calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);//输出闹铃时间

//    }
//    RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW);        //清闹钟中断
//    RTC_WaitForLastTask();
//}
//判断是否是闰年函数
//月份   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<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_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);    //使能PWR和BKP外设时钟
    PWR_BackupAccessCmd(ENABLE);    //使能RTC和后备寄存器访问
    RTC_SetCounter(seccount);    //设置RTC计数器的值

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

//初始化闹钟
//以1970年1月1日为基准
//1970~2099年为合法年份
//syear,smon,sday,hour,min,sec:闹钟的年月日时分秒
//返回值:0,成功;其他:错误代码.
u8 RTC_Alarm_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<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_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);    //使能PWR和BKP外设时钟
    PWR_BackupAccessCmd(ENABLE);    //使能后备寄存器访问
    //上面三步是必须的!

RTC_SetAlarm(seccount);

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

return 0;
}

//得到当前的时间
//返回值:0,成功;其他:错误代码.
u8 RTC_Get(void)
{
    static u16 daycnt=0;
        u32 timecount=0;
        u32 temp=0;
        u16 temp1=0;          
        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 break;  
                        }
                        else temp-=365;          //平年
                        temp1++;  
                }   
                calendar.w_year=temp1;//得到年份
                temp1=0;
                while(temp>=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_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);
}

main.c文件如下:MAX7219请查看上一次发布或者请查看原子哥:

stm32f103rct6利用max7219驱动数码管显示-OpenEdv-开源电子网

#include "stm32f10x.h"
#include "delay.h"
#include "sys.h"
#include "MAX7219.h" 
#include "rtc.h"
int main(void)
{
        SysTick_Init(72);//延时初始化
    GPIOA_Init();        //GPIA初始化
        RTC_Init();    
    delay_ms(50);
    Init_MAX7219();
    delay_ms(2000);
        RTC_Set(2022,4,26,15,30,55);
    while(1)
    {
        RTC_Get();
    Write_Max7219(1,calendar.sec%10);
    Write_Max7219(2,calendar.sec/10);
    Write_Max7219(3,10);
    Write_Max7219(4,calendar.min%10);
    Write_Max7219(5,calendar.min/10);
    Write_Max7219(6,10);
    Write_Max7219(7,calendar.hour%10);
    Write_Max7219(8,calendar.hour/10);
        delay_s(2);
        Write_Max7219(1,calendar.w_date%10);
    Write_Max7219(2,calendar.w_date/10);
    Write_Max7219(3,10);
    Write_Max7219(4,calendar.w_month%10);
    Write_Max7219(5,calendar.w_month/10);
    Write_Max7219(6,10);
    Write_Max7219(7,(calendar.w_year%100)%10);
    Write_Max7219(8,(calendar.w_year%100)/10);
        delay_s(1);
    }
     
 }

MAX7219数码管+RTC时钟——stm32相关推荐

  1. STM32读取RTC时钟

    STM32读取RTC时钟 一.RTC 1. 简介 2. 特征 3. 组成 二.项目创建 三.代码修改 四.总结 参考 一.RTC 1. 简介 RTC-real time clock,实时时钟,主要包含 ...

  2. STM32物联网项目-RTC时钟

    RTC时钟 RTC简介 实时时钟是一个独立的定时器.RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能.修改计数器的值可以重新设置系统当前的时间和日期. RTC模块和时钟配置系 ...

  3. 纠结的STM32 RTC时钟源LSE

    一开始,所有实验都是在神舟板上去完成,根本就没有发现RTC的问题.直到我们自己画板来后调试时,才发现STM32 RTC的外部时钟源存在问题. 这也算是STM32的一个鸡肋,对于LSE外部晶振太过于苛刻 ...

  4. esp32 rtc 时钟设置不对_STM32入门系列-STM32时钟系统,STM32时钟树

    时钟对于单片机来说是非常重要的,它为单片机工作提供一个稳定的机器周期从而使系统能够正常运行.时钟系统犹如人的心脏,一旦有问题整个系统就崩溃.我们知道STM32属于高级单片机,其内部有很多的外设,但不是 ...

  5. 什么是RCT实时时钟?(STM32中RTC时钟源)

    什么是RCT(Real Time Clock,实时时钟)? 一.RTC时钟简介 RTC(Real Time Clock,实时时钟)是指安装在电子设备或实现其功能的IC(集成电路)上的时钟,一般会是集成 ...

  6. STM32CubeMX | STM32 F1系列HAL库低功耗STOP和STANDBY模式唤醒(RTC时钟唤醒+外部中断唤醒示例)

    STM32CubeMX | STM32 F1系列HAL库低功耗STOP和STANDBY模式唤醒(RTC时钟唤醒+外部中断唤醒示例) 目录 STM32CubeMX | STM32 F1系列HAL库低功耗 ...

  7. STM32 RTC时钟源LSE

    一开始,所有实验都是在神舟板上去完成,根本就没有发现RTC的问题.直到我们自己画板来后调试时,才发现STM32 RTC的外部时钟源存在问题. 这也算是STM32的一个鸡肋,对于LSE外部晶振太过于苛刻 ...

  8. STM32之RTC时钟

    前言 了解实时时钟RTC的原理.STM32芯片自带RTC,因此不须像其他MCU需外接RTC模块.请编程实现STM32的日历读取.设置和输出.要求: 1)读取RTC初始时间,验证是否为 1970年1月1 ...

  9. STM32 RTC时钟读取时间

    文章目录 一.RTC简介 1.1 RTC 1.2 RTC特征 1.3 RTC原理框图 1.4 RTC工作流程 1.5 RTC时钟选择 1.6 RTC复位过程 1.7 RTC中断 二.CubeMX配置 ...

最新文章

  1. 计算机视觉开源库OpenCV之利用开操作(Opening Operation)修复受损照片方法
  2. Mysql8.0注意url变更写法
  3. 注册表编辑器厘米爱你找不到mysql,win7系统中安装mysql后找不到服务或出现找不到指定文件的解决方法...
  4. error: conversion from ‘const char [ ]‘ to non-scalar type
  5. P3702-[SDOI2017]序列计数【矩阵乘法】
  6. 当执行游戏0xc000007b错误的解决方法
  7. linux_shell_根据网站来源分桶
  8. C++获取多维数组维数
  9. android for opencv (2) byte[] ,Bitmap 与 Mat 类型转换,Bitmap保存照片
  10. PHP substr(),mb_substr(),mb_strcut()比较
  11. 【操作系统】-- 时间片轮转调度算法、优先级调度算法、多级反馈队列调度算法
  12. MySQL 误删数据恢复
  13. 《UnityAPI.Transform变换》(Yanlz+Unity+SteamVR+云技术+5G+AI+VR云游戏+Transform+eulerAngles+LookAt+立钻哥哥++OK++)
  14. 【HCIE备考】笔试题库P1-10
  15. eclipse使用install报No compiler is provided in this environment. Perhaps you are running on a JRE rathe
  16. gcc与cuda的关系
  17. 美团配送和亚马逊AWS的异曲同工
  18. 等保测评师-等保测评工程师-发展路线(不喜勿喷)
  19. Java 学习 - 全文索引 - Lucene
  20. 360云盘关闭:一个360系列粉的吐槽

热门文章

  1. 一种基于卷积神经网络的数据驱动故障诊断方法
  2. 通往真理的最短路径 - 【复数】科普/详解
  3. Python实现照片里添加文字
  4. UART(Universal Asynchronous Receiver/Transmitter,异步收发传输器)
  5. ## IDEA创建maven项目没有src目录问题解决
  6. SwiftUI:属性装饰器的理解@State,@Binding,@ObservedObject,@Published,@Environment,@EnvironmentObject
  7. 杨可桢机械设计基础第6版笔记和课后答案
  8. winfrom下载服务器图片到本地,用C#打开Windows自带的图片传真查看器
  9. 茗创:脑电数据处理业务
  10. error: invalid application of 'sizeof' to an incomplete type 'JNINativeMethod []'