stm32f10x_rtc
RTC(Real-Time Clock)外设是STM32F10x系列微控制器中的实时时钟模块,提供精确的时间计数和闹钟功能。该外设具有独立的时钟源,在系统掉电后仍能保持时间计数,支持秒中断、闹钟中断和溢出中断。RTC外设广泛应用于需要时间戳、定时唤醒、闹钟提醒等功能的嵌入式系统中。
数据类型定义
RTC中断定义
#define RTC_IT_OW ((uint16_t)0x0004) /* 溢出中断 */
#define RTC_IT_ALR ((uint16_t)0x0002) /* 闹钟中断 */
#define RTC_IT_SEC ((uint16_t)0x0001) /* 秒中断 */说明:
RTC_IT_OW:RTC计数器溢出中断,当32位计数器溢出时触发RTC_IT_ALR:RTC闹钟中断,当计数器值等于闹钟值时触发RTC_IT_SEC:RTC秒中断,每秒触发一次
RTC标志位定义
#define RTC_FLAG_RTOFF ((uint16_t)0x0020) /* RTC操作关闭标志 */
#define RTC_FLAG_RSF ((uint16_t)0x0008) /* 寄存器同步标志 */
#define RTC_FLAG_OW ((uint16_t)0x0004) /* 溢出标志 */
#define RTC_FLAG_ALR ((uint16_t)0x0002) /* 闹钟标志 */
#define RTC_FLAG_SEC ((uint16_t)0x0001) /* 秒标志 */说明:
RTC_FLAG_RTOFF:RTC操作关闭标志,表示RTC当前不可访问RTC_FLAG_RSF:寄存器同步标志,表示RTC寄存器已同步RTC_FLAG_OW:溢出标志,表示RTC计数器已溢出RTC_FLAG_ALR:闹钟标志,表示闹钟事件已发生RTC_FLAG_SEC:秒标志,表示秒事件已发生
RTC寄存器定义
STM32F10x RTC外设包含以下主要寄存器:
// RTC控制寄存器
#define RTC_CRH ((uint16_t)0x0000) /* RTC控制寄存器高字节 */
#define RTC_CRL ((uint16_t)0x0001) /* RTC控制寄存器低字节 */
// RTC预分频器寄存器
#define RTC_PRLH ((uint16_t)0x0002) /* RTC预分频器寄存器高字节 */
#define RTC_PRLL ((uint16_t)0x0003) /* RTC预分频器寄存器低字节 */
// RTC分频器寄存器
#define RTC_DIVH ((uint16_t)0x0004) /* RTC分频器寄存器高字节 */
#define RTC_DIVL ((uint16_t)0x0005) /* RTC分频器寄存器低字节 */
// RTC计数器寄存器
#define RTC_CNTH ((uint16_t)0x0006) /* RTC计数器寄存器高字节 */
#define RTC_CNTL ((uint16_t)0x0007) /* RTC计数器寄存器低字节 */
// RTC闹钟寄存器
#define RTC_ALRH ((uint16_t)0x0008) /* RTC闹钟寄存器高字节 */
#define RTC_ALRL ((uint16_t)0x0009) /* RTC闹钟寄存器低字节 */标准库函数详解
1. RTC_ITConfig
/**
* @brief 使能/屏蔽 RTC 中断源(秒、闹钟、溢出),配合 NVIC 实现定时唤醒或事件响应
* @param RTC_IT: 要配置的RTC中断
* 该参数可以是以下值之一:
* @arg RTC_IT_OW: 溢出中断
* @arg RTC_IT_ALR: 闹钟中断
* @arg RTC_IT_SEC: 秒中断
* @param NewState: 中断的新状态
* 该参数可以是以下值之一:
* @arg ENABLE: 使能中断
* @arg DISABLE: 禁用中断
* @retval 无
* @example
* RTC_ITConfig(RTC_IT_SEC, ENABLE);
*/
void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);功能说明:
- 可单独打开秒中断(每秒节拍)、闹钟中断(定时唤醒)或溢出中断
- 使能后还需在 NVIC 中配置 RTC_IRQn 才能进入中断服务程序
- 修改中断使能后建议调用 RTC_WaitForLastTask 等待写入完成
2. RTC_EnterConfigMode
/**
* @brief 进入 RTC 配置模式,解锁对预分频器、计数器、闹钟等寄存器的写访问
* @param 无
* @retval 无
* @example
* RTC_EnterConfigMode();
*/
void RTC_EnterConfigMode(void);功能说明:
- 修改 PRL、CNT、ALR 等寄存器前必须先调用
- 与 RTC_ExitConfigMode 成对使用,退出后寄存器受硬件保护
- 通常配合 PWR_BackupAccessCmd(ENABLE) 和备份域时钟使能
3. RTC_ExitConfigMode
/**
* @brief 退出 RTC 配置模式,锁定寄存器并使新配置生效
* @param 无
* @retval 无
* @example
* RTC_ExitConfigMode();
*/
void RTC_ExitConfigMode(void);功能说明:
- 完成 SetCounter/SetPrescaler/SetAlarm 后必须调用
- 退出后 RTC 硬件开始按新配置计数
- 建议随后调用 RTC_WaitForLastTask 确认写操作完成
4. RTC_GetCounter
/**
* @brief 读取 RTC 32 位计数器当前值,即自上电/复位以来累计的秒数
* @param 无
* @retval RTC计数器的32位值
* @example
* uint32_t counter = RTC_GetCounter();
*/
uint32_t RTC_GetCounter(void);功能说明:
- 返回值即当前时间戳(秒),可换算为时分秒
- 读取前应调用 RTC_WaitForSynchro 确保寄存器已同步
- 32 位计数器约 136 年溢出,需配合 RTC_IT_OW 处理
5. RTC_SetCounter
/**
* @brief 设置 RTC 计数器初值,用于校时或系统上电后初始化时间基准
* @param CounterValue: 要设置的计数器值
* @retval 无
* @example
* RTC_SetCounter(0);
*/
void RTC_SetCounter(uint32_t CounterValue);功能说明:
- 须在 RTC_EnterConfigMode 与 RTC_ExitConfigMode 之间调用
- 写入后调用 RTC_WaitForLastTask 等待硬件完成
- 常用于首次上电将计数器归零或写入已知时间戳
6. RTC_SetPrescaler
/**
* @brief 设置 RTC 预分频器,将 LSE/LSI 时钟分频为 1 Hz 秒节拍
* @param PrescalerValue: 预分频器值,范围0-0xFFFFF
* @retval 无
* @example
* RTC_SetPrescaler(32767);
*/
void RTC_SetPrescaler(uint32_t PrescalerValue);功能说明:
- 预分频值 = 输入时钟频率 − 1(LSE 32.768 kHz 时设为 32767)
- 须在配置模式下调用,通常只在初始化时设置一次
- 分频正确后 RTC 计数器每秒递增 1
7. RTC_SetAlarm
/**
* @brief 设置 RTC 闹钟匹配值,计数器等于该值时触发闹钟中断
* @param AlarmValue: 闹钟值
* @retval 无
* @example
* RTC_SetAlarm(3600);
*/
void RTC_SetAlarm(uint32_t AlarmValue);功能说明:
- 须在配置模式下调用,AlarmValue 为绝对计数值而非相对延时
- 配合 RTC_ITConfig(RTC_IT_ALR, ENABLE) 实现定时唤醒
- 触发后需在中断中清除挂起位,可重新设置下一次闹钟
8. RTC_GetDivider
/**
* @brief 读取 RTC 分频器当前计数值,反映当前秒内亚秒级进度
* @param 无
* @retval RTC分频器的32位值
* @example
* uint32_t divider = RTC_GetDivider();
*/
uint32_t RTC_GetDivider(void);功能说明:
- 分频器从预分频值向下计数到 0 时产生秒脉冲
- 可用于亚秒精度时间推算或调试 RTC 分频状态
- 读取前建议先等待 RTC_WaitForSynchro
9. RTC_WaitForLastTask
/**
* @brief 阻塞等待 RTC 最后一次写操作完成(RTOFF 标志置位)
* @param 无
* @retval 无
* @example
* RTC_SetCounter(0);
* RTC_WaitForLastTask();
*/
void RTC_WaitForLastTask(void);功能说明:
- 每次写 RTC 寄存器后应调用,确保数据已写入备份域
- 轮询 RTC_FLAG_RTOFF,为 SET 时表示可继续下一次操作
- 连续多次写操作之间不可省略此等待
10. RTC_WaitForSynchro
/**
* @brief 等待 RTC 寄存器与 APB 总线同步(RSF 标志置位),读寄存器前必须调用
* @param 无
* @retval 无
* @example
* RTC_WaitForSynchro();
*/
void RTC_WaitForSynchro(void);功能说明:
- 复位后、从待机唤醒后或切换 RTC 时钟源后必须调用
- 轮询 RTC_FLAG_RSF,为 SET 后方可安全读取 CNT 等寄存器
- 通常在 RCC_RTCCLKCmd 使能后作为初始化第一步
11. RTC_GetFlagStatus
/**
* @brief 查询 RTC 标志位状态(同步、溢出、闹钟、秒事件等)
* @param RTC_FLAG: 要检查的RTC标志
* 该参数可以是以下值之一:
* @arg RTC_FLAG_RTOFF: RTC操作关闭标志
* @arg RTC_FLAG_RSF: 寄存器同步标志
* @arg RTC_FLAG_OW: 溢出标志
* @arg RTC_FLAG_ALR: 闹钟标志
* @arg RTC_FLAG_SEC: 秒标志
* @retval 标志状态
* 该返回值可以是以下值之一:
* @arg SET: 标志已设置
* @arg RESET: 标志已清除
* @example
* FlagStatus flag = RTC_GetFlagStatus(RTC_FLAG_SEC);
*/
FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG);功能说明:
- 用于轮询方式检测秒/闹钟/溢出事件,无需中断
- RTOFF 和 RSF 常用于初始化流程中的同步等待
- 返回 SET 表示对应事件已发生
12. RTC_ClearFlag
/**
* @brief 清除 RTC 事件标志(溢出、闹钟、秒),轮询模式下处理完事件后调用
* @param RTC_FLAG: 要清除的RTC标志
* 该参数可以是以下值之一:
* @arg RTC_FLAG_OW: 溢出标志
* @arg RTC_FLAG_ALR: 闹钟标志
* @arg RTC_FLAG_SEC: 秒标志
* @retval 无
* @example
* RTC_ClearFlag(RTC_FLAG_SEC);
*/
void RTC_ClearFlag(uint16_t RTC_FLAG);功能说明:
- 仅清除标志位,不影响中断使能配置
- 轮询 RTC_FLAG_SEC 等标志后必须清除,否则会重复触发
- 不可用于清除 RTOFF/RSF 等硬件状态标志
13. RTC_GetITStatus
/**
* @brief 查询 RTC 中断挂起状态,用于中断服务程序中判断中断源
* @param RTC_IT: 要检查的RTC中断
* 该参数可以是以下值之一:
* @arg RTC_IT_OW: 溢出中断
* @arg RTC_IT_ALR: 闹钟中断
* @arg RTC_IT_SEC: 秒中断
* @retval 中断状态
* 该返回值可以是以下值之一:
* @arg SET: 中断已挂起
* @arg RESET: 中断未挂起
* @example
* ITStatus status = RTC_GetITStatus(RTC_IT_SEC);
*/
ITStatus RTC_GetITStatus(uint16_t RTC_IT);功能说明:
- 在 RTC_IRQHandler 中区分秒、闹钟、溢出中断源
- 返回 SET 表示该中断已挂起且已使能
- 处理完毕后须调用 RTC_ClearITPendingBit 清除
14. RTC_ClearITPendingBit
/**
* @brief 清除 RTC 中断挂起位,防止同一中断重复进入
* @param RTC_IT: 要清除的RTC中断
* 该参数可以是以下值之一:
* @arg RTC_IT_OW: 溢出中断
* @arg RTC_IT_ALR: 闹钟中断
* @arg RTC_IT_SEC: 秒中断
* @retval 无
* @example
* RTC_ClearITPendingBit(RTC_IT_SEC);
*/
void RTC_ClearITPendingBit(uint16_t RTC_IT);功能说明:
- 必须在中断服务程序末尾调用,否则中断会反复触发
- 同时会清除对应的事件标志位
- 三个中断源须分别判断、分别清除
使用示例
基本RTC初始化示例
#include "stm32f10x.h"
void RTC_Init_Example(void)
{
// 使能PWR和BKP时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
// 使能对备份寄存器和RTC的访问
PWR_BackupAccessCmd(ENABLE);
// 使能LSE作为RTC时钟源
RCC_LSEConfig(RCC_LSE_ON);
// 等待LSE稳定
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
// 选择LSE作为RTC时钟源
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
// 使能RTC时钟
RCC_RTCCLKCmd(ENABLE);
// 等待RTC寄存器同步
RTC_WaitForSynchro();
// 等待最后一个写操作完成
RTC_WaitForLastTask();
// 进入配置模式
RTC_EnterConfigMode();
// 设置预分频器(LSE = 32.768kHz,预分频器 = 32768-1 = 32767)
RTC_SetPrescaler(32767);
// 设置初始时间(秒)
RTC_SetCounter(0);
// 退出配置模式
RTC_ExitConfigMode();
// 等待最后一个写操作完成
RTC_WaitForLastTask();
}RTC秒中断示例
#include "stm32f10x.h"
volatile uint32_t seconds = 0;
void RTC_SecondInterrupt_Example(void)
{
// 初始化RTC(参考上面的初始化代码)
RTC_Init_Example();
// 使能RTC秒中断
RTC_ITConfig(RTC_IT_SEC, ENABLE);
// 使能NVIC中断
NVIC_EnableIRQ(RTC_IRQn);
// 等待最后一个写操作完成
RTC_WaitForLastTask();
}
// RTC中断服务程序
void RTC_IRQHandler(void)
{
if(RTC_GetITStatus(RTC_IT_SEC) == SET)
{
// 秒中断处理
seconds++;
// 清除中断挂起位
RTC_ClearITPendingBit(RTC_IT_SEC);
}
}RTC闹钟示例
#include "stm32f10x.h"
void RTC_Alarm_Example(void)
{
// 初始化RTC(参考上面的初始化代码)
RTC_Init_Example();
// 进入配置模式
RTC_EnterConfigMode();
// 设置闹钟在60秒后触发
RTC_SetAlarm(60);
// 退出配置模式
RTC_ExitConfigMode();
// 使能RTC闹钟中断
RTC_ITConfig(RTC_IT_ALR, ENABLE);
// 使能NVIC中断
NVIC_EnableIRQ(RTC_IRQn);
// 等待最后一个写操作完成
RTC_WaitForLastTask();
}
// RTC中断服务程序
void RTC_IRQHandler(void)
{
if(RTC_GetITStatus(RTC_IT_ALR) == SET)
{
// 闹钟中断处理
// 执行闹钟相关操作
// 清除中断挂起位
RTC_ClearITPendingBit(RTC_IT_ALR);
}
}时间获取和设置示例
#include "stm32f10x.h"
// 获取当前时间(秒)
uint32_t RTC_GetTime(void)
{
return RTC_GetCounter();
}
// 设置当前时间(秒)
void RTC_SetTime(uint32_t time)
{
// 进入配置模式
RTC_EnterConfigMode();
// 设置时间
RTC_SetCounter(time);
// 退出配置模式
RTC_ExitConfigMode();
// 等待最后一个写操作完成
RTC_WaitForLastTask();
}
// 时间转换函数(秒转时分秒)
void RTC_SecondsToTime(uint32_t seconds, uint8_t *hours, uint8_t *minutes, uint8_t *secs)
{
*hours = (seconds / 3600) % 24;
*minutes = (seconds / 60) % 60;
*secs = seconds % 60;
}
// 时间转换函数(时分秒转秒)
uint32_t RTC_TimeToSeconds(uint8_t hours, uint8_t minutes, uint8_t secs)
{
return hours * 3600 + minutes * 60 + secs;
}注意事项
- 时钟源选择:RTC可以使用LSE(32.768kHz)或LSI作为时钟源,LSE精度更高
- 预分频器设置:预分频器值 = 输入时钟频率 - 1,确保得到1Hz的时钟
- 配置模式:修改RTC配置寄存器前必须进入配置模式
- 同步等待:读取RTC寄存器前应等待同步完成
- 中断处理:在中断服务程序中必须清除中断挂起位
- 备份域访问:使用RTC前必须使能备份域访问权限
- 时间精度:RTC时间精度取决于时钟源的稳定性
- 溢出处理:32位计数器约136年后溢出,需要处理溢出事件
总结
STM32F10x RTC外设提供了完整的实时时钟功能,支持精确的时间计数、闹钟功能和多种中断。通过独立的时钟源,RTC在系统掉电后仍能保持时间计数,为嵌入式系统提供可靠的时间基准。RTC外设广泛应用于需要时间戳、定时唤醒、闹钟提醒等功能的系统中。在使用时需要注意正确的初始化顺序、时钟源选择和中断处理,确保RTC功能的稳定运行。