打印
[其他ST产品]

STM32之RTC时钟,闹钟,日历

[复制链接]
895|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
RTC时钟的一些功能介绍
RTC时钟即实时时钟,它提供了用于管理所有低功耗模式的自动唤醒单元,还提供了具有可编程闹钟中断功能的日历时钟/日历。

并且可以自动将月份的天数补偿为 28、29(闰年)、30 和 31 天。并且还可以进行夏令时补偿。

中断屏蔽事件:有两个闹钟,时间戳,入侵检测,唤醒中断。

硬件上需要注意的部分
若要使用rtc功能,并且能够掉电继续工作,那么要外接纽扣电池或其他电池电源。

这里参考的是STM32F767芯片及正点的底板的设计原理图

(用BAT54C做多电源供电电路,当单片机上电时,使用VCC3.3供电,当单片机掉电时,VBAT会自动切换到BAT供电。)



使用特权

评论回复
沙发
工程师犹饿死|  楼主 | 2024-2-27 19:24 | 只看该作者
RTC框图



RTC的时钟源
​ 可以是外部低速晶振(LSE),外部高速晶振(HSE),内部低速晶振(LSI)。我们一般选用外部低速晶振(32.768kHz)作为时钟源。

RTC时钟走向
​ 先经过RTC校准寄存器(RTC_CALR)对RTC时钟进行校准;然后进入预分频寄存器(RTC_PRER)进行预分频,有两类:异步预分频(7位,默认128)、同步预分频(15位,默认256);时钟另外一个走向是预分频寄存器(WUCKSEL)这个是作为RTC唤醒定时器的时钟源。

使用特权

评论回复
板凳
工程师犹饿死|  楼主 | 2024-2-27 19:25 | 只看该作者
3个影子寄存器
时间寄存器(RTC_TR):用来初始化配置日历时间
日期寄存器(RTC_DR):用来初始化配置日历日期
亚秒寄存器(RTC_SSR):用来进一步精确时间变化
控制寄存器(RTC_CR)
用于配置RTC的功能。

使用特权

评论回复
地板
工程师犹饿死|  楼主 | 2024-2-27 19:25 | 只看该作者
RTC时钟初始化配置

RTC_HandleTypeDef RTC_Handler;  //RTC句柄

//配置RTC底层驱动和时钟
void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc)
{
    //配置RCC的时钟
    RCC_OscInitTypeDef RCC_OscInitStruct;
    //配置RCC扩展外设时钟
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;

    __HAL_RCC_PWR_CLK_ENABLE();                //使能电源时钟PWR
        HAL_PWR_EnableBkUpAccess();                //取消备份区域写保护
   
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;        //LSE配置
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;                                //不启用RCC分频
    RCC_OscInitStruct.LSEState = RCC_LSE_ON;                          //RTC使用LSE
    HAL_RCC_OscConfig(&RCC_OscInitStruct);                                                //将配置好的参数写入结构体

    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;        //外设为RTC
    PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;        //RTC时钟源为LSE
    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);                        //将配置好的参数写入结构体
        
    __HAL_RCC_RTC_ENABLE();//RTC时钟使能
}

//RTC初始化参数配置
u8 RTC_Init(void)
{      
        RTC_Handler.Instance=RTC;
        RTC_Handler.Init.HourFormat=RTC_HOURFORMAT_24;                                //RTC设置为24小时格式
        RTC_Handler.Init.AsynchPrediv=0X7F;                                           //RTC异步分频系数(1~0X7F)
        RTC_Handler.Init.SynchPrediv=0XFF;                                            //RTC同步分频系数(0~7FFF)   
        RTC_Handler.Init.OutPut=RTC_OUTPUT_DISABLE;                             //不用外部输出
        RTC_Handler.Init.OutPutPolarity=RTC_OUTPUT_POLARITY_HIGH;
        RTC_Handler.Init.OutPutType=RTC_OUTPUT_TYPE_OPENDRAIN;
    //执行初始化并检查初始化是否成功
        if(HAL_RTC_Init(&RTC_Handler)!=HAL_OK)
                return 2;

    //用备份域的寄存器DR0来标记配置标志
    if(HAL_RTCEx_BKUPRead(&RTC_Handler,RTC_BKP_DR0) != 0X5050)//是否第一次配置
    {
        RTC_Set_Time(23,59,56,RTC_HOURFORMAT12_PM);            //设置时间
        RTC_Set_Date(15,12,27,7);                                //设置日期
        HAL_RTCEx_BKUPWrite(&RTC_Handler,RTC_BKP_DR0,0X5050);        //标记已经初始化过了
    }
    return 0;
}

使用特权

评论回复
5
工程师犹饿死|  楼主 | 2024-2-27 19:25 | 只看该作者
RTC设置时间和日期


//RTC时间设置
HAL_StatusTypeDef RTC_Set_Time(u8 hour,u8 min,u8 sec,u8 ampm)
{
        RTC_TimeTypeDef RTC_TimeStructure;
        RTC_TimeStructure.Hours=hour;
        RTC_TimeStructure.Minutes=min;
        RTC_TimeStructure.Seconds=sec;
        RTC_TimeStructure.TimeFormat=ampm;        //配置12小时或24小时格式
        RTC_TimeStructure.DayLightSaving=RTC_DAYLIGHTSAVING_NONE;
        RTC_TimeStructure.StoreOperation=RTC_STOREOPERATION_RESET;
        return HAL_RTC_SetTime(&RTC_Handler,&RTC_TimeStructure,RTC_FORMAT_BIN);       
}

//RTC日期设置
HAL_StatusTypeDef RTC_Set_Date(u8 year,u8 month,u8 date,u8 week)
{
        RTC_DateTypeDef RTC_DateStructure;
        RTC_DateStructure.Date=date;
        RTC_DateStructure.Month=month;
        RTC_DateStructure.WeekDay=week;
        RTC_DateStructure.Year=year;
        return HAL_RTC_SetDate(&RTC_Handler,&RTC_DateStructure,RTC_FORMAT_BIN);
}

使用特权

评论回复
6
工程师犹饿死|  楼主 | 2024-2-27 19:25 | 只看该作者
RTC配置闹钟
配置RTC周期性唤醒定时器
void RTC_Set_WakeUp(u32 wksel,u16 cnt)
{
    __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RTC_Handler, RTC_FLAG_WUTF);//清除RTC WAKE UP的标志
       
                HAL_RTCEx_SetWakeUpTimer_IT(&RTC_Handler,cnt,wksel);            //设置重装载值和时钟
       
    HAL_NVIC_SetPriority(RTC_WKUP_IRQn,0x02,0x02); //抢占优先级1,子优先级2
    HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
}

//RTC WAKE UP中断服务函数
void RTC_WKUP_IRQHandler(void)
{
    HAL_RTCEx_WakeUpTimerIRQHandler(&RTC_Handler);
}

//RTC WAKE UP中断处理
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{
   //...........
}

使用特权

评论回复
7
工程师犹饿死|  楼主 | 2024-2-27 19:26 | 只看该作者
配置闹钟
void RTC_Set_AlarmA(u8 week,u8 hour,u8 min,u8 sec)
{
    RTC_AlarmTypeDef RTC_AlarmSturuct;
   
    RTC_AlarmSturuct.AlarmTime.Hours=hour;                          //小时
    RTC_AlarmSturuct.AlarmTime.Minutes=min;                                //分钟
    RTC_AlarmSturuct.AlarmTime.Seconds=sec;                         //秒
    RTC_AlarmSturuct.AlarmTime.SubSeconds=0;
    RTC_AlarmSturuct.AlarmTime.TimeFormat=RTC_HOURFORMAT12_AM;
   
    RTC_AlarmSturuct.AlarmMask=RTC_ALARMMASK_NONE;                //精确匹配星期,时分秒
    RTC_AlarmSturuct.AlarmSubSecondMask=RTC_ALARMSUBSECONDMASK_NONE;
    RTC_AlarmSturuct.AlarmDateWeekDaySel=RTC_ALARMDATEWEEKDAYSEL_WEEKDAY;//按星期
    RTC_AlarmSturuct.AlarmDateWeekDay=week;                         //星期
    RTC_AlarmSturuct.Alarm=RTC_ALARM_A;                             //闹钟A
    HAL_RTC_SetAlarm_IT(&RTC_Handler,&RTC_AlarmSturuct,RTC_FORMAT_BIN);
   
    HAL_NVIC_SetPriority(RTC_Alarm_IRQn,0x01,0x02);         //抢占优先级1,子优先级2
    HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
}

使用特权

评论回复
8
工程师犹饿死|  楼主 | 2024-2-27 19:26 | 只看该作者
将数据显示在LCD上

//获取时间:时分秒
HAL_RTC_GetTime(&RTC_Handler,&RTC_TimeStruct,RTC_FORMAT_BIN);

sprintf((char*)tbuf,"Time:%02d:%02d:%02d",RTC_TimeStruct.Hours,RTC_TimeStruct.Minutes,RTC_TimeStruct.Seconds);
LCD_ShowString(30,140,210,16,16,tbuf);       

//获取日期:年月日,周
HAL_RTC_GetDate(&RTC_Handler,&RTC_DateStruct,RTC_FORMAT_BIN);

sprintf((char*)tbuf,"Date:20%02d-%02d-%02d",RTC_DateStruct.Year,RTC_DateStruct.Month,RTC_DateStruct.Date);
LCD_ShowString(30,160,210,16,16,tbuf);       

sprintf((char*)tbuf,"Week:%d",RTC_DateStruct.WeekDay);
LCD_ShowString(30,180,210,16,16,tbuf);

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

75

主题

886

帖子

0

粉丝