0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

GD32F470的RTC时间设置和获取,以及其中BCD码的坑

撞上电子 2023-12-26 08:00 次阅读

一,背景知识

1、RTC时钟源:有三种:IRC32K,内部低速时钟源,不精确,温漂大;LXTAL:外部低速时钟源,32.768KHz,精度高;HXTAL:外部高速时钟源。

2、实时时钟 (RTC) 是一个独立的 BCD 定时器/计数器;32 位寄存器包含 BCD 格式的秒、分钟、小时(12 或 24 小时制)、星期几、日期、月份和年份。

3、BCD进制:BCD进制是便于人们快速进行二进制和十进制之间的转换产生的,是由4位bit表示十进制中的0~9。4位bit可以表示的范围是2^4=16,所以BCD进制也有几种分类:

8421码:因为从左到右这4位bit,每位为1其他位为0时分别对应十进制数值8/4/2/1,以此得名。

d4f3217e-a381-11ee-9788-92fbcf53809c.png

余3码:在8421码的基础上偏移3

d50005ba-a381-11ee-9788-92fbcf53809c.png

2421码:

d4f3217e-a381-11ee-9788-92fbcf53809c.png

二、RTC初始化

初始化部分按照GD的RTC例程,去掉提示信息printf这些不需要的东西。初始化先随意设置一个时间,第二章节会讲解如何按照用户需求设定时间。

1、宏定义和全局变量:

选定RTC的时钟源--LXTAL,定义RTC的句柄全局变量。

#define RTC_CLOCK_SOURCE_LXTAL //使用外部32.768K晶振#define BKP_VALUE 0x32F1 rtc_parameter_struct rtc_initpara; //RTC句柄

2、RTC的初始化:

使能寄存器写入,选择时钟源,设置分频值产生1Hz时钟频率:时钟源频率/( prescaler_a * prescaler_s)=32768/(0x7f * 0xff)=1,使能外设时钟。

void RTC_Init(void){ /* enable PMU clock */ rcu_periph_clock_enable(RCU_PMU); /* enable the access of the RTC registers */ pmu_backup_write_enable(); rtc_pre_config(); /* get RTC clock entry selection */ RTCSRC_FLAG = GET_BITS(RCU_BDCTL, 8, 9); /* check if RTC has aready been configured */ if ((BKP_VALUE != RTC_BKP0) || (0x00 == RTCSRC_FLAG)) { /* backup data register value is not correct or not yet programmed or RTC clock source is not configured (when the first time the program is executed or data in RCU_BDCTL is lost due to Vbat feeding) */ rtc_setup(); } rcu_all_reset_flag_clear();} /*! \brief RTC configuration function \param[in] none \param[out] none \retval none*/void rtc_pre_config(void){ #if defined (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 defined (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();} /*! \brief use hyperterminal to setup RTC time and alarm \param[in] none \param[out] none \retval none*/void rtc_setup(void){ /* setup RTC time value */ uint32_t tmp_hh = 0x00, tmp_mm = 0x00, tmp_ss = 0x00; rtc_initpara.factor_asyn = prescaler_a; rtc_initpara.factor_syn = prescaler_s; rtc_initpara.year = 0x16; rtc_initpara.day_of_week = 0; rtc_initpara.month = RTC_APR; rtc_initpara.date = 0x30; 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; /* RTC current time configuration */ if(ERROR != rtc_init(&rtc_initpara)) { RTC_BKP0 = BKP_VALUE; }}

三、设置时间和获取时间1、BCD和二进制转换函数:

/** * @brief Convert a 2 digit decimal to BCD format. * @param Value: Byte to be converted * @retval Converted byte */uint8_t byte_to_bcd(uint8_t Value){ uint32_t bcdhigh = 0; while(Value >= 10) { bcdhigh++; Value -= 10; } return ((uint8_t)(bcdhigh << 4) | Value);} /** * @brief Convert from 2 digit BCD to Binary. * @param Value: BCD value to be converted * @retval Converted word */uint8_t bcd_to_byte(uint8_t Value){ uint32_t tmp = 0; tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10; return (tmp + (Value & (uint8_t)0x0F));}

2、设置指定时间:

注意一定要将年月日时分秒等参数从二进制转换成BCD,再赋值给rtc_initpara

typedefstruct{uint8_t year;uint8_t month;uint8_t date;uint8_t hour;uint8_t minute;uint8_t second;}S_RTCTimeInfo;//均为二进制格式 S_RTCTimeInfo RTCTime;//RTC全局变量,存储外界输入的待设定的时间 /*需要设定时间时调用此函数,将时间赋值给RTC句柄*/void RtcSetTime(S_RTCTimeInfo time){ rtc_initpara.year = byte_to_bcd(time.year); rtc_initpara.month= byte_to_bcd(time.month); rtc_initpara.date= byte_to_bcd(time.date); rtc_initpara.hour= byte_to_bcd(time.hour); rtc_initpara.minute= byte_to_bcd(time.minute); rtc_initpara.second= byte_to_bcd(time.second); rtc_init(&rtc_initpara);}

3、获取当前时间:

void RtcGetTime(void){ rtc_current_time_get(&rtc_initpara); RTCTime.year = bcd_to_byte(rtc_initpara.year); RTCTime.month= bcd_to_byte(rtc_initpara.year); RTCTime.date= bcd_to_byte(rtc_initpara.year); RTCTime.hour= bcd_to_byte(rtc_initpara.year); RTCTime.minute= bcd_to_byte(rtc_initpara.year); RTCTime.second= bcd_to_byte(rtc_initpara.year);}

四、遇到的问题

1、如果不使用周几,可以将rtc_initpara.day_of_week设为0,这样就不启用这项了。如果初始化时设置了day_of_week,后续修改设定时间时没有将这项对应修改,会造成设置的时间不准。因为设定时间赋值后会进行rtc_init,day_of_week会影响reg_date。

/*gd32f4xx_rtc.c文件中*/ErrStatus rtc_init(rtc_parameter_struct *rtc_initpara_struct){ ErrStatus error_status = ERROR; uint32_t reg_time = 0U, reg_date = 0U; reg_date = (DATE_YR(rtc_initpara_struct->year) | \ DATE_DOW(rtc_initpara_struct->day_of_week) | \ DATE_MON(rtc_initpara_struct->month) | \ DATE_DAY(rtc_initpara_struct->date));...省略部分代码}

2、当没有使用宏定义,而是使用数字给rtc_initpara 的年月日时分秒赋值时,一定要进行二进制到BCD的转换。对于此问题,STM32H7的HAL库就封装的很人性化,HAL库函数提供了可以选择使用哪种进制,,用户只需要选择对应的进制,传入参数即可,不需要自己进行进制转换。

/*stm32h7xx_hal_rtc.c文件*/ /** * @brief Set RTC current date. * @param hrtc: RTC handle * @param sDate: Pointer to date structure * @param Format: specifies the format of the entered parameters. * This parameter can be one of the following values: * @arg RTC_FORMAT_BIN: Binary data format * @arg RTC_FORMAT_BCD: BCD data format * @retval HAL status */HAL_StatusTypeDefHAL_RTC_SetDate(RTC_HandleTypeDef*hrtc,RTC_DateTypeDef*sDate,uint32_tFormat);

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • BCD
    BCD
    +关注

    关注

    1

    文章

    86

    浏览量

    29685
  • RTC
    RTC
    +关注

    关注

    2

    文章

    531

    浏览量

    66375
  • 时钟源
    +关注

    关注

    0

    文章

    93

    浏览量

    15945
收藏 人收藏

    评论

    相关推荐

    GD32F470紫藤派开发板使用手册】第九讲 USART-printf打印实验

    通过本实验主要学习以下内容: 串口简介 GD32F470串口工作原理 使用printf打印信息
    的头像 发表于 05-13 10:14 1661次阅读
    【<b class='flag-5'>GD32F470</b>紫藤派开发板使用手册】第九讲  USART-printf打印实验

    GD32F470紫藤派开发板使用手册】第十一讲 SPI-SPI NOR FLASH读写实验

    通过本实验主要学习以下内容: •SPI简介 •GD32F470 SPI简介 •SPI NOR FLASH——GD25Q32ESIGR简介 •使用GD32F470 SPI接口实现对GD2
    的头像 发表于 05-17 09:57 1689次阅读
    【<b class='flag-5'>GD32F470</b>紫藤派开发板使用手册】第十一讲 SPI-SPI NOR FLASH读写实验

    采用GD32F470高性能MCU的PowerWriter X1多功能调试烧录器

    GD32F470/F427/F425系列Cortex-M4内核高性能MCU 以高性能、强实时、大容量特性,强化更为广泛的市场领先优势。采用Arm Cortex-M4内核,处理器主频高达240MHz,可支持算法复杂度更高的嵌入式应
    的头像 发表于 08-22 09:43 1952次阅读
    采用<b class='flag-5'>GD32F470</b>高性能MCU的PowerWriter X1多功能调试烧录器

    使用GD32F470编译drv_adc.c时报错怎么解决?

    使用GD32F470芯片,编译drv_adc.c时报错好几个编译错误,可能是适配GD32F470芯片没有适配好。 编译问题如下图:
    发表于 02-23 06:55

    GD32F103的RTC实现

    一、GDRTC:只有GD32F405、GD32F407和GD32F450带完整的时间和日历功能
    发表于 08-16 11:17

    GD32F4系列,RTC闹钟如何设置成每天固定时间起作用?

    目前配置的只能是当天的闹钟,如何做到每天在设置的那个时间点进闹钟呢?哪位大佬帮忙解答下。GD32跟STM32不太一样,没法参照。以下是我做的闹钟代码,该如何修改成每天的闹钟。用的是库函数提供的寄存器
    发表于 01-20 11:20

    现有的BSP工程可以直接在GD32F470上进行开发吗

    大家好:有关于GD32F470的BSP工程的问题咨询,我在GD官网上查照资料了解470和450是很相似的,目前因为项目需要使用的470芯片,想使用rt-thread的操作系统,但是不知
    发表于 08-01 10:39

    移植RT-Thread BSP中GDF450工程运行在GD32F470芯片上失败如何修改

    各位好:如题,移植GD32F450的工程运行在GD32F470的芯片上,加载成功后程序会死在rt_smem_alloc函数里面的289行代码,RT_ASSERT()函数,经过调试发现感觉是因为
    发表于 11-07 14:18

    GD32F207-RTC

    单片机GD32F207学习例程之GD32F207-RTC例程源码
    发表于 06-03 15:40 15次下载

    基于GD32F307的嵌入式学习之路--RTC

    GD32F307之RTC
    发表于 11-29 16:36 10次下载
    基于<b class='flag-5'>GD32F</b>307的嵌入式学习之路--<b class='flag-5'>RTC</b>

    ---GD32 MCU---RTC使用LXTAL时钟源异常

    问题描述:客户在使用40K的内部时钟时钟发现计时异常,然后切换到LXTAL时钟,时钟停止无法运行。原因:40k时钟计数异常,是应为RTC时间存储格式是BCD,需要转换,客户没有转换
    发表于 12-02 14:51 6次下载
    ---<b class='flag-5'>GD</b>32 MCU---<b class='flag-5'>RTC</b>使用LXTAL时钟源异常

    什么是BCD

    在使用RTC外设时,我们常常会接触 BCD的概念,同时鱼鹰在介绍 USB 协议版本时也说了 BCD ,那么什么是
    的头像 发表于 09-07 09:10 1.6w次阅读

    GD32F470xx 数据表

    GD32F470xx 数据表
    发表于 02-22 18:23 2次下载
    <b class='flag-5'>GD32F470</b>xx 数据表

    芯片GD32与以太网芯片的

    GD32F470平台后,一直卡在卡在gd32fxx_enet.c中enet_phy_config,经过排查发现GD32的官方库文件也需要修改,分别为gd32f4
    的头像 发表于 01-16 08:00 1964次阅读
    芯片<b class='flag-5'>GD</b>32与以太网芯片的<b class='flag-5'>坑</b>

    GD32F470紫藤派开发板使用手册】第八讲 ADC-规则组多通道采样实验

    通过本实验主要学习以下内容: •ADC的简介 •GD32F470 ADC工作原理 •DMA原理 •规则组多通道循环采样
    的头像 发表于 05-12 10:00 709次阅读
    【<b class='flag-5'>GD32F470</b>紫藤派开发板使用手册】第八讲 ADC-规则组多通道采样实验