打印

GD32 RTC

[复制链接]
2526|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
paotangsan|  楼主 | 2021-6-3 16:11 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
部分GD32RTC只有一个存储寄存器,官方例程也只能存储时分秒,故此特别编写UTC时间,兼容上年月日周时分秒







---------------------------------------------------------------------------------------C---------------------------------------------------------------------------------------

#include "my_rtc.h"

const unsigned int NonleapYearMonth[12] = { 31, 31 + 28, 31 + 28 + 31,  31 + 28 + 31 + 30,  31 + 28 + 31 + 30 + 31,  31 + 28 + 31 + 30 + 31 + 30,  31 + 28 + 31 + 30 + 31 + 30 + 31,  31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,  31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,  31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,  31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,  31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 };
const unsigned int LeapYearMonth[12] = { 31, 31 + 29, 31 + 29 + 31,  31 + 29 + 31 + 30,  31 + 29 + 31 + 30 + 31,  31 + 29 + 31 + 30 + 31 + 30,  31 + 29 + 31 + 30 + 31 + 30 + 31,  31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,  31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,  31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,  31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,  31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 };

uint8_t my_rtc_cf(void)
{
    if(bkp_data_read(BKP_DATA_0) != 0xA5A5)
    return 0;
    else
    return 1;
}


使用特权

评论回复
沙发
paotangsan|  楼主 | 2021-6-3 16:11 | 只看该作者
void my_rtc_sync(void)
{
    rcu_periph_clock_enable(RCU_BKPI);
    rcu_periph_clock_enable(RCU_PMU);
    pmu_backup_write_enable();

    rtc_register_sync_wait();
    rtc_lwoff_wait();
    rcu_all_reset_flag_clear();
}


使用特权

评论回复
板凳
paotangsan|  楼主 | 2021-6-3 16:12 | 只看该作者
static unsigned char alg_IsLeapYear(unsigned int year)
{
    if((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))) //能被4整除,不能被百整除,能被400整除。
    {
        return 1;                //闰年
    }
    else
    {
        return 0;                //平年
    }
}


使用特权

评论回复
地板
paotangsan|  楼主 | 2021-6-3 16:12 | 只看该作者
my_timejg alg_Utc2LocalTime(unsigned int UtcVal, char TimeZone)
{
    unsigned int i = 0;
    my_timejg LocalTime;
    unsigned int Hour,Days,Year;


    LocalTime.my_seconds    =    UtcVal%60;                        //得到秒余数
    LocalTime.my_minutes    =    (UtcVal/60)%60;                //得到整数分钟数

    Hour    =    (UtcVal/60)/60;                                        //得到整数小时数
    LocalTime.my_hour    =    Hour%24+TimeZone;            //得到小时余数+时区
    if(LocalTime.my_hour>23)
    {
        LocalTime.my_hour-=24;
        Days=Hour/24+1;
    }
    else
    {
        Days=Hour/24;
    }
    LocalTime.my_week=(Days+4)%7;                            //计算星期,0-表示星期天        注:1970-1-1 是星期4

                                                    //注:400年=146097天,100年=36524天,4年=1461天
    Year = 1970;                                                            //utc时间从1970开始
    Year += (Days/146097)*400;

    Days %= 146097;                                                        //计算400年内的剩余天数
    Year += (Days/36525)*100;

    Days %= 36525;
    Year += (Days/1461)*4;

    Days %= 1461;                                                            //计算4年内剩余天数,1970平1972闰年
    while( Days > 365)
    {
        if(alg_IsLeapYear(Year))
        {
            Days--;
        }
        Days -= 365;
        Year++;
    }
    if (!alg_IsLeapYear(Year) && (Days == 365) )
    {
        Year++;
        LocalTime.my_day    =1;        
        LocalTime.my_month    =1;
        LocalTime.my_years    =Year;
        return LocalTime;
    }
    LocalTime.my_years    =Year;
    LocalTime.my_month=0;
    LocalTime.my_day=0;
    if (alg_IsLeapYear(Year))                                    //本年是闰年
    {
        for (i = 0; i < 12; i++)
        {
            if (Days < LeapYearMonth[i])
            {
                LocalTime.my_month = i + 1;
                if (i == 0)
                {
                    LocalTime.my_day = Days;
                }
                else
                {
                    LocalTime.my_day = Days - LeapYearMonth[i - 1];
                }
                LocalTime.my_day++;
                return LocalTime;
            }
        }
    }
    else                                                                            //本年是平年
    {
        for (i = 0; i < 12; i++)
        {
            if (Days < NonleapYearMonth[i])
            {
                LocalTime.my_month  = i + 1;
                if (i == 0)
                {
                    LocalTime.my_day = Days;
                }
                else
                {
                    LocalTime.my_day = Days - NonleapYearMonth[i - 1];
                }
                LocalTime.my_day++;
                return LocalTime;
            }
        }
    }
    return LocalTime;
}


使用特权

评论回复
5
paotangsan|  楼主 | 2021-6-3 16:12 | 只看该作者
unsigned int  alg_LocalTime2Utc(my_timejg LocalTime, char TimeZone)
{
    unsigned int y = LocalTime.my_years -1970;                            //看一下有几个400年,几个100年,几个4年
    unsigned int dy = (y / 400);
    unsigned int days = dy *  (400 * 365 + 97);                        //400年的天数

    dy = (y % 400) / 100;
    days += dy * (100 * 365 + 25);                                        //100年的天数

    dy = (y % 100) / 4;
    days += dy * (4 * 365 + 1);                                                //4年的天数

    dy = y % 4;                                                                                //注意:这里1972是闰年,与1970只差2年
    days += dy * 365 ;

    if(dy == 3)                                                                                //这个4年里,有没有闰年就差1天   
    {
        days++;    //只有这个是要手动加天数的,因为1973年计算时前面的天数按365天算,1972少算了一天
    }

    if (LocalTime.my_month != 1)
    {
        if(alg_IsLeapYear(LocalTime.my_years))                                                //看看今年是闰年还是平年
        {
            days += LeapYearMonth[(LocalTime.my_month - 1) - 1];
        }
        else
        {
            days += NonleapYearMonth[(LocalTime.my_month  - 1) - 1];         //如果给定的月份数为x则,只有x-1个整数月
        }
    }
    days += LocalTime.my_day - 1;

    return (days * 24 * 3600 + ((unsigned int)LocalTime.my_hour - TimeZone)* 3600 + (unsigned int)LocalTime.my_minutes * 60 + (unsigned int)LocalTime.my_seconds);  
}


使用特权

评论回复
6
paotangsan|  楼主 | 2021-6-3 16:13 | 只看该作者
void my_time_adjust(my_timejg time)
{
    rtc_lwoff_wait();
    rtc_counter_set(alg_LocalTime2Utc(time,8));
    rtc_lwoff_wait();

        //PMU 时钟打开
        rcu_periph_clock_enable(RCU_BKPI);
        rcu_periph_clock_enable(RCU_PMU);
        //备份域写使能
        pmu_backup_write_enable();
        //向备份域写入标记
        bkp_data_write(BKP_DATA_0, 0xA5A5);
        //备份域写失能
        pmu_backup_write_disable();
}



使用特权

评论回复
7
paotangsan|  楼主 | 2021-6-3 16:13 | 只看该作者
void my_time_read(my_timejg *time)
{
    *time=alg_Utc2LocalTime(rtc_counter_get(),8);
}

使用特权

评论回复
8
paotangsan|  楼主 | 2021-6-3 16:13 | 只看该作者
//重置备份域
static void bkp_deinit(void)
{
    /* reset BKP domain register*/
    rcu_bkp_reset_enable();
    rcu_bkp_reset_disable();
}

使用特权

评论回复
9
paotangsan|  楼主 | 2021-6-3 16:13 | 只看该作者
void my_rtc_init(void)
{
//PMU 时钟打开
    rcu_periph_clock_enable(RCU_BKPI);
    rcu_periph_clock_enable(RCU_PMU);
//备份域写使能和重置
    pmu_backup_write_enable();
    bkp_deinit();
//使能外部32.768晶振
    rcu_osci_on(RCU_LXTAL);
//等待外部时钟稳定
    rcu_osci_stab_wait(RCU_LXTAL);
//选择外部32.768时钟给RTC供给
    rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);
//使能RTC时钟
    rcu_periph_clock_enable(RCU_RTC);
//等待RTC注册同步
    rtc_register_sync_wait();
//等待RTC写完数据
    rtc_lwoff_wait();
//设置RTC分频器:设置RTC周期为1秒
    rtc_prescaler_set(32767);
//等待RTC写完数据
    rtc_lwoff_wait();
}


使用特权

评论回复
10
paotangsan|  楼主 | 2021-6-3 16:14 | 只看该作者
---------------------------------------------------------------------------------------H---------------------------------------------------------------------------------------

#ifndef __MY_RTC__
#define __MY_RTC__


#include "gd32f20x_rtc.h"
#include "gd32f20x_bkp.h"
#include "gd32f20x_rcu.h"
#include "gd32f20x_pmu.h"
#include "stdint.h"

//时间信息结构体
typedef struct
{
    unsigned char     my_seconds;      
    unsigned char     my_minutes;   
    unsigned char     my_hour;  
    unsigned char     my_day;  
    unsigned char     my_month;   
  unsigned char     my_week;      
    unsigned int     my_years;   
}my_timejg;

//设置时间
void my_time_adjust(my_timejg time);
//获取时间
void my_time_read(my_timejg *time);
//UTC时间转换
my_timejg alg_Utc2LocalTime(unsigned int UtcVal, char TimeZone);
//转换为UTC时间
unsigned int  alg_LocalTime2Utc(my_timejg LocalTime, char TimeZone);
//同步时间
void my_rtc_sync(void);
//查询是否设置过时间
uint8_t my_rtc_cf(void);

#endif


使用特权

评论回复
11
weifeng90| | 2021-6-3 21:39 | 只看该作者
为什么不直接上传附件了?

使用特权

评论回复
12
jheng| | 2021-10-13 14:22 | 只看该作者
((unsigned int)LocalTime.my_hour - TimeZone),有漏洞

使用特权

评论回复
13
huquanz711| | 2021-10-15 07:54 | 只看该作者
感谢楼主分享经验

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

53

主题

4119

帖子

0

粉丝