历史上的今天
今天是: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();
}
史海拾趣
|
在很多时候都要谈及的抗干扰,干扰来自何方啊!我个人认为30%被干扰了的设备都是电源被干扰造成的.我以前最早做过一个抗干扰的小东西就是给绞肉机(听起来很恐怖,是做火腿肠的)做的换向器,开始我说你就弄仨按钮完事了,结果对方告诉我,原来工大的给做了 ...… 查看全部问答> |
|
本帖最后由 paulhyde 于 2014-9-15 09:29 编辑 在5月22日新闻发布会上,王越院士表示“今年我们开始强调两个方面的应用。第一个就是做出来的产品的性能价格比应该是比较好的。不能为完成一个比较简单的任务,用一个非常复杂,非常昂贵的小系统合和 ...… 查看全部问答> |
|
平台:s3c2440 + wince5.0 在串口驱动文件pdds3c2440_ser.cpp中 void CPdd2440Uart::XmitInterruptHandler(PUCHAR pTxBuffer, ULONG *pBuffLen) { ...... for (DWORD dwByteWrite=0; dwByteWriteWrite ...… 查看全部问答> |
|
//驱动中write函数 对物理地址WR_ADDR写 0x1234abcd ssize_t regs_op_write( struct file *filp, char *buf, size_t count, loff_t *f_pos) { char *tmp; ...… 查看全部问答> |
















