找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 304|回复: 0
打印 上一主题 下一主题
收起左侧

STM32单片机RTC时钟程序 带中文注释

[复制链接]
跳转到指定楼层
楼主
ID:1053560 发表于 2024-2-28 11:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32 RTC时钟带中文注释
#include "stm32f10x.h"                  // Device header
#include <time.h>

uint16_t MyRTC_Time[] = {2024, 2, 26, 15, 18, 00};        //定义全局的时间数组,数组内容分别为年、月、日、时、分、秒

void MyRTC_SetTime(void);                                //函数声明

/**
  * 函    数:RTC初始化
  * 参    数:无
  * 返 回 值:无
  */
void MyRTC_Init(void)
{
        /*开启时钟*/
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);                //开启PWR的时钟
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);                //开启BKP的时钟
        
        /*备份寄存器访问使能*/
        PWR_BackupAccessCmd(ENABLE);                                                        //使用PWR开启对备份寄存器的访问
        
        if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)                        //通过写入备份寄存器的标志位,判断RTC是否是第一次配置
                                                                                                                        //if成立则执行第一次的RTC配置
        {
                RCC_LSEConfig(RCC_LSE_ON);                                                        //开启LSE时钟
                while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) != SET);        //等待LSE准备就绪
               
                RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);                                //选择RTCCLK来源为LSE
                RCC_RTCCLKCmd(ENABLE);                                                                //RTCCLK使能
               
                RTC_WaitForSynchro();                                                                //等待同步
                RTC_WaitForLastTask();                                                                //等待上一次操作完成
               
                RTC_SetPrescaler(32768 - 1);                                                //设置RTC预分频器,预分频后的计数频率为1Hz
                RTC_WaitForLastTask();                                                                //等待上一次操作完成
               
                MyRTC_SetTime();                                                                        //设置时间,调用此函数,全局数组里时间值刷新到RTC硬件电路
               
                BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);                        //在备份寄存器写入自己规定的标志位,用于判断RTC是不是第一次执行配置
        }
        else                                                                                                        //RTC不是第一次配置
        {
                RTC_WaitForSynchro();                                                                //等待同步
                RTC_WaitForLastTask();                                                                //等待上一次操作完成
        }
}

//如果LSE无法起振导致程序卡死在初始化函数中
//可将初始化函数替换为下述代码,使用LSI当作RTCCLK
//LSI无法由备用电源供电,故主电源掉电时,RTC走时会暂停
/*
void MyRTC_Init(void)
{
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);
        
        PWR_BackupAccessCmd(ENABLE);
        
        if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)
        {
                RCC_LSICmd(ENABLE);
                while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) != SET);
               
                RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
                RCC_RTCCLKCmd(ENABLE);
               
                RTC_WaitForSynchro();
                RTC_WaitForLastTask();
               
                RTC_SetPrescaler(40000 - 1);
                RTC_WaitForLastTask();
               
                MyRTC_SetTime();
               
                BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
        }
        else
        {
                RCC_LSICmd(ENABLE);                                //即使不是第一次配置,也需要再次开启LSI时钟
                while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) != SET);
               
                RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
                RCC_RTCCLKCmd(ENABLE);
               
                RTC_WaitForSynchro();
                RTC_WaitForLastTask();
        }
}*/

/**
  * 函    数:RTC设置时间
  * 参    数:无
  * 返 回 值:无
  * 说    明:调用此函数后,全局数组里时间值将刷新到RTC硬件电路
  */
void MyRTC_SetTime(void)
{
        time_t time_cnt;                //定义秒计数器数据类型
        struct tm time_date;        //定义日期时间数据类型
        
        time_date.tm_year = MyRTC_Time[0] - 1900;                //将数组的时间赋值给日期时间结构体
        time_date.tm_mon = MyRTC_Time[1] - 1;
        time_date.tm_mday = MyRTC_Time[2];
        time_date.tm_hour = MyRTC_Time[3];
        time_date.tm_min = MyRTC_Time[4];
        time_date.tm_sec = MyRTC_Time[5];
        
        time_cnt = mktime(&time_date) - 8 * 60 * 60;        //调用mktime函数,将日期时间转换为秒计数器格式
                                                                                                        //- 8 * 60 * 60为东八区的时区调整
        
        RTC_SetCounter(time_cnt);                                                //将秒计数器写入到RTC的CNT中
        RTC_WaitForLastTask();                                                        //等待上一次操作完成
}

/**
  * 函    数:RTC读取时间
  * 参    数:无
  * 返 回 值:无
  * 说    明:调用此函数后,RTC硬件电路里时间值将刷新到全局数组
  */
void MyRTC_ReadTime(void)
{
        time_t time_cnt;                //定义秒计数器数据类型
        struct tm time_date;        //定义日期时间数据类型
        
        time_cnt = RTC_GetCounter() + 8 * 60 * 60;                //读取RTC的CNT,获取当前的秒计数器
                                                                                                        //+ 8 * 60 * 60为东八区的时区调整
        
        time_date = *localtime(&time_cnt);                                //使用localtime函数,将秒计数器转换为日期时间格式
        
        MyRTC_Time[0] = time_date.tm_year + 1900;                //将日期时间结构体赋值给数组的时间
        MyRTC_Time[1] = time_date.tm_mon + 1;
        MyRTC_Time[2] = time_date.tm_mday;
        MyRTC_Time[3] = time_date.tm_hour;
        MyRTC_Time[4] = time_date.tm_min;
        MyRTC_Time[5] = time_date.tm_sec;
}



#include "MyRTC.h"

int main(void)
{
        /*模块初始化*/
        OLED_Init();                //OLED初始化
        MyRTC_Init();                //RTC初始化
//        MyRTC_SetTime();//设置时间
        /*显示静态字符串*/
        OLED_ShowString(1, 1, "Date:XXXX-XX-XX");
        OLED_ShowString(2, 1, "Time:XX:XX:XX");
        OLED_ShowString(3, 1, "CNT :");
        OLED_ShowString(4, 1, "DIV :");
        
        while (1)
        {
                MyRTC_ReadTime();                                                        //RTC读取时间,最新的时间存储到MyRTC_Time数组中
               
                OLED_ShowNum(1, 6, MyRTC_Time[0], 4);                //显示MyRTC_Time数组中的时间值,年
                OLED_ShowNum(1, 11, MyRTC_Time[1], 2);                //月
                OLED_ShowNum(1, 14, MyRTC_Time[2], 2);                //日
                OLED_ShowNum(2, 6, MyRTC_Time[3], 2);                //时
                OLED_ShowNum(2, 9, MyRTC_Time[4], 2);                //分
                OLED_ShowNum(2, 12, MyRTC_Time[5], 2);                //秒
               
                OLED_ShowNum(3, 6, RTC_GetCounter(), 10);        //显示32位的秒计数器
                OLED_ShowNum(4, 6, RTC_GetDivider(), 10);        //显示余数寄存器
        }
}

原理图: 无
仿真: 无
代码: 12-2 实时时钟.7z (179.82 KB, 下载次数: 11)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表