GD32 RTC

部分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;
}

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();
}


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;                //平年
    }
}

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

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);  
}


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();
}


void my_time_read(my_timejg *time)
{
    *time=alg_Utc2LocalTime(rtc_counter_get(),8);
}

//重置备份域
static void bkp_deinit(void)
{
    /* reset BKP domain register*/
    rcu_bkp_reset_enable();
    rcu_bkp_reset_disable();
}

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();
}

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

 

 

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
GD32芯片的RTC模块是一个实时时钟计时器,用于提供精确的日期和时间信息。下面是GD32RTC配置步骤: 1. 开启RTC时钟:使能PWR和BKP模块时钟,然后设置RTC时钟源为LSE或者LSI。 ```c RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); RCC_LSEConfig(RCC_LSE_ON); // 开启LSE while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET); // 等待LSE稳定 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); // 选择RTC时钟源 ``` 2. 初始化RTC:设置RTC的分频系数、时间格式、并清除RTC计数器。 ```c RTC_InitTypeDef RTC_InitStructure; RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24; // 24小时格式 RTC_InitStructure.RTC_AsynchPrediv = 0x7F; // 异步分频系数为0x7F RTC_InitStructure.RTC_SynchPrediv = 0xFF; // 同步分频系数为0xFF RTC_InitStructure.RTC_OutPut = RTC_Output_Disable; // 输出禁止 RTC_Init(&RTC_InitStructure); RTC_WriteProtectionCmd(DISABLE); // 取消写保护 RTC_SetCounter(0); // 清除RTC计数器 RTC_WriteProtectionCmd(ENABLE); // 使能写保护 ``` 3. 启用RTC中断:使能RTC中断,然后在中断服务函数中处理RTC事件。 ```c NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; // RTC中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 抢占优先级0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 子优先级0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); RTC_ITConfig(RTC_IT_SEC, ENABLE); // 使能RTC秒中断 RTC_ClearITPendingBit(RTC_IT_SEC); // 清除RTC秒中断标志位 ``` 以上是GD32 RTC的基本配置步骤,具体配置还需要根据实际需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值