四、GD32 MCU 常见外设介绍(14)

GD32 MCU内部提供了一个RTC(实时时钟)模块,通过RTC可以实现日历时钟、闹钟等功能。RTC也可以用于深度睡眠或待机模式的低功耗唤醒。不同系列的GD32 MCU在RTC设计和功能上有所区别,总体可以分为三大系列:

(1)F10x、F30x、E10x系列RTC功能基本相同,后文简称0x系列。

(2)F1x0、F3x0、E23x系列RTC功能基本相同,后文简称x0系列。

(3)F405、F407、F450系列RTC功能基本相同,后文简称4xx系列。后文会对0x系列、x0系列、4xx系列的RTC模块分别进行介绍,简单介绍RTC的工作原理、配置使用方法。

14.1.GD32 RTC 外设简介

0x 系列 RTC

0x系列RTC整体架构相对精简,主要依靠32位累加计数器配置分频实现时钟计数。日历功能可通过软件计算并写入备份域中实现;同时具有闹钟功能可用于定时产生中断和唤醒唤醒事件;RTC的核心计数部分在备份域中,可在VDD断电时VBAT供电的情况保持RTC的计数,正常上电工作时通过APB总线接口可对RTC寄存器进行配置。

0x系列RTC主要特点:

◼ 32位可编程计数器,用于计数运行时间

– 可编程的预分频器: 分频系数最高可达220

◼ 独立时钟域:

– PCLK1时钟域

– RTC时钟域(该时钟必须比PCLK1时钟至少慢4倍)

◼ RTC时钟源:

– HXTAL时钟分频

– LXTAL振荡电路时钟

– IRC40K振荡电路时钟

◼ 可屏蔽的中断源:

– 闹钟中断

– 秒中断

– 溢出中断

0x系列RTC框图介绍:

RTC由两个主要部分组成,如下图0x系列RTC结构框图所示,位于PCLK1时钟域的APB接口和位于RTC时钟域的RTC内核。

输入图片说明

第一部分APB接口用来和APB1总线相连。此单元还包含一组16位寄存器,可通过APB1总线对其进行读写操作。对RTC模块进行相关配置。

另一部分(RTC核心)由一组可编程计数器组成,分成两个主要模块。第一个模块是RTC的预分频模块,RTC时钟源输入后经过预分频模块,可编程产生RTC时间基准SC_CLK。RTC的预分频模块包含了一个20位的可编程分频器(RTC预分频器);如果在RTC_INTEN寄存器中设置了相应的允许位,则在每个SC_CLK周期中RTC产生一个中断(秒中断)。

第二个模块是一个32位的可编程计数器,可被初始化为当前的系统时间。系统时间按SC_CLK周期累加并与存储在RTC_ALRM寄存器中的可编程时间相比较,如果RTC_INTEN控制寄存器中设置了相应允许位,比较匹配时将产生一个闹钟中断。

x0 系列 RTC

0x系列RTC提供了一个包含日期(年/月/日)和时间(时/分/秒/亚秒)的日历功能。除亚秒用二进制码显示外,时间和日期都以BCD码的形式显示。RTC可以进行夏令时补偿。RTC可以工作在省电模式下,并通过软件配置来智能唤醒。RTC支持外接更高精度的低频时钟,用以达到更高的日历精度。

x0系列RTC主要特点:

◼ 通过软件设置来实现夏令时补偿。

◼ 参考时钟检测功能:通过外接更高精度的低频率时钟源(50Hz/60Hz)来提高日历精度。

◼ 数字校准功能:通过调整最小时间单位(最大可调精度0.95ppm)来进行日历校准。

◼ 通过移位功能进行亚秒级调整。

◼ 记录事件时间的时间戳功能。

◼ 两个模式可配置的独立的侵入检测。

◼ 可编程的日历和一个位域可屏蔽的闹钟。

◼ 5个32位(共20字节)通用备份寄存器,能够在省电模式下保存数据。当有外部事件侵入时,备份寄存器将会复位。

◼ 可屏蔽的中断源:

– 闹钟0;

– 时间戳检测;

– 侵入检测;

x0系列RTC框图介绍:

x0系列RTC工作在备份域,可在低功耗模式下保持工作,通过APB总线可对RTC寄存器进行读取和配置。如下图x0系列RTC结构框图所示,RTC时钟源可配置通过数字平滑校准或直接输入到7位异步预分频器输出ck_apre时钟用于RTC_SS亚秒寄存器自减计数,ck_apre时钟又经过15位同步预分频器后输出1HZ的ck_spre时钟提供日历寄存器使用;基于日历寄存器还实现了闹钟和时间戳功能;RTC还具有闹钟、时钟输出功能,对RTC_TS、RTC_TAMP0、RTC_TAMP1引脚的有效输入可触发时间戳和侵入事件并产生中断。侵入事件会将备份域复位。

输入图片说明

◼ 闹钟

RTC闹钟功能被划分为多个位域并且每一个位域有一个该域的可屏蔽位。屏蔽某些位域后可固定周期产生闹钟事件。

◼ 侵入事件

RTC_TAMPx管脚可以作为侵入事件检测功能输入管脚,检测模式有两种可供用户选择:边沿检测模式或者是带可配置滤波功能的电平检测模式。侵入事件会将备份域复位,可产生一个中断。

◼ 可选的RTC输出功能:

  • 512Hz( 默认预分频值): RTC_OUT;

  • 1Hz( 默认预分频值): RTC_ OUT;

  • 闹钟事件( 极性可配置): RTC_ OUT。

◼ 可选的RTC输入功能:

  • 时间戳事件检测( RTC_TS);

  • 侵入事件检测 0( RTC_TAMP0);

  • 侵入事件检测 1( RTC_TAMP1);

  • 参考时钟输入 RTC_REFIN( 50 或 60Hz)。

◼ RTC中断

所有的RTC中断(闹钟、时间戳、侵入事件)都被连接到EXTI控制器。

4xx 系列 RTC 4xx系列RTC在x0系列RTC的基础上做了部分功能的升级。提供了一个包含日期(年/月/日)和时间(时/分/秒/亚秒)的日历功能。除亚秒用二进制码显示外,时间和日期都以BCD码的形式显示。

RTC可以进行夏令时补偿。RTC可以工作在省电模式下,并通过软件配置来智能唤醒。RTC支持外接更高精度的低频时钟,用以达到更高的日历精度。

  1. 4xx系列RTC主要特点:

◼ 通过软件设置来实现夏令时补偿。

◼ 参考时钟检测功能:通过外接更高精度的低频率时钟源(50Hz或60Hz)来提高日历精度。

◼ 数字校准功能:通过调整最小时间单位(最大可调精度0.95ppm)来进行日历校准。

◼ 通过移位功能进行亚秒级调整。

◼ 记录事件时间的时间戳功能。

◼ 两个模式可配置的独立的侵入检测。

◼ 可编程的日历和一个位域可屏蔽的闹钟。

◼ 20个32位(共80字节)通用备份寄存器,能够在省电模式下保存数据。当有外部事件侵入时,备份寄存器将会复位。

◼ 可屏蔽的中断源:

– 闹钟0和闹钟1;

– 时间戳检测;

– 自动唤醒事件;

– 侵入检测;

◼ 可配置周期的自动唤醒定时器

4xx系列RTC框图介绍:

4xx系列RTC工作在备份域,可在低功耗模式下保持工作,通过APB总线可对RTC寄存器进行读取和配置。如下图4xx系列RTC结构框图所示,RTC时钟源可配置通过数字平滑校准或直接输入到7位异步预分频器输出ck_apre时钟用于RTC_SS亚秒寄存器自减计数,ck_apre时钟又可通过数字粗平滑校准或直接输入15位同步预分频器后输出1HZ的ck_spre时钟提供日历寄存器使用;基于日历寄存器还实现了闹钟和时间戳功能;RTC还具有闹钟、时钟输出功能,对RTC_TS、RTC_TAMP0、RTC_TAMP1引脚的有效输入可触发时间戳和侵入事件并产生中断。侵入事件会将备份域复位。4xx系列RTC有一个独立的自动重加载唤醒定时器可用于产生唤醒事件和中断。

输入图片说明

◼ 闹钟

RTC闹钟功能被划分为多个位域并且每一个位域有一个该域的可屏蔽位。屏蔽某些位域后可固定周期产生闹钟事件。

◼ 侵入事件

RTC_TAMPx管脚可以作为侵入事件检测功能输入管脚,检测模式有两种可供用户选择:边沿检测模式或者是带可配置滤波功能的电平检测模式。侵入事件会将备份域复位,可产生一个中断。

◼ 可选的RTC输出功能:

  • 512Hz(默认预分频值):(RTC_OUT)PC13

  • 1Hz(默认预分频值):(RTC_OUT)PC13

  • 闹钟事件(极性可配置):(RTC_OUT)PC13

  • 自动唤醒事件(极性可配置):(RTC_OUT)PC13

◼ 可选的RTC输入功能:

  • 时间戳事件检测(RTC_TS):RTC_AF0、RTC_AF1;

  • 侵入事件检测 0(RTC_TAMP0):RTC_AF0、RTC_AF1;

  • 侵入事件检测 1(RTC_TAMP1):RTC_AF1;

  • 参考时钟输入 RTC_REFIN(50或60Hz)。

◼ RTC中断

所有的RTC中断(闹钟0、闹钟1、唤醒、时间戳、侵入0、侵入1)都被连接到EXTI控制器。

各系列 RTC 模块功能对比

x0系列中的E23x系列均没有VBAT引脚,不支持VDD掉电保持RTC工作。

0x系列备份域不同于x0、4xx系列,为单独的一个外设模块,所以使用RTC时,0x系列相比x0系列和4xx系列还需使能BKP的时钟。

各系列 RTC 模块功能对比

输入图片说明

14.2.GD32 RTC 硬件设计

◼ Vbat电源设计

Vbat可以连接至外部电池,在Vdd掉电时可以保证备份域不掉电、RTC继续运行。VBAT引脚需要对GND连接0.1uF电容,如果没有外部电池需要将VBAT和一个0.1uF电容连接至Vdd电源上。

输入图片说明

◼ RTC_TAMPx引脚

入侵事件会导致备份域复位,如使用该功能需注意检测引脚的滤波,可在RTC_TAMPx引脚上并联0.1uf电容。

14.3.GD32 RTC 软件配置

GD32MCU_Example下的RTC_Example例程配置了日历和闹钟功能,并开启了闹钟中断。本小节讲解RTC_Example例程中RTC模块的配置说明,主要包括时钟及分频配置、日历配置、闹钟配置、主函数说明。本例程主要介绍GD32 MCU各系列RTC模块的时间、闹钟配置,有关RTC其他功能例程可参考各系列固件库例程。

时钟及分频配置

◼ 由于RTC工作在备份域,所以使用RTC时需要使能备份域写功能,而控制备份域写功能的寄存器位于PMU中,所以操作RTC还需要将PMU_CTL寄存中的BKPWEN置位,从而还需使能PMU的时钟。而对于0x系列备份域为单独的外设,还需额外使能BKP备份域时钟。

◼ 为了实现准确的日历功能,配置RTC前需要准备好需要的时钟源,在选择合适的时钟源后RTC还需要进行预分频的配置。

0x系列时钟及分频配置如代码清单 RTC 0x系列时钟及分频配置所示,RTC使能后需要等待RTC寄存器和APB1时钟同步,执行rtc_register_sync_wait()函数;此外0x系列RTC在RTC寄存器配 置时需要等待上一次配置结束才能继续新的配置,所以在每个寄存器配置前需要执行rtc_lwoff_wait()函数,等待LWOFF置位。

代码清单 RTC 0x 系列时钟及分频配置

void rtc_config(void)
{
uint32_t prescaler=0;
/* enable PMU and BKPI clocks */rcu_periph_clock_enable(RCU_BKPI);rcu_periph_clock_enable(RCU_PMU);/* allow access to BKP domain */pmu_backup_write_enable();
#if RTC_CLOCK_SOURCE_IRC40K 
prescaler=40000;
/* enable LXTAL */rcu_osci_on(RCU_IRC40K);/* wait till LXTAL is ready */rcu_osci_stab_wait(RCU_IRC40K);/* select RCU_LXTAL as RTC clock source */rcu_rtc_clock_config(RCU_RTCSRC_IRC40K);
#elif RTC_CLOCK_SOURCE_LXTAL
prescaler=32767;
/* enable LXTAL */rcu_osci_on(RCU_LXTAL);/* wait till LXTAL is ready */rcu_osci_stab_wait(RCU_LXTAL);/* select RCU_LXTAL as RTC clock source */rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);
#else
#error RTC clock source should be defined.
#endif /* RTC_CLOCK_SOURCE_IRC40K *//* enable RTC Clock */rcu_periph_clock_enable(RCU_RTC);/* wait for RTC registers synchronization */rtc_register_sync_wait();/* wait until last write operation on RTC registers has finished */
rtc_lwoff_wait();/* set RTC prescaler: set RTC period to 1s */rtc_prescaler_set(prescaler);rtc_lwoff_wait();rtc_interrupt_enable(RTC_INT_ALARM);rtc_lwoff_wait();
}

x0系列时钟及分频配置如代码清单 RTC x0系列时钟及分频配置所示,RTC使能后需要等待RTC寄存器和APB1时钟同步,执行rtc_register_sync_wait()函数;和0x系列不同,后续配置过程x0和4xx系列均不需要执行rtc_lwoff_wait()函数。

代码清单 RTC x0 系列时钟及分频配置

void rtc_config(void)
{/* enable PMU clock */rcu_periph_clock_enable(RCU_PMU);/* enable the access of the RTC registers */pmu_backup_write_enable();#if (RTC_CLOCK_SOURCE_IRC40K) rcu_osci_on(RCU_IRC40K);rcu_osci_stab_wait(RCU_IRC40K);rcu_rtc_clock_config(RCU_RTCSRC_IRC40K);prescaler_s = 0x18F;prescaler_a = 0x63;#elif (RTC_CLOCK_SOURCE_LXTAL)rcu_osci_on(RCU_LXTAL);rcu_osci_stab_wait(RCU_LXTAL);rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);prescaler_s = 0xFF;prescaler_a = 0x7F;#else#error RTC clock source should be defined.#endif /* RTC_CLOCK_SOURCE_IRC40K */rcu_periph_clock_enable(RCU_RTC);rtc_register_sync_wait();
rtc_interrupt_enable(RTC_INT_ALARM); 
}

4xx系列时钟及分频配置如代码清单 RTC 4xx系列时钟及分频配置所示,和x0系列基本相同,但由于4xx系列内部低速时钟为32K,所以分频系数和x0系列有所不同。

代码清单 RTC 4xx 系列时钟及分频配置

void rtc_config(void)
{/* enable PMU clock */rcu_periph_clock_enable(RCU_PMU);/* enable the access of the RTC registers */pmu_backup_write_enable();#if (RTC_CLOCK_SOURCE_IRC32K) rcu_osci_on(RCU_IRC32K);rcu_osci_stab_wait(RCU_IRC32K);
rcu_rtc_clock_config(RCU_RTCSRC_IRC32K);prescaler_s = 0x13F;prescaler_a = 0x63;#elif (RTC_CLOCK_SOURCE_LXTAL)rcu_osci_on(RCU_LXTAL);rcu_osci_stab_wait(RCU_LXTAL);rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);prescaler_s = 0xFF;prescaler_a = 0x7F;#else#error RTC clock source should be defined.#endif /* RTC_CLOCK_SOURCE_IRC32K */rcu_periph_clock_enable(RCU_RTC);rtc_register_sync_wait();rtc_interrupt_enable(RTC_INT_ALARM0); 
}

日历配置

0x系列由于没有硬件日历功能,所以需要读取计数器通过软件计算出日历;而x0系列和4xx系列具有硬件日历功能,日期信息均是BCD码,所以在日历配置的格式和方式均有差别。

0x系列RTC的日历配置如代码清单 RTC 0x系列日历配置所示,该函数提供了日历配置的入口参数,先将需要配置的日历信息转换成秒单位,再写入RTC计数器即可。入口参数使用十进制写入。

代码清单 RTC 0x 系列日历配置

uint32_t rtc_time_set(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second)
{uint16_t t;uint32_t seccount = 0;if(year < 1970 || year > 2099)return ERROR;for(t = 1970; t < year; t++){if(is_leap_year(t)){seccount += 31622400;}else{seccount += 31536000;}}month -= 1;for(t=0; t < month; t++){seccount += (uint32_t)month_table[t] * 86400; if(is_leap_year(year) && t==1){seccount+=86400;}}seccount += (uint32_t)(day-1) * 86400;seccount += (uint32_t)hour * 3600;
seccount += second;
rtc_lwoff_wait();rtc_counter_set(seccount);
rtc_lwoff_wait();return SUCCESS;
}

x0系列RTC的日历配置如代码清单 RTC x0系列日历配置所示,该函数提供了日历配置的入口参数,参数为BCD码格式,写入后对RTC日历结构体赋初值,日历结构体还可以配置星期、时间格式等,这里默认配置了24小时制。函数入口参数使用16进制写入。

代码清单 RTC x0 系列日历配置

uint32_t rtc_time_set(uint16_t year,uint8_t month,uint8_t day,uint32_t tmp_hh,uint32_t tmp_mm,uint32_t tmp_ss)
{rtc_initpara.rtc_factor_asyn = prescaler_a;rtc_initpara.rtc_factor_syn = prescaler_s;rtc_initpara.rtc_year = year&0x00ff;rtc_initpara.rtc_day_of_week = RTC_SATURDAY;rtc_initpara.rtc_month = month;rtc_initpara.rtc_date = day;rtc_initpara.rtc_display_format = RTC_24HOUR;rtc_initpara.rtc_am_pm = RTC_AM;rtc_initpara.rtc_hour = tmp_hh;
rtc_initpara.rtc_minute = tmp_mm;rtc_initpara.rtc_second = tmp_ss;if(ERROR == rtc_init(&rtc_initpara)){return ERROR;
}
return SUCCESS;
}

4xx系列RTC的日历配置如代码清单 0-52 RTC 4xx系列日历配置所示,和x0系列基本相同, 唯一区别只是日历结构体成员名字少了“RTC_”的前缀。

代码清单 RTC 4xx 系列日历配置

uint32_t rtc_time_set(uint16_t year,uint8_t month,uint8_t day,uint32_t tmp_hh,uint32_t tmp_mm,uint32_t tmp_ss)
{rtc_initpara.factor_asyn = prescaler_a;rtc_initpara.factor_syn = prescaler_s;rtc_initpara.year = year&0x00ff;rtc_initpara.day_of_week = RTC_SATURDAY;rtc_initpara.month = month;rtc_initpara.date = day;rtc_initpara.display_format = RTC_24HOUR;rtc_initpara.am_pm = RTC_AM;rtc_initpara.hour = tmp_hh;
rtc_initpara.minute = tmp_mm;rtc_initpara.second = tmp_ss;if(ERROR == rtc_init(&rtc_initpara)){
return ERROR;
}
return SUCCESS;
}

闹钟配置

0x系列的RTC通过32位计数器运行时间,所以其闹钟也是32位数据,当计数器和闹钟值匹配时会产生闹钟事件或中断,所需配置的闹钟值为闹钟剩余倒计时加上当前计数器值;而x0系列和4xx系列是硬件BCD日历功能,所以其闹钟也是BDC格式,且具有位域屏蔽功能,根据需要直接配置具体的时间即可。

0x系列RTC的闹钟配置如代码清单 RTC 0x系列闹钟配置所示,该函数提供了闹钟配置的入口参数,先将需要配置的时间信息转换成秒单位,再加上当前计数器的值写入闹钟寄存器即可。

0x系列配置的闹钟参数为闹钟中断的倒计时时间,写入参数为十进制。

代码清单 RTC 0x 系列闹钟配置

void rtc_alarm_set(uint8_t hour, uint8_t minute, uint8_t second)
{alarm_second = 3600 * hour + minute * 60 + second;
rtc_lwoff_wait();rtc_alarm_config(rtc_counter_get() + alarm_second);
rtc_lwoff_wait();
} seccount += (uint32_t)(day-1) * 86400;seccount += (uint32_t)hour * 3600;seccount += (uint32_t)minute * 60;seccount += second;
rtc_lwoff_wait();rtc_counter_set(seccount);
rtc_lwoff_wait();return SUCCESS;
}

x0系列RTC的闹钟配置如代码清单 RTC x0系列闹钟配置所示,该函数提供了闹钟配置的入口参数,参数为BCD码格式,写入后对RTC闹钟结构体赋初值,闹钟结构体可以配置位域屏蔽、选择配置日期或星期、时间格式等,这里默认配置了屏蔽天、小时、分钟,所以配置最后实际生效的只有秒,所以配置后闹钟均是1分钟产生一次。闹钟配置前需失能闹钟,配置后再使能,4xx系列配置的闹钟参数为闹钟产生的日期时间,因BCD格式写入参数参数使用16进制。

代码清单 RTC x0 系列闹钟配置

void rtc_alarm_set(uint32_t tmp_hh,uint32_t tmp_mm,uint32_t tmp_ss)
{
rtc_alarm_struct rtc_alarm;rtc_alarm_disable();rtc_alarm.rtc_alarm_mask = RTC_ALARM_DATE_MASK|RTC_ALARM_HOUR_MASK|RTC_ALARM_MINUTE_MASK;rtc_alarm.rtc_weekday_or_date = RTC_ALARM_DATE_SELECTED;rtc_alarm.rtc_alarm_day = 0x31;rtc_alarm.rtc_am_pm = RTC_AM;rtc_alarm.rtc_alarm_hour = tmp_hh;rtc_alarm.rtc_alarm_minute = tmp_mm;rtc_alarm.rtc_alarm_second = tmp_ss;rtc_alarm_config(&rtc_alarm);rtc_alarm_enable(); 
}

4xx系列RTC的闹钟配置如代码清单 0-55 RTC 4xx系列闹钟配置所示,和x0系列基本相同, 唯一区别只是闹钟结构体成员名字少了“RTC_”的前缀。

代码清单 RTC 4xx 系列闹钟配置

uint32_t rtc_time_set(uint16_t year,uint8_t month,uint8_t day,uint32_t tmp_hh,uint32_t tmp_mm,uint32_t tmp_ss)
{rtc_initpara.factor_asyn = prescaler_a;rtc_initpara.factor_syn = prescaler_s;rtc_initpara.year = year&0x00ff;rtc_initpara.day_of_week = RTC_SATURDAY;rtc_initpara.month = month;rtc_initpara.date = day;rtc_initpara.display_format = RTC_24HOUR;rtc_initpara.am_pm = RTC_AM;rtc_initpara.hour = tmp_hh;
rtc_initpara.minute = tmp_mm;rtc_initpara.second = tmp_ss;if(ERROR == rtc_init(&rtc_initpara)){return ERROR;
}
return SUCCESS;
}

主函数说明 主函数如代码清单 RTC_Example主函数所示,主要包含了中断配置、RTC时钟源和预分频配置、日历设置以及闹钟设置,成功设置好日历和闹钟后在备份域数据寄存器写入一个标志位,下次非备份域复位的情况就可以不再重复配置RTC。While1中循环调用rtc_current_time_get()函数获取日历信息。4xx系列和x0系列中固件库底层已经提供了rtc_current_time_get()函数,直接更新至日历结构体;而0x系列固件库没有此函数,额外编写了相同接口的函数,通过读取32位计数器软件计算出日历信息更新至自定义的日历结构体中。通过仿真或串口打印可以看到结构体中的时间数据在更新。

代码清单 RTC_Example 主函数

int main(void)
{/* NVIC configure */nvic_config();
rtc_config();
alarm_second=5;
if (RTC_BKP0 != 0xA5A5){ /* backup data register value is not correct or not yet programmed(when the first time the program is executed) */
#if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10Xif(SUCCESS==rtc_time_set(2019, 10, 14, 12, 0, 0)){rtc_alarm_set(12, 12, alarm_second);
#elif defined GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X
if(SUCCESS==rtc_time_set(0x2019, 0x10, 0x14, 0x12, 0, 0)){
rtc_alarm_set(0x12, 0x12, alarm_second);
#endif
RTC_BKP0=0xA5A5;}}while (1){
/* updata time in infinite loop */rtc_current_time_get(&rtc_initpara);
}
}

代码清单 0x 系列自定义 rtc_current_time_get()主函数

void rtc_current_time_get(rtc_parameter_struct* RTC_Calend)
{static uint16_t daycnt = 0;uint32_t temp = 0,timevar=rtc_counter_get();uint16_t temp1 = 0;temp = timevar / 86400;if(daycnt != temp) {daycnt = temp;temp1 = 1970;while(temp >= 365){if(is_leap_year(temp1)){if(temp >= 366)temp-=366;else break;}else temp -= 365;temp1++;}RTC_Calend->years = temp1;temp1=0;while(temp >= 28){if(is_leap_year(RTC_Calend->years) && temp1 == 1){if(temp >= 29)temp -= 29;elsebreak;}else{if(temp >= month_table[temp1])temp -= month_table[temp1];elsebreak;}temp1++;}RTC_Calend->months = temp1 + 1;RTC_Calend->days = temp + 1;}temp = timevar % 86400;RTC_Calend->hours = temp / 3600;RTC_Calend->minutes = (temp % 3600) / 60; RTC_Calend->seconds = (temp % 3600) % 60; 
}

闹钟中断说明

例程中开启了闹钟中断,初始化调用rtc_alarm_set(uint8_t hour, uint8_t minute, uint8_t second)函数分别配置了“0时0分5秒”的闹钟。

◼ 对0x系列来说这个配置是倒计时“0时0分5秒”后产生闹钟,进入闹钟中断后再配置新的5s实现5s一次的闹钟周期;

◼ 对x0和4xx系列这个配置是时间在“0时0分5秒”时产生闹钟,但因为闹钟配置中已经屏蔽了闹钟的天、时、分位域,所以闹钟会在每分钟的5秒产生,闹钟周期为一分钟产生一次。

14.4.RTC 使用注意事项

1、 因为内部低速时钟是在VDDA电源域,所以VDD断电后VBAT供电情况下保持RTC运行需要使用外部低速时钟;此外使用LXTAL在非备份域复位时可以不用在初始化阶段配置,但使用内部低速时钟需要每次复位都进行内部时钟的初始化。

2、 内部低速时钟精度相对较差,如必须使用内部且对精度有一定要求,4xx和0x系列可以使用TIMER4、x0系列可以使用TIMER13捕获内部低速时钟,计算出实际的频率值来进行合适分频。

3、 日历信息意外被清零的话注意是否发生过备份域复位,是否有Vbat掉电或入侵事件发生。

4、 调试中如果修改了RTC代码的配置,请先擦除全片Flash,然后断电并上电后再下载新的代码。

更多GD32 MCU相关咨询:https://www.gd32bbs.com/ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3281628.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

springboot美食网站—计算机毕业设计源码11574

摘 要 随着人们生活水平的提高&#xff0c;人们对美食的要求也越来越高&#xff0c;对各类美食信息需求越来越大。因此&#xff0c;结合计算机快速发展、普及&#xff0c;在此基础上制作一个页面简单、美观,功能实用的美食网站势在必行&#xff0c;满足用户分享美食的需求。 美…

关于Handler你不知道的事

提到Handler&#xff0c;我们都会想到可以用来在子线程给UI线程发送消息&#xff0c;常用来子线程刷新UI。 而往深了问&#xff0c;你一定还知道Handler会绑定到一个Looper&#xff0c;而每个Looper会和一个MessageQ关联&#xff0c;从而达到向指定线程发送消息的功能。除此之外…

【计算机视觉学习之CV2图像操作实战:红绿灯识别1】

红绿灯识别1 步骤 高斯模糊边缘提取膨胀腐蚀中值滤波再次膨胀霍夫圆环检测区域将图片从BGR格式转换为HSV格式设计颜色阈值中值滤波统计像素点数 import cv2 import numpy as np COLOERS {red: (0, 0, 255),green: (0, 255, 0),yellow: (0, 255, 255), } def detect_color(im…

探索Netty框架的核心构件

Netty是一个高性能、异步事件驱动的网络应用程序框架&#xff0c;用于快速开发可维护的高性能、高可靠性的网络服务器和客户端程序。本文将深入探讨Netty框架的基本组件&#xff0c;帮助开发者更好地理解和使用这一强大的工具。 1. 事件循环&#xff08;EventLoop&#xff09;…

系统架构师--第1章计算机组成与体系结构-1.2 存储器系统

目录 1.2 存储器系统 1.2.1 主存储器 1.2.2 辅助存储器 1.2.3 Cache 存储器 &#xff08;1&#xff09;直接映像 &#xff08;2&#xff09;全相联映像 &#xff08;3&#xff09;组相联映像 1.2 存储器系统 存储器是用来存放程序和数据的部件&#xff0c;它是一个记忆装…

Vue - CSS基础学习

一、元素及属性 CSS 是为 web 内容添加样式的代码。 style标签 1.语法 1.除了选择器部分&#xff0c;每个规则集都应该包含在成对的大括号里&#xff08;{}&#xff09;。 2.在每个声明里要用冒号&#xff08;:&#xff09;将属性与属性值分隔开。 3.在每个规则集里要用分号…

Android Studio运行报错:module java.base dose not “opens java.io“ to unnamed module

今天第一次使用Android Studio运行一个安卓工程&#xff0c;报如图错误,应该是环境问题。 解决&#xff1a; 右上角的设置图标->settings->Buid,Execution,Deployment->Build Tools->Gradle->Gradle JDK->选择本地环境的java_home jdk&#xff08;怎么安装…

SEQ 4. 转录本蛋白编码能力预测软件(CPAT)

简 介 深度转录组测序能够检测数千个新的转录本。这一发现大而“隐藏”的转录组重新激活了对能够快速区分编码和非编码 RNA 的方法的需求。在这里提出了一种新的无比对方法&#xff0c;编码潜在评估工具( CPAT) &#xff0c;可以快速识别来自大量候选转录本的编码和非编码转…

公司里的IT是什么?

公司里的IT是什么&#xff1f; 文章目录 公司里的IT是什么&#xff1f;1、公司里的IT2、IT技术3、IT行业4、IT行业常见证书 如果对你有帮助&#xff0c;就点赞收藏把&#xff01;(&#xff61;&#xff65;ω&#xff65;&#xff61;)&#xff89;♡ 前段时间&#xff0c;在公…

【C语言】指针基础知识理解【续】

1. ⼆级指针 指针变量也是变量&#xff0c;是变量就有地址&#xff0c;那指针变量的地址存放在哪⾥&#xff1f;这就是 ⼆级指针 。 1.1 引入二级指针 由于一级指针已经很熟悉&#xff0c;这里就不再赘述&#xff0c;这里我们重点探讨二级指针 下面先简单使用一个二级指针看…

TPAMI 2024 | 全新框架!深度学习可解释度量学习!

TPAMI 2024 | 全新框架&#xff01;深度学习可解释度量学习&#xff01; DIML: Deep Interpretable Metric Learning via Structural Matching 题目&#xff1a;DIML: 通过结构匹配的深度可解释度量学习 作者&#xff1a;Wenliang Zhao, Yongming Rao, Jie Zhou , and Jiwen…

C++笔试强训10

文章目录 一、选择题1-5题6-10题 二、编程题题目一题目二 一、选择题 1-5题 前面做过很多次了&#xff0c;记住就好&#xff0c;不在赘述&#xff0c;选C。 内联函数经常使用的场景包括&#xff1a; 小型函数&#xff1a;当函数体非常小&#xff0c;只包含几条语句时&#xf…

【C++】模板的特化

文章目录 概念函数模板特化类模板特化全特化偏特化 概念 通常情况下&#xff0c;使用模板可以实现一些与类型无关的代码&#xff0c;但是有一些类型需要特殊处理&#xff0c;否则可能会得到一些错误的结果。 比如&#xff0c;在比较两个数的大小时&#xff0c;如果传入两个变量…

手动上电电路(电路收藏)

SW1按下 V1栅极对地 V1通 Vout给Mcu工作 GPIO2 高电平 V2通 SW1松开 V1栅极依然通过V2对地 维持V1通 Vout。再次按下SW1 GPIO1 对地 使Mcu收到中断 将GPIO2 输出低电平 V2关 松开SW1 V1栅极悬空 V1断开 Vout被截断

产品思维之什么是好的设计?

点击下方“JavaEdge”&#xff0c;选择“设为星标” 第一时间关注技术干货&#xff01; 免责声明~ 任何文章不要过度深思&#xff01; 万事万物都经不起审视&#xff0c;因为世上没有同样的成长环境&#xff0c;也没有同样的认知水平&#xff0c;更「没有适用于所有人的解决方案…

原生微信小程序wxml2canvas生成海报并包保存至本地

Wxml2Canvas是什么&#xff1f; Wxml2Canvas 是一个用于微信小程序开发的工具库&#xff0c;主要用途是将小程序页面的内容绘制成图片&#xff0c;以便生成海报或保存分享图片到相册等功能。具体用途包括&#xff1a; ①海报生成功能&#xff1a;允许开发者将当前页面的特定部…

【机器学习】决策边界的基本概念以及如何在逻辑回归中找到决策边界

引言 在机器学习中&#xff0c;决策边界是分类算法用来区分不同类别数据点的线、面或超平面。这些边界通常是模型的预测规则&#xff0c;用于将特征空间中的点分配到不同的类别。决策边界可以是线性的&#xff0c;也可以是非线性的&#xff0c;取决于数据的分布和所使用的分类算…

鸿蒙 HarmonyOS NEXT端云一体化开发-云数据库篇

一、概述 云数据库是一款基于对象模型的数据库&#xff0c;采用存储区、对象类型和对象三级结构。 数据模型 存储区 存储区是一个独立的数据存储区域&#xff0c;多个数据存储区之间相互独立&#xff0c;每个存储区拥有完全相同的对象类型定义 --类似于关系型数据库中的da…

ECMA6Script学习笔记(五)

【摘要】 本文是对自己学习ES6的学习笔记回顾,后面是概要: 本文介绍了ES6中的对象创建和拷贝方法。对象创建方面&#xff0c;ES6通过class关键字支持了面向对象的语法糖&#xff0c;包括属性设置、getter和setter方法、构造器、静态方法以及私有属性的定义。同时&#xff0c;展…

专业做护眼灯的有哪些品牌?五款市面主流护眼灯专业测评

专业做护眼灯的有哪些品牌&#xff1f;市面上出现的品牌毫不夸张的说&#xff0c;真的算得上是琳琅满目&#xff0c;而且每一个品牌都在说自己的产品才是最值得的&#xff0c;这种情况下来&#xff0c;很多人一时之间根本就不知道要选择哪一款比较好。而且还有一些还会买到低劣…