历史上的今天
返回首页

历史上的今天

今天是:2024年11月01日(星期五)

正在发生

2021年11月01日 | stm32专题三十三:RTC实时时钟

2021-11-01 来源:eefocus

RTC功能描述


实时时钟是一个独立的定时器。RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。


RTC模块和时钟配置系统(RCC_BDCR寄存器)处于后备区域,即在系统复位或从待机模式唤醒后,RTC的设置和时间维持不变。


系统复位后,对后备寄存器和RTC的访问被禁止,这是为了防止对后备区域(BKP)的意外写操作。执行以下操作将使能对后备寄存器和RTC的访问:


设置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备接口时钟;

设置寄存器PWR_CR的DBP位,使能对后备寄存器和RTC的访问;

为什么时间不能超过1秒?


其实是对RTCCLK进行分频,比如RTCCLK为32768Hz,那最大可用的分频也就是(32767 + 1),此时计数频率 TR_CLK = 32768 / (32767 + 1)= 1Hz,计数时间为1秒。如果分频系数再增大,如设置为(49999 + 1),那么计数频率 TR_CLK = 32768 / ((49999 + 1)= 0.65536 Hz,这肯定出错。所以,TR_CLK最小为 1Hz,再小就成小数了。


RTC时钟源:

RTC结构框图

访问后备区域:

RTC寄存器的配置过程

RTC寄存器说明


中断配置:

控制寄存器:

RTC预分频寄存器 RTC_PRL

预分频余数寄存器 RTC_DIV

RTC 计数器寄存器 


RTC核有一个32位可编程的计数器,可通过两个16位的寄存器访问。计数器以预分频器产生的TR_CLK时间基准为参考进行计数。RTC_CNT寄存器用来存放计数器的计数值。他们受RTC_CR的位RTOFF写保护,仅当RTOFF值为’1’时,允许写操作。在高或低寄存器(RTC_CNTH或RTC_CNTL)上的写操作,能够直接装载到相应的可编程计数器,并且重新装载RTC预分频器。当进行读操作时,直接返回计数器内的计数值(系统时间)。

闹钟寄存器


Unix时间戳


Unix时间戳网站服务:

RTC库函数


RTC使用的标准库函数也很简单,直接看源代码:


1 等待时钟同步和操作完成:


/**

  * @brief  Waits until the RTC registers (RTC_CNT, RTC_ALR and RTC_PRL)

  *   are synchronized with RTC APB clock.

  * @note   This function must be called before any read operation after an APB reset

  *   or an APB clock stop.

  * @param  None

  * @retval None

  */

void RTC_WaitForSynchro(void)

{

  /* Clear RSF flag */

  RTC->CRL &= (uint16_t)~RTC_FLAG_RSF;

  /* Loop until RSF flag is set */

  while ((RTC->CRL & RTC_FLAG_RSF) == (uint16_t)RESET)

  {

  }

}


2 等待上一次对RTC的操作完成:


/**

  * @brief  Waits until last write operation on RTC registers has finished.

  * @note   This function must be called before any write to RTC registers.

  * @param  None

  * @retval None

  */

void RTC_WaitForLastTask(void)

{

  /* Loop until RTOFF flag is set */

  while ((RTC->CRL & RTC_FLAG_RTOFF) == (uint16_t)RESET)

  {

  }

}

3 使能备份区域寄存器和RTC配置(在 PWR 里面)

/**

  * @brief  Enables or disables access to the RTC and backup registers.

  * @param  NewState: new state of the access to the RTC and backup registers.

  *   This parameter can be: ENABLE or DISABLE.

  * @retval None

  */

void PWR_BackupAccessCmd(FunctionalState NewState)

{

  /* Check the parameters */

  assert_param(IS_FUNCTIONAL_STATE(NewState));

  *(__IO uint32_t *) CR_DBP_BB = (uint32_t)NewState;

}

4 进入和退出RTC模式(主要被其他函数调用)


/**

  * @brief  Enters the RTC configuration mode.

  * @param  None

  * @retval None

  */

void RTC_EnterConfigMode(void)

{

  /* Set the CNF flag to enter in the Configuration Mode */

  RTC->CRL |= RTC_CRL_CNF;

}

 

/**

  * @brief  Exits from the RTC configuration mode.

  * @param  None

  * @retval None

  */

void RTC_ExitConfigMode(void)

{

  /* Reset the CNF flag to exit from the Configuration Mode */

  RTC->CRL &= (uint16_t)~((uint16_t)RTC_CRL_CNF); 

}

5 设置 RTC 时钟分频(直接把分频系数写入高16位和低16位)


/**

  * @brief  Sets the RTC prescaler value.

  * @param  PrescalerValue: RTC prescaler new value.

  * @retval None

  */

void RTC_SetPrescaler(uint32_t PrescalerValue)

{

  /* Check the parameters */

  assert_param(IS_RTC_PRESCALER(PrescalerValue));

  

  RTC_EnterConfigMode();

  /* Set RTC PRESCALER MSB word */

  RTC->PRLH = (PrescalerValue & PRLH_MSB_MASK) >> 16;

  /* Set RTC PRESCALER LSB word */

  RTC->PRLL = (PrescalerValue & RTC_LSB_MASK);

  RTC_ExitConfigMode();

}

6 设置、获取计数值和闹钟


/**

  * @brief  Sets the RTC counter value.

  * @param  CounterValue: RTC counter new value.

  * @retval None

  */

void RTC_SetCounter(uint32_t CounterValue)

  RTC_EnterConfigMode();

  /* Set RTC COUNTER MSB word */

  RTC->CNTH = CounterValue >> 16;

  /* Set RTC COUNTER LSB word */

  RTC->CNTL = (CounterValue & RTC_LSB_MASK);

  RTC_ExitConfigMode();

}

 

/**

  * @brief  Gets the RTC counter value.

  * @param  None

  * @retval RTC counter value.

  */

uint32_t RTC_GetCounter(void)

{

  uint16_t tmp = 0;

  tmp = RTC->CNTL;

  return (((uint32_t)RTC->CNTH << 16 ) | tmp) ;

}

 

/**

  * @brief  Sets the RTC alarm value.

  * @param  AlarmValue: RTC alarm new value.

  * @retval None

  */

void RTC_SetAlarm(uint32_t AlarmValue)

{  

  RTC_EnterConfigMode();

  /* Set the ALARM MSB word */

  RTC->ALRH = AlarmValue >> 16;

  /* Set the ALARM LSB word */

  RTC->ALRL = (AlarmValue & RTC_LSB_MASK);

  RTC_ExitConfigMode();

}

推荐阅读

史海拾趣

C&K Components公司的发展小趣事

进入新时代,C&K继续坚持创新驱动的发展战略,不断加大在研发和创新方面的投入。公司紧跟行业趋势,积极探索新技术、新工艺和新应用,推出了一系列具有创新性和领先性的开关产品。同时,C&K也注重与客户的沟通和合作,深入了解客户需求,提供个性化的解决方案和优质的服务。这些举措使C&K在激烈的市场竞争中始终保持领先地位,并赢得了更多客户的认可和支持。

这些故事展示了C&K Components公司在电子行业中的发展历程和取得的成就。从初创时期的坚持与探索,到60年代的转型与突破,再到90年代的行业领先地位确立,以及千禧年代的并购与融合和新时代的创新与发展,C&K始终保持着对技术的热爱和对市场的敏锐洞察,不断推动公司向前发展。

Acutechnology公司的发展小趣事

Acutechnology公司自XXXX年创立之初,便专注于电子技术的研发与创新。创始团队由一群富有经验的电子工程师组成,他们对市场趋势有着敏锐的洞察力。在初创期,公司集中资源投入到一项具有前瞻性的技术研发项目中,经过多次试验和改进,最终成功开发出了一款具有竞争力的电子产品,为公司的后续发展奠定了坚实的技术基础。

EiKO Global LLC公司的发展小趣事

随着智能家居和物联网技术的兴起,EiKO开始积极探索智能照明系统的研发与应用。公司投入大量研发资源,将传统照明产品与智能控制技术相结合,推出了具有远程控制、定时开关、色温调节等功能的智能照明系统。

这些智能照明系统不仅提高了用户的使用体验,还为用户带来了更加便捷和智能的生活方式。例如,用户可以通过手机APP远程控制家中的照明设备,实现定时开关和色温调节等功能;同时,智能照明系统还可以与智能家居系统相连接,实现与其他智能设备的联动控制。

EPC公司的发展小趣事

某EPC公司在电子行业中以技术创新为核心竞争力。在早期阶段,公司专注于研发高效的电子制造技术和工艺,通过不断的技术突破,成功降低了生产成本,提高了产品质量。随着技术的不断成熟和应用,公司逐渐在行业内树立了技术领先的形象,吸引了众多客户的合作。通过与知名企业的合作,公司不断拓展市场份额,实现了快速发展。

Crowd Supply公司的发展小趣事

在Crowd Supply平台上线不久,一家专注于智能家居设备的初创公司选择在这里发起众筹。这个项目凭借其独特的设计和前瞻性的功能,迅速吸引了大量关注。经过一段时间的筹备和宣传,该项目成功筹集到了所需的资金,并顺利进入了生产阶段。这一成功案例不仅为Crowd Supply赢得了良好的口碑,也为其后续的发展奠定了坚实的基础。

Big-Sun Electronics Co Ltd公司的发展小趣事

品质是Big-Sun Electronics Co Ltd公司一直以来的核心竞争力。公司建立了严格的质量管理体系,从原材料采购到生产流程控制,再到产品出厂检验,每一个环节都严格把关。同时,Big-Sun还注重品牌建设,通过广告宣传和客户服务,不断提升品牌知名度和美誉度。

问答坊 | AI 解惑

对于工业环境干扰的一点想法

在很多时候都要谈及的抗干扰,干扰来自何方啊!我个人认为30%被干扰了的设备都是电源被干扰造成的.我以前最早做过一个抗干扰的小东西就是给绞肉机(听起来很恐怖,是做火腿肠的)做的换向器,开始我说你就弄仨按钮完事了,结果对方告诉我,原来工大的给做了 ...…

查看全部问答>

王越院士畅谈2009年NEC电子杯出题理念

本帖最后由 paulhyde 于 2014-9-15 09:29 编辑 在5月22日新闻发布会上,王越院士表示“今年我们开始强调两个方面的应用。第一个就是做出来的产品的性能价格比应该是比较好的。不能为完成一个比较简单的任务,用一个非常复杂,非常昂贵的小系统合和 ...…

查看全部问答>

自动绕线工具Specctra指南

很好的呀@和大家一起分享下…

查看全部问答>

如何判断仪表返回的数据有多少位?

通过串口发送指令,不知道返回的数据有多少位?难道末位有特殊的结束符吗?…

查看全部问答>

如何判断串口数据发送完毕

平台:s3c2440 + wince5.0 在串口驱动文件pdds3c2440_ser.cpp中 void    CPdd2440Uart::XmitInterruptHandler(PUCHAR pTxBuffer, ULONG *pBuffLen) {     ......     for (DWORD dwByteWrite=0; dwByteWriteWrite ...…

查看全部问答>

请问,cpld中也能设定rom嘛?

请问,cpld中也能设定rom嘛?    看过 fpga的可以,不知道cpld的怎么样啊  …

查看全部问答>

iar442不能设置断点是怎么回事啊?

                                 rt…

查看全部问答>

LPC1100大家族

LPC1100家族不断庞大,期待未来更多的型号。 …

查看全部问答>

求救:字附型驱动write函数传入的char×型数据有问题

//驱动中write函数 对物理地址WR_ADDR写 0x1234abcd ssize_t regs_op_write( struct file *filp, char *buf,                 size_t count, loff_t *f_pos) {         char *tmp; ...…

查看全部问答>

怎样消除接触电阻的影响

谁能告诉我如果使用低值精密电阻采样,怎么才能消除接触电阻的影响?感谢!…

查看全部问答>