RTC基本定义
STM32的实时时钟(RTC)是一个独立的定时器。STM32的RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。
RTC时钟框图
RTC配置一般步骤
1、使能PWR和BKP时钟 2、使能后备寄存器访问 3、配置RTC时钟源,使能RTC时钟:如果使用LSE,要打开LSE: RCC_LSEConfig(RCC_LSE_ON); 4、设置RTC预分频系数 5、设置时间 6、开启相关中断(如果需要) 7、编写中断服务函数 8、部分操作要等待写操作完成和同步。
RTC的初始化CubeMX基本配置
1、选择时钟源有效,日历有效 2、对时钟进行初始化配置 3、配置时钟树
RTC代码编写
rtc.c文件
#include "rtc.h"
RTC_HandleTypeDef hrtc;
void RTC_Init(void)
{
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 125;
hrtc.Init.SynchPrediv = 6000;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
hrtc.Init.OutPutPullUp = RTC_OUTPUT_PULLUP_NONE;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
sTime.Hours = 0x12;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.SubSeconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
sDate.WeekDay = RTC_WEEKDAY_THURSDAY;
sDate.Month = RTC_MONTH_FEBRUARY;
sDate.Date = 0x3;
sDate.Year = 0x22;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
}
void HAL_RTC_MspInit(RTC_HandleTypeDef* rtcHandle)
{
if(rtcHandle->Instance==RTC)
{
__HAL_RCC_RTC_ENABLE();
}
}
rtc.h文件
#ifndef __RTC_H
#define __RTC_H
#include "main.h"
extern RTC_HandleTypeDef hrtc;
void RTC_Init(void);
#endif
main.c文件
#include "main.h"
#include "stdio.h"
#include "string.h"
#include "lcd.h"
#include "rtc.h"
__IO uint32_t uwTick_LCD_State_Pointer;
unsigned char Lcd_Disp_String[21];
RTC_TimeTypeDef T;
RTC_DateTypeDef D;
int main(void)
{
RTC_Init();
while (1)
{
LCD_Proc();
}
}
void LCD_Proc(void)
{
if(uwTick-uwTick_LCD_State_Pointer<100) return;
uwTick_LCD_State_Pointer=uwTick;
HAL_RTC_GetTime(&hrtc , &T , RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc , &D , RTC_FORMAT_BIN);
memset(Lcd_Disp_String,0,sizeof(Lcd_Disp_String));
sprintf((char*)Lcd_Disp_String, "Date: %02d-%02d-%02d " ,D.Year,D.Month,D.Date);
LCD_DisplayStringLine(Line0, Lcd_Disp_String);
memset(Lcd_Disp_String,0,sizeof(Lcd_Disp_String));
sprintf((char*)Lcd_Disp_String, "Time: %02d-%02d-%02d " ,T.Hours,T.Minutes,T.Seconds);
LCD_DisplayStringLine(Line1, Lcd_Disp_String);
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV3;
RCC_OscInitStruct.PLL.PLLN = 20;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART1
|RCC_PERIPHCLK_ADC12;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV32;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
|